Чтобы отсортировать список материалов в слотах материалов объекта в Blender нужным образом, например, по алфавиту, мы можем воспользоваться созданной нами ранее функцией перестановки материалов в слотах.
Для начала создадим список имен всех материалов текущего активного объекта.
1 2 3 |
mat_names = [_mat.name for _mat in bpy.context.active_object.data.materials] # ['red', 'green', 'blue', 'cyan'] |
Как мы видим, порядок расположения имен материалов соответствует порядку расположения материалов в слотах.
Отсортируем его по алфавиту, чтобы получить список в требуемом нам порядке.
1 2 3 |
mat_names.sort() # ['blue', 'cyan', 'green', 'red'] |
Индекс имени материала в отсортированном списке соответствует нужному нам порядковому номеру — на этом месте он и должен располагаться в слотах материалов объекта.
Следовательно, мы можем получить для каждого материала нужный индекс, куда его поставить, просто пройдя по списку с использованием функции enumerate().
1 |
for _slot_to_idx, mat_name in enumerate(mat_names): |
Нам остается для каждого материала определить индекс, где он находится в списке слотов материалов сейчас. После чего мы можем вызвать нашу функцию, указав оба индекса, для перестановки материалов в слотах местами. Таким образом материал встает на «свое» место.
Найдем текущий индекс материала по его имени:
1 2 3 |
slot_from_idx = next((_idx + _slot_to_idx for _idx, _material in enumerate(bpy.context.object.data.materials[_slot_to_idx:]) if _material.name == mat_name), None) |
На каждом проходе цикла один материал, начиная с начала списка (сверху в списке слотов) становится на свое место. Поэтому для поиска материала мы используем срез, начиная с текущей итерации цикла, чтобы не проверять материалы, уже стоящие корректно на своих слотах.
1 |
bpy.context.object.data.materials[_slot_to_idx:] |
Выбирая из этого среза материал с текущим именем, мы получаем его индекс, дополнительно прибавляя к индексу число итерации цикла, чтобы учесть срез.
Получив три входных параметра для нашей функции:
- объект — bpy.context.object
- индекс, откуда переставить материал — slot_from_idx
- и индекс куда его переставить — slot_to_idx
мы можем вызвать функцию перестановки материалов.
1 2 |
if slot_from_idx: switch_materials(bpy.context.object, slot_from_idx, _slot_to_idx) |
После того как мы пройдем весь цикл по материалам, все материалы в слотах будут выстроены по алфавиту.
Весь код:
1 2 3 4 5 6 7 8 9 |
mat_names = [_mat.name for _mat in bpy.context.active_object.data.materials] mat_names.sort() for _slot_to_idx, mat_name in enumerate(mat_names): slot_from_idx = next((_idx + _slot_to_idx for _idx, _material in enumerate(bpy.context.object.data.materials[_slot_to_idx:]) if _material.name == mat_name), None) if slot_from_idx: switch_materials(bpy.context.object, slot_from_idx, _slot_to_idx) |