Comment ajouter un modificateur de miroir à tous les objets d'une certaine collection?

Nov 29 2020

Je voudrais ajouter un modificateur de miroir à chaque objet d'une certaine collection.

Le problème est que le modificateur ne sera ajouté qu'au dernier objet qui reçoit même le même modificateur plusieurs fois et je ne sais pas pourquoi:

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

Q: Comment ajouter un modificateur de miroir à tous les objets d'une certaine collection?

Réponses

3 Psyonic Nov 29 2020 at 10:25

Vous feriez mieux bpy.data.objectsde les manipuler. De cette façon, vous n'avez pas besoin de vous fier à ce qui est sélectionné, tout ce dont vous avez besoin est le nom des objets.

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

Pour les opérateurs, utilisez le contexte.

Étant donné le selfcode de la question, en supposant que vous écrivez un opérateur

Suite à la réponse de @RoufirHassan en guise d'explication, faire une boucle sur les objets de la collection, désélectionner et sélectionner un seul, ne changeait pas l'objet actif. L'ajout context.objectd'une déclaration imprimée le confirmerait.

L'objet actif et l'objet sélectionné à zéro sont-ils toujours les mêmes?

pour corriger, définissez l'objet actif sur l'objet de boucle avant d'appeler l'opérateur.

context.view_layer.objects.active = obj

API Blender 2.8, python, définir un objet actif

Cependant, un problème ici serait que les scripts ont tendance à ralentir horriblement s'ils bouclent beaucoup d'opérateurs. Le nombre d'exécutions de l'opérateur utilisant le code de question modifié serait de 2 x le nombre d'objets dans la collection.

L'opérateur d'ajout de modificateur ajoute à la fin de la pile de modificateurs

si vous utilisez l'opérateur d'ajout de modificateurs, le modificateur nouvellement ajouté sera

context.object.modifiers[-1]

c'est-à - dire le dernier. Encore une fois dans Blender, utiliser le nom peut être douteux, tout comme avec des objets, ajouter un autre avec le même nom n'aura pas le même nom.

Premier candidat pour KeyError

Ne jamais utiliser bpy.data.whatevers["Foo"]sauf si vous êtes certain que "Foo" existe. Où il peut avoir de la valeur NoneRecommandez également d'utiliser des objets de scène, comme si l'objet dans bpy.data.objectsn'est pas lié à la scène, il ne fonctionnera probablement pas comme prévu.

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

ou utilisez le contexte. Dans ce cas par exemple, la collection peut être une collection de contexte (dernière sélection dans outliner) et la cible du modificateur peut êtrecontext.object

Contexte de remplacement

Peut transmettre un dictionnaire de contexte aux opérateurs. Ci-dessous, la méthode expliquée par @RoufirHassan utilisant le remplacement. Remarque: cela ajoutera tous les modificateurs du premier objet de maillage de la collection (y compris le miroir nouvellement ajouté) à tous les autres objets de maillage de la collection, sauf à la cible du miroir s'il s'agit d'un objet de maillage de la même collection

Cela n'exécutera que 2 opérateurs, quel que soit le nombre d'objets dans la collection.

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éthodes API.

Enfin, je recommanderais d'utiliser la méthode API comme suggéré dans la réponse de @Pysonic , sauf d'utiliser le contexte pour définir la cible de la collection et du modificateur.

1 RoufirHasan Nov 29 2020 at 09:50

Sélectionnez tous les maillages de votre collection et ajoutez un modificateur de miroir.

Mais comme vous l'avez dit, il ne reflétera que l'objet actif (objet actif = dernier objet sélectionné avec un contour de couleur différente). Donc, pour refléter chaque objet, tapez simplement ( Ctrl+ L) > modifiers . Il liera tous les objets avec le même modificateur.

Vous pouvez l'utiliser pour tous les autres modificateurs.