Jak dodać modyfikator lustra do wszystkich obiektów w określonej kolekcji?

Nov 29 2020

Chciałbym dodać modyfikator lustra do każdego obiektu z określonej kolekcji.

Problem w tym, że modyfikator zostanie dodany tylko do ostatniego obiektu, który nawet kilka razy dostaje ten sam modyfikator i nie wiem dlaczego:

 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: Jak dodać modyfikator lustra do wszystkich obiektów w określonej kolekcji?

Odpowiedzi

3 Psyonic Nov 29 2020 at 10:25

Lepiej jest użyć ich bpy.data.objectsdo manipulowania nimi. W ten sposób nie musisz polegać na tym, co jest zaznaczone, wystarczy tylko nazwa obiektu.

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

Dla operatorów użyj kontekstu.

Biorąc pod uwagę selfw kodzie pytania, zakładając, że piszesz operator

W nawiązaniu do odpowiedzi @RoufirHassan w celu wyjaśnienia, zapętlanie się po obiektach kolekcji odznaczanie i wybieranie pojedynczych, nie zmieniało aktywnego obiektu. Dodanie context.objectdo wydruku oświadczenia mogłoby to potwierdzić.

Czy obiekt aktywny i obiekt zaznaczony jako zerowy zawsze są takie same?

naprawić ustaw obiekt aktywny na obiekt pętli przed wywołaniem operatora.

context.view_layer.objects.active = obj

Blender 2.8 API, python, ustaw aktywny obiekt

Jednak problemem byłoby to, że skrypty mają tendencję do strasznego zwalniania, jeśli zapętlają wiele operatorów. Liczba uruchomień operatora przy użyciu zmienionego kodu pytania wyniosłaby 2 x liczba obiektów w kolekcji.

Operator add modyfikatora dodaje na koniec stosu modyfikatorów

jeśli używasz modyfikatorów add operator, to nowo dodany modyfikator będzie

context.object.modifiers[-1]

czyli ostatni. Ponownie w blenderze użycie nazwy może być podejrzane, tak jak w przypadku obiektów o tej samej nazwie nie będzie miało tej samej nazwy.

Główny kandydat na KeyError

Nigdy nie używaj, bpy.data.whatevers["Foo"]jeśli nie masz pewności, że istnieje „Foo”. Gdzie może to mieć wartość NoneZalecamy również używanie obiektów sceny, tak jakby obiekt bpy.data.objectsnie był powiązany ze sceną, prawdopodobnie nie będzie działał zgodnie z oczekiwaniami.

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

lub użyj kontekstu. W tym przypadku na przykład kolekcja może być kolekcją kontekstową (ostatnio wybraną w programie outliner), a celem modyfikatora może byćcontext.object

Nadrzędny kontekst

Może przekazywać słownik kontekstowy do operatorów. Poniżej znajduje się wyjaśnienie metody @RoufirHassan za pomocą zastąpienia. Uwaga: spowoduje to dodanie wszystkich modyfikatorów pierwszego obiektu siatki w kolekcji (w tym nowo dodanego lustra) do wszystkich innych obiektów siatki w kolekcji, z wyjątkiem celu odbicia lustrzanego, jeśli jest to obiekt siatkowy w tej samej kolekcji

Spowoduje to uruchomienie tylko 2 operatorów, niezależnie od liczby obiektów w kolekcji.

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

Metody API.

Na koniec poleciłbym użycie metody API, jak zasugerowano w odpowiedzi @Pysonic , z wyjątkiem używania kontekstu do ustawiania celu kolekcji i modyfikatora.

1 RoufirHasan Nov 29 2020 at 09:50

Wybierz wszystkie siatki w swojej kolekcji i dodaj modyfikator lustra.

Ale jak powiedziałeś, będzie to odzwierciedlać tylko aktywny obiekt (aktywny obiekt = ostatni wybrany obiekt z innym kolorowym konturem). Aby więc odzwierciedlić każdy obiekt, wystarczy wpisać ( Ctrl+ L) > modyfikatory . Połączy wszystkie obiekty z tym samym modyfikatorem.

Możesz go użyć do dowolnych innych modyfikatorów.