Как добавить модификатор зеркала ко всем объектам определенной коллекции?

Nov 29 2020

Я бы хотел добавить модификатор зеркала к каждому объекту определенной коллекции.

Проблема в том, что модификатор будет добавлен только к последнему объекту, который даже получит один и тот же модификатор несколько раз, и я не знаю почему:

 def add_empty_collection(self):
    for obj in bpy.data.collections['my_collection'].all_objects:
        print("obj_: ", obj)
        bpy.ops.object.select_all(action='DESELECT') # Deselecting all
        obj.select_set(True)
        bpy.ops.object.modifier_add(type='MIRROR')
        bpy.context.object.modifiers["Mirror"].use_axis[0] = False
        bpy.context.object.modifiers["Mirror"].use_axis[1] = True
        bpy.context.object.modifiers["Mirror"].use_axis[2] = False
        bpy.context.object.modifiers["Mirror"].mirror_object = bpy.data.objects["target"]

В: Как добавить модификатор зеркала ко всем объектам определенной коллекции?

Ответы

3 Psyonic Nov 29 2020 at 10:25

Лучше использовать, bpy.data.objectsчтобы ими манипулировать. Таким образом, вам не нужно полагаться на то, что выбрано, все, что вам нужно, это имя объекта.

import bpy

mod_name = 'My-Mirror-Modifier'

for obj in bpy.data.collections["My-Collection"].all_objects:
    if obj.type == 'MESH':
        mod = obj.modifiers.new(mod_name, 'MIRROR')
        mod.use_axis[0] = False
        mod.use_axis[1] = True
        mod.use_axis[2] = False
        mod.mirror_object = bpy.data.objects["Light"]
2 batFINGER Nov 30 2020 at 12:47

Для операторов используйте context.

Учитывая selfкод в вопросе, предполагая, что вы пишете оператор

В дополнение к ответу @RoufirHassan в качестве объяснения, цикл по объектам коллекции, отменяющий выбор и выбор одного, не изменял активный объект. Добавление context.objectв выписку для печати подтвердит это.

Всегда ли активный объект и нулевой выбранный объект одинаковы?

чтобы исправить, установите активный объект в объект цикла перед вызовом оператора.

context.view_layer.objects.active = obj

Blender 2.8 API, python, установить активный объект

Однако проблема здесь в том, что скрипты имеют тенденцию к ужасному замедлению, если в цикле выполняется большое количество операторов. Счетчик запусков оператора с использованием измененного кода вопроса будет равен 2-кратному количеству объектов в коллекции.

Оператор добавления модификатора добавляет в конец стека модификаторов

при использовании оператора добавления модификаторов вновь добавленный модификатор будет

context.object.modifiers[-1]

т.е. последний. Еще раз, в блендере использование имени может быть изворотливым, точно так же, как с объектами, добавляющими другое с тем же именем, не будет иметь того же имени.

Главный кандидат на KeyError

Никогда не используйте, bpy.data.whatevers["Foo"]если вы не уверены, что "Foo" существует. Где он может иметь значение. NoneТакже рекомендуется использовать объекты сцены, так как если объект bpy.data.objectsне связан со сценой, он, скорее всего, не будет работать должным образом.

target = context.scene.objects.get("Foo")

или используйте контекст. В этом случае, например, коллекция может быть контекстной коллекцией (последней выбранной в планировщике), а цель модификатора может бытьcontext.object

Превалирующий контекст

Может передавать операторам контекстный словарь. Ниже приведен метод, объясненный @RoufirHassan с использованием переопределения. Примечание: это добавит все модификаторы первого объекта сетки в коллекции (включая недавно добавленное зеркало) ко всем другим объектам сетки в коллекции, за исключением цели зеркала, если это объект сетки в той же коллекции

При этом будут выполняться только 2 оператора, независимо от того, сколько объектов в коллекции.

import bpy

context = bpy.context

coll = context.collection
ob = context.object

mesh_obs = [o for o in coll.all_objects 
        if o.type == 'MESH'
        and o is not ob]


if mesh_obs:
    ao = mesh_obs.pop(0)
    bpy.ops.object.modifier_add(
            {"object" : ao},
            type='MIRROR'
            )
    mod = ao.modifiers[-1]
    mod.use_axis = (True, False, True)
    mod.mirror_object = ob
    bpy.ops.object.make_links_data(
            {"object" : ao,
             "selected_editable_objects": mesh_obs
             },
             type='MODIFIERS',
             )

Методы API.

Наконец, я бы рекомендовал использовать метод API, как предложено в ответе @Pysonic , за исключением использования контекста для установки целевого объекта коллекции и модификатора.

1 RoufirHasan Nov 29 2020 at 09:50

Выделите все меши в своей коллекции и добавьте модификатор зеркала.

Но, как вы сказали, он будет отражать только активный объект (активный объект = последний объект, выбранный с другим цветным контуром). Поэтому, чтобы отразить каждый объект, просто введите ( Ctrl+ L) > модификаторы . Он свяжет все объекты с одним и тем же модификатором.

Вы можете использовать его для любых других модификаторов.