initial commit

This commit is contained in:
iron 2022-10-23 02:24:06 +01:00
parent 4963053dd1
commit 5967a2cb98
4 changed files with 175 additions and 3 deletions

View File

@ -1,3 +1,9 @@
# Simple-Material-Flattener The user interface is created in the "right" panel in the 3D View
This panel is normally closed, so it must be opened (+) to be seen.
This plugin looks through materials in selected objects, and if they're simple enough (a single texture) then it attempts to consolidate all materials sharing that texture and keep the faces that materials were assigned to.
I want to take ripped assets that have many duplicate materials
and combine them all into a single material.
This plugin looks through materials in selected objects, and if they're simple enough (a single texture) then it attempts to consolidate all materials sharing that texture and keep the faces that materials were assigned to.
This does NOT keep shader settings, and should be used on objects that are imported with default-ish materials like obj rips.

54
__init__.py Normal file
View File

@ -0,0 +1,54 @@
# /bin/python
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#----------------------------------------------------------
# File __init__.py
#----------------------------------------------------------
bl_info = {
"name" : "Simple Material Flattener",
"author" : "Irssss sssssson",
"description" : "",
"blender" : (3, 3, 1),
"version" : (0, 0, 1),
"location" : "View3D &gt; N Panel &gt; Misc.",
"warning" : "",
"category" : "Material"
}
if "bpy" in locals():
from importlib import reload
reload(operators)
reload(panel)
else:
from . import operators
from . import panel
import bpy
from bpy.types import Scene
classes = (
operators.SMF_OT_flatten_materials,
panel.SMF_PT_Panel
)
def register():
for c in classes:
bpy.utils.register_class(c)
def unregister():
for c in reversed(classes):
bpy.utils.unregister_class(c)

99
operators.py Normal file
View File

@ -0,0 +1,99 @@
import bpy
import bpy.ops
from bpy.types import Operator
class SMF_OT_flatten_materials(Operator):
bl_idname = 'scene.flatten_materials'
bl_label = 'Flatten materials'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return True
def execute(self, context):
# self.scene = context.scene
# bpy.context.selected_objects
# object.material_slots[0].material.node_tree.nodes (list)
# bpy.ops.object.material_slot_select()
# bpy.ops.object.mode_set(mode='EDIT') (mode='OBJECT)
# bpy.types.ShaderNodeTexImage() ???
selected_objects = [i for i in bpy.context.selected_objects]
store_selected_objects = selected_objects.copy()
last_image = None
#select none
bpy.ops.object.select_all(action='DESELECT')
for o in selected_objects:
imageMaterialNames = {}
print("gettings materials from %s" % o.name)
# select this object
o.select_set(True)
# switch to edit mode
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
for slot in o.material_slots:
nodes = slot.material.node_tree.nodes
# Check to not break more complex materials
if not self.CheckIsSimpleMaterial(nodes):
print("not simple enough")
continue
image = self.getImage(nodes)
if not last_image: last_image = image
if last_image == image:
o.active_material_index = slot.slot_index
bpy.ops.object.material_slot_select()
continue
# materials are not the same: Finish up last image and start again
if last_image in imageMaterialNames:
print("re-assigning materials")
print("Hard Mode")
# select other material's mesh # active material index bpy.data.objects["name"].active_material_index : INT
o.active_material_index = o.material_slots[imageMaterialNames[last_image]].slot_index
# assign to this slot # bpy.ops.object.material_slot_assign()
bpy.ops.object.material_slot_assign()
else:
print("new texture path: %s" % last_image.filepath)
imageMaterialNames[last_image] = o.material_slots[o.active_material_index].name
bpy.ops.object.material_slot_assign()
bpy.ops.mesh.select_all(action='DESELECT')
last_image = image
# select this material
o.active_material_index = slot.slot_index
# select this materials faces
bpy.ops.object.material_slot_select()
bpy.ops.object.material_slot_assign()
# switch to object mode
bpy.ops.object.mode_set(mode='OBJECT')
# remove unused slots
bpy.ops.object.material_slot_remove_unused()
# reselect all
for o in selected_objects:
o.select_set(True)
return {'FINISHED'}
def getImage(self, nodes):
for node in nodes:
if node.type == 'TEX_IMAGE':
return node.image
else:
return False
def CheckIsSimpleMaterial(self, nodes):
if len(nodes) != 3: return False
else: return True

13
panel.py Normal file
View File

@ -0,0 +1,13 @@
from bpy.types import Panel
class SMF_PT_Panel(Panel):
bl_idname = "VIEW3D_PT_simple_material_flattener_331"
bl_label = "Simple Material Flattener"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
row = layout.row()
col = row.column()
self.layout.operator("scene.flatten_materials", text="Flatten materials")