Получить все доступные шейдерные ноды в виде списка можно по их типу.
Для начала, добавим в сцену любой объект, например – куб, создадим для него материал и удалим из него все ноды. Сюда, в этот материал, мы выведем все имеющиеся в Blender ноды шейдеров.
Получить все доступные типы шейдерных нодов можно с помощью структуры “bpy.types”. В ней хранится список всех доступных в API Blender типов объектов, в том числе и нодов.
Выполнив команду
1 2 3 |
dir(bpy.types) # 'ANIM_OT_clear_useless_actions', 'ANIM_OT_keying_set_export', 'ANIM_OT_update_animated_transform_constraints', 'Action', ... |
мы получим список имен всех доступных в API типов объектов.
Все типы нодов шейдеров наследуются от типа “ShaderNode”. Следовательно, для того, чтобы получить из общего списка только типы нодов, нужно проверить не наследуется ли конкретный тип от “ShaderNode”.
Проверку наследования одного типа от другого можно выполнить при помощи команды
1 |
issubclass(_CHECK_TYPE_, _PARENT_TYPE_) |
она вернет True, если тип _CHECK_TYPE_ наследуется от типа _PARENT_TYPE_.
Функция “issubclass” сравнивает типы а не их текстовые представления, которые мы получили с помощью функции “dir”. Чтобы получить сам тип по его текстовому имени воспользуемся тем, что в Python любой тип является одновременно и атрибутом модуля, в котором он описан. Следовательно, получить тип, описанный в “bpy.types” можно с помощью команды:
1 |
getattr(bpy.types, _TEXT_TYPE_) |
Имея список типов нодов, можно добавить в текущий материал сами ноды по их типу.
Указатель на текущее нодовое дерево, сюда мы будем добавлять ноды, можно получить следующим образом:
1 2 3 |
import bpy node_tree = bpy.context.object.active_material.node_tree |
Зададим начальные значения для расположения нодов.
1 2 |
location_x = 0 location_y = 0 |
Пройдем по всем возможным типам объектов API:
1 2 |
for type in dir(bpy.types): real_type = getattr(bpy.types, type) |
и если тип наследуется от “ShaderNode”
1 |
if issubclass(real_type, bpy.types.ShaderNode): |
добавим нод этого типа в нодовое дерево, задав для него ширину и смещение.
1 2 3 4 5 6 7 |
node = node_tree.nodes.new(type) node.width = 250 node.location = (location_x, location_y) location_x += 300 if location_x > 3000: location_x = 0 location_y -= 600 |
Финальный код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import bpy node_tree = bpy.context.object.active_material.node_tree location_x = 0 location_y = 0 for type in dir(bpy.types): real_type = getattr(bpy.types, type) if issubclass(real_type, bpy.types.ShaderNode): try: node = node_tree.nodes.new(type) node.width = 250 node.location = (location_x, location_y) location_x += 300 if location_x > 3000: location_x = 0 location_y -= 600 except: pass |
Часть кода, добавляющего нод в нодовое дерево, заключим в блок try – except, чтобы предотвратить ошибки при попытках создать абстрактный нод, не имеющий представления, например тот же “ShaderNode”.
После выполнения данного кода в материал будут последовательно добавлены все доступные ноды.