Сортирует материалы на меше
Сортирует материалы на меше
1import bpy
2import re
3from collections import defaultdict
4
5def extract_id(material_name):
6 """Извлекает числовой ID из имени материала"""
7 match = re.match(r'id(\d{1,3})_', material_name)
8 return int(match.group(1)) if match else None
9
10def process_mesh(obj):
11 """Основная функция обработки меша"""
12 print(f"\nОбработка объекта: {obj.name}")
13
14
15 material_assignments = {
16 'polygons': defaultdict(list),
17 'edges': defaultdict(list),
18 'vertices': defaultdict(list)
19 }
20
21
22 for poly in obj.data.polygons:
23 if poly.material_index < len(obj.material_slots):
24 mat_name = obj.material_slots[poly.material_index].material.name
25 material_assignments['polygons'][mat_name].append(poly.index)
26
27
28 if hasattr(obj.data, 'edges'):
29 for edge in obj.data.edges:
30 if hasattr(edge, 'material_index'):
31 if edge.material_index < len(obj.material_slots):
32 mat_name = obj.material_slots[edge.material_index].material.name
33 material_assignments['edges'][mat_name].append(edge.index)
34
35
36 if hasattr(obj.data, 'vertices'):
37 for vert in obj.data.vertices:
38 if hasattr(vert, 'material_index'):
39 if vert.material_index < len(obj.material_slots):
40 mat_name = obj.material_slots[vert.material_index].material.name
41 material_assignments['vertices'][mat_name].append(vert.index)
42
43
44 materials = {}
45 for i, slot in enumerate(obj.material_slots):
46 if slot.material:
47 materials[slot.material.name] = {
48 'material': slot.material,
49 'original_index': i
50 }
51
52
53 materials_with_id = []
54 materials_without_id = []
55
56 for mat_data in materials.values():
57 mat = mat_data['material']
58 if extract_id(mat.name) is not None:
59 materials_with_id.append(mat)
60 else:
61 materials_without_id.append(mat)
62
63
64 materials_with_id_sorted = sorted(materials_with_id, key=lambda x: extract_id(x.name))
65 materials_without_id_sorted = sorted(materials_without_id, key=lambda x: x.name.lower())
66 final_materials = materials_with_id_sorted + materials_without_id_sorted
67
68
69 name_to_new_index = {mat.name: i for i, mat in enumerate(final_materials)}
70
71
72 obj.data.materials.clear()
73 for mat in final_materials:
74 obj.data.materials.append(mat)
75
76
77
78 for mat_name, poly_indices in material_assignments['polygons'].items():
79 if mat_name in name_to_new_index:
80 new_index = name_to_new_index[mat_name]
81 for poly_idx in poly_indices:
82 obj.data.polygons[poly_idx].material_index = new_index
83
84
85 if hasattr(obj.data, 'edges'):
86 for mat_name, edge_indices in material_assignments['edges'].items():
87 if mat_name in name_to_new_index:
88 new_index = name_to_new_index[mat_name]
89 for edge_idx in edge_indices:
90 obj.data.edges[edge_idx].material_index = new_index
91
92
93 if hasattr(obj.data, 'vertices'):
94 for mat_name, vert_indices in material_assignments['vertices'].items():
95 if mat_name in name_to_new_index:
96 new_index = name_to_new_index[mat_name]
97 for vert_idx in vert_indices:
98 obj.data.vertices[vert_idx].material_index = new_index
99
100 print(f"Уникальных материалов: {len(final_materials)}")
101 return len(final_materials)
102
103
104if __name__ == "__main__":
105 selected_objects = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
106 if not selected_objects:
107 print("Ошибка: Не выбрано ни одного меша!")
108 else:
109
110 prev_mode = bpy.context.object.mode if bpy.context.object else 'OBJECT'
111 if prev_mode != 'OBJECT':
112 bpy.ops.object.mode_set(mode='OBJECT')
113
114 total_processed = 0
115 for obj in selected_objects:
116 total_processed += process_mesh(obj)
117
118
119 if prev_mode != 'OBJECT':
120 bpy.ops.object.mode_set(mode=prev_mode)
121
122 print(f"\nОбработка завершена! Обработано объектов: {len(selected_objects)}, материалов: {total_processed}")