Wie füge ich allen Objekten einer bestimmten Sammlung einen Spiegelmodifikator hinzu?

Nov 29 2020

Ich möchte jedem Objekt einer bestimmten Sammlung einen Spiegelmodifikator hinzufügen.

Das Problem ist, dass der Modifikator nur dem letzten Objekt hinzugefügt wird, das sogar mehrmals denselben Modifikator erhält, und ich weiß nicht warum:

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

F: Wie füge ich allen Objekten einer bestimmten Sammlung einen Spiegelmodifikator hinzu?

Antworten

3 Psyonic Nov 29 2020 at 10:25

Du bist besser dran, sie bpy.data.objectszu manipulieren. Auf diese Weise müssen Sie sich nicht auf die Auswahl verlassen. Sie benötigen lediglich den Objektnamen.

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

Verwenden Sie für Operatoren den Kontext.

Unter der selfAnnahme im Fragencode, dass Sie einen Operator schreiben

Nach der Antwort von @RoufirHassan zur Erläuterung wurde das aktive Objekt nicht geändert, indem die Sammlungsobjekte durchlaufen wurden, die die Auswahl aufgehoben und einzelne ausgewählt hatten. Das Hinzufügen context.objectzur Druckanweisung würde dies bestätigen.

Ist das aktive Objekt und das nullte ausgewählte Objekt immer gleich?

Um dies zu beheben, setzen Sie das aktive Objekt auf das Schleifenobjekt, bevor Sie den Operator aufrufen.

context.view_layer.objects.active = obj

Blender 2.8 API, Python, aktives Objekt festlegen

Ein Problem hierbei wäre jedoch, dass Skripte dazu neigen, sich schrecklich zu verlangsamen, wenn viele Operatoren wiederholt werden. Die Anzahl der Operatorläufe unter Verwendung des geänderten Fragencodes beträgt 2 x Anzahl der Objekte in der Sammlung.

Der Operator zum Hinzufügen von Modifikatoren wird am Ende des Modifikatorstapels hinzugefügt

Wenn Sie den Operator "Modifikatoren hinzufügen" verwenden, wird der neu hinzugefügte Modifikator verwendet

context.object.modifiers[-1]

dh der letzte. Wiederum kann die Verwendung von Namen im Mixer zwielichtig sein, genau wie bei Objekten, bei denen ein anderes mit demselben Namen hinzugefügt wird, nicht denselben Namen haben.

Hauptkandidat für KeyError

Verwenden bpy.data.whatevers["Foo"]Sie es nur, wenn Sie sicher sind, dass "Foo" vorhanden ist. Wo es einen Wert haben kann NoneEmpfehlen Sie auch die Verwendung von Szenenobjekten, da das Objekt in bpy.data.objectsnicht mit der Szene verknüpft ist und wahrscheinlich nicht wie erwartet funktioniert.

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

oder benutze den Kontext. In diesem Fall kann die Sammlung beispielsweise eine Kontextsammlung (zuletzt im Outliner ausgewählt) und das Modifikatorziel seincontext.object

Kontext überschreiben

Kann ein Kontextwörterbuch an Operatoren übergeben. Nachfolgend finden Sie eine Methode, die von @RoufirHassan mithilfe von Override erläutert wird . Hinweis: Dadurch werden alle Modifikatoren des ersten Netzobjekts in der Sammlung (einschließlich des neu hinzugefügten Spiegels) zu allen anderen Netzobjekten in der Sammlung hinzugefügt, mit Ausnahme des Spiegelziels, wenn es sich um ein Netzobjekt in derselben Sammlung handelt

Dadurch werden nur 2 Operatoren ausgeführt, unabhängig davon, wie viele Objekte sich in der Sammlung befinden.

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-Methoden.

Schließlich würde ich empfehlen, die API-Methode zu verwenden, wie in der Antwort von @Pysonic vorgeschlagen , außer den Kontext zum Festlegen des Erfassungs- und Modifikatorziels zu verwenden.

1 RoufirHasan Nov 29 2020 at 09:50

Wählen Sie alle Netze in Ihrer Sammlung aus und fügen Sie einen Spiegelmodifikator hinzu.

Wie Sie bereits sagten, wird nur das aktive Objekt gespiegelt (aktives Objekt = letztes ausgewähltes Objekt mit verschiedenfarbigem Umriss). Um jedes einzelne Objekt zu spiegeln, geben Sie einfach ( Ctrl+ L) > Modifikatoren ein . Es werden alle Objekte mit demselben Modifikator verknüpft.

Sie können es für alle anderen Modifikatoren verwenden.