特定のコレクションのすべてのオブジェクトにミラー修飾子を追加するにはどうすればよいですか?

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

Q:特定のコレクションのすべてのオブジェクトにミラー修飾子を追加するにはどうすればよいですか?

回答

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

演算子の場合はコンテキストを使用します。

self質問コードで与えられた、あなたが演算子を書いていると仮定して

説明としての@RoufirHassanの回答に加えて、コレクションオブジェクトの選択を解除して単一を選択することをループしても、アクティブオブジェクトは変更されませんでした。context.objectprintステートメントに追加すると、これが確認されます。

アクティブオブジェクトと0番目に選択されたオブジェクトは常に同じですか?

修正するには、演算子を呼び出す前に、アクティブオブジェクトをループオブジェクトに設定します。

context.view_layer.objects.active = obj

Blender 2.8 API、python、アクティブオブジェクトを設定

ただし、ここでの問題は、多くの演算子をループすると、スクリプトの速度が大幅に低下する傾向があることです。修正された質問コードを使用したオペレーターの実行カウントは、コレクション内のオブジェクトの数の2倍になります。

修飾子追加演算子は、修飾子スタックの最後に追加します

修飾子追加演算子を使用する場合、新しく追加された修飾子は次のようになります。

context.object.modifiers[-1]

つまり、最後のもの。繰り返しますが、blenderで名前を使用するのは危険です。同じ名前で別のオブジェクトを追加するオブジェクトと同じように、同じ名前はありません。

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メソッド。

最後に、@ Pysonicの回答で提案されているAPIメソッドを使用することをお勧めします。ただし、コンテキストを使用してコレクションと修飾子のターゲットを設定する場合を除きます。

1 RoufirHasan Nov 29 2020 at 09:50

コレクション内のすべてのメッシュを選択し、ミラーモディファイヤを追加します。

しかし、あなたが言ったように、それはアクティブなオブジェクトのみをミラーリングします(アクティブなオブジェクト=異なる色のアウトラインで選択された最後のオブジェクト)。したがって、すべてのオブジェクトをミラーリングするには、(Ctrl+ L>修飾子を入力するだけです。すべてのオブジェクトを同じ修飾子でリンクします。

他の修飾子に使用できます。