¿Cómo agregar un modificador de espejo a todos los objetos de una determinada colección?

Nov 29 2020

Me gustaría agregar un modificador de espejo a cada objeto de una colección determinada.

El problema es que el modificador solo se agregará al último objeto que incluso obtiene el mismo modificador varias veces y no sé por qué:

 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"]

P: ¿Cómo agregar un modificador de espejo a todos los objetos de una colección determinada?

Respuestas

3 Psyonic Nov 29 2020 at 10:25

Es mejor usarlos bpy.data.objectspara manipularlos. De esta manera, no necesita depender de lo que está seleccionado, todo lo que necesita es el nombre de los objetos.

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

Para los operadores, use el contexto.

Dado el selfen el código de la pregunta, suponiendo que está escribiendo un operador

Además de la respuesta de @RoufirHassan a modo de explicación, recorrer los objetos de colección deseleccionando y seleccionando solo, no estaba cambiando el objeto activo. Agregar context.objecta la declaración impresa confirmaría esto.

¿El objeto activo y el objeto seleccionado cero son siempre iguales?

para arreglar, establezca el objeto activo en el objeto de bucle antes de llamar al operador.

context.view_layer.objects.active = obj

Blender 2.8 API, python, establecer objeto activo

Sin embargo, un problema aquí sería que los scripts tienen una tendencia a ralentizarse horriblemente si se repiten muchos operadores. El recuento de ejecuciones del operador utilizando el código de pregunta modificado sería 2 x número de objetos en la colección.

El operador de adición de modificador se agrega al final de la pila de modificadores

si usa el operador de adición de modificadores, el modificador recién agregado será

context.object.modifiers[-1]

es decir, el último. Una vez más, en Blender, usar el nombre puede ser complicado, al igual que con los objetos, agregar otro con el mismo nombre no tendrá el mismo nombre.

Candidato principal para KeyError

Nunca lo use a bpy.data.whatevers["Foo"]menos que esté seguro de que "Foo" existe. Dónde puede tener valor NoneTambién recomiende el uso de objetos de escena, ya que si el objeto en bpy.data.objectsno está vinculado a la escena, probablemente no funcionará como se esperaba.

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

o usa el contexto. En este caso, por ejemplo, la colección puede ser una colección de contexto (la última seleccionada en el esquema) y el objetivo del modificador puede sercontext.object

Contexto primordial

Puede pasar un diccionario de contexto a los operadores. A continuación se muestra el método explicado por @RoufirHassan mediante la anulación. Nota: esto agregará todos los modificadores del primer objeto de malla en la colección (incluido el espejo recién agregado) a todos los demás objetos de malla en la colección, excepto al objetivo del espejo si es un objeto de malla en la misma colección

Esto ejecutará solo 2 operadores sin importar cuántos objetos haya en la colección.

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',
             )

Métodos API.

Finalmente, recomendaría usar el método API como se sugiere en la respuesta de @Pysonic , excepto que use el contexto para establecer la colección y el objetivo del modificador.

1 RoufirHasan Nov 29 2020 at 09:50

Seleccione todas las mallas de su colección y agregue un modificador de espejo.

Pero como dijiste, solo reflejará el objeto activo (objeto activo = último objeto seleccionado con un contorno de color diferente). Entonces, para reflejar cada objeto, simplemente escriba ( Ctrl+ L) > modificadores . Vinculará todos los objetos con el mismo modificador.

Puede usarlo para otros modificadores.