Material Combiner Improvements

This commit is contained in:
Yusarina
2024-07-25 22:10:45 +01:00
parent 83366072b8
commit 61dbd7a79f
2 changed files with 32 additions and 38 deletions
+21 -28
View File
@@ -1,7 +1,7 @@
import bpy
import re
from typing import List, Tuple, Optional, Set
from bpy.types import Material, Operator, Context, Object
from typing import List, Tuple, Optional, Set, Dict
from bpy.types import Material, Operator, Context, Object, NodeTree
from ..core.common import clean_material_names, get_selected_armature, is_valid_armature, get_all_meshes
from ..core.register import register_wrap
from ..functions.translations import t
@@ -21,31 +21,30 @@ def copy_tex_nodes(mat1: Material, mat2: Material) -> None:
node2.mapping = node1.mapping
node2.projection = node1.projection
def consolidate_textures(mat1: Material, mat2: Material) -> None:
if mat1.node_tree and mat2.node_tree:
for node1 in mat1.node_tree.nodes:
def consolidate_textures(node_tree1: NodeTree, node_tree2: NodeTree) -> None:
for node1 in node_tree1.nodes:
if node1.type == 'TEX_IMAGE':
if node1.node_tree:
consolidate_textures(node1.node_tree, mat2.node_tree)
for node2 in mat2.node_tree.nodes:
for node2 in node_tree2.nodes:
if (node2.type == 'TEX_IMAGE' and
node1.image == node2.image):
consolidate_nodes(node1, node2)
node2.image = node1.image
copy_tex_nodes(mat1, mat2)
elif node1.type == 'GROUP':
if node1.node_tree and node2.node_tree:
consolidate_textures(node1.node_tree, node2.node_tree)
def color_match(col1: Tuple[float, float, float, float], col2: Tuple[float, float, float, float], tolerance: float = 0.01) -> bool:
return abs(col1[0] - col2[0]) < tolerance
return all(abs(c1 - c2) < tolerance for c1, c2 in zip(col1, col2))
def materials_match(mat1: Material, mat2: Material, tolerance: float = 0.01) -> bool:
if not color_match(mat1.diffuse_color, mat2.diffuse_color, tolerance):
return False
if mat1.roughness != mat2.roughness:
if abs(mat1.roughness - mat2.roughness) > tolerance:
return False
consolidate_textures(mat1, mat2)
if mat1.node_tree and mat2.node_tree:
consolidate_textures(mat1.node_tree, mat2.node_tree)
return True
@@ -53,9 +52,6 @@ def get_base_name(name: str) -> str:
mat_match = re.match(r"^(.*)\.\d{3}$", name)
return mat_match.group(1) if mat_match else name
def report_consolidated(self: Operator, num_combined: int) -> None:
self.report({'INFO'}, f"Combined {num_combined} materials")
@register_wrap
class CombineMaterials(Operator):
bl_idname = "avatar_toolkit.combine_materials"
@@ -83,9 +79,9 @@ class CombineMaterials(Operator):
return {'CANCELLED'}
self.consolidate_materials(meshes)
self.remove_unused_materials()
self.cleanmatslots()
self.clean_material_slots(meshes)
self.clean_material_names()
self.clear_unused_data_blocks()
return {'FINISHED'}
@@ -102,25 +98,19 @@ class CombineMaterials(Operator):
base_mat: Material = mat_mapping[base_name]
try:
if materials_match(base_mat, mat):
consolidate_textures(base_mat, mat)
consolidate_textures(base_mat.node_tree, mat.node_tree)
num_combined += 1
slot.material = base_mat
except AttributeError:
# Skip this material if there's an attribute mismatch
self.report({'WARNING'}, t("Optimization.material_attribute_mismatch").format(material_name=mat.name))
continue
else:
mat_mapping[base_name] = mat
self.report({'INFO'}, t("Optimization.materials_combined").format(num_combined=num_combined))
def remove_unused_materials(self) -> None:
for mat in bpy.data.materials:
if not any(obj for obj in bpy.data.objects if obj.material_slots and mat.name in obj.material_slots):
bpy.data.materials.remove(mat, do_unlink=True)
def cleanmatslots(self) -> None:
for obj in bpy.data.objects:
if obj.type == 'MESH':
def clean_material_slots(self, meshes: List[Object]) -> None:
for obj in meshes:
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.material_slot_remove_unused()
@@ -130,3 +120,6 @@ class CombineMaterials(Operator):
for obj in bpy.data.objects:
if obj.type == 'MESH':
clean_material_names(obj)
def clear_unused_data_blocks(self) -> None:
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
+1
View File
@@ -52,6 +52,7 @@
"Optimization.processing_mesh_no_shapekeys": "Processing mesh with no shapekeys named \"{mesh_name}\"",
"Optimization.remove_doubles_completed": "Remove doubles operation completed",
"Optimization.select_armature": "Please select an armature",
"Optimization.material_attribute_mismatch": "Attribute mismatch in material {material_name}, skipping",
"Tools.select_armature": "Please select an armature",
"Tools.label": "Tools",
"Tools.tools_title.label": "Tools:",