シーン内のすべてのライトを*効率的に*見つける方法は?
カスタムUIリストに現在のシーンにあるすべてのライトを入力したいのですが、これを行うための最良の方法がわかりません。繰り返してbpy.context.scene.objects
検証object.type == 'LIGHT'
し、フィルターobjects[i].data
をかけて実際の光を取得することもできますが、特にオブジェクトが多数あるシーンでは、不格好でパフォーマンスが悪いと感じます。
理想的にはbpy.data.lights
、各ライトが使用されているシーンに基づいて、このはるかに小さなデータセットをドリルダウンしてフィルタリングしたいと思います。しかし、ライトが与えられたbpy.data.lights
場合、それを使用しているオブジェクトをどのように見つけ、そこからこのオブジェクトのuser_scene
属性を確認できますか?これは、バジリオンのオブジェクトのdata
属性をトップダウンで繰り返すよりもはるかに高速であると私は思いますが、ライトからそれを使用しているオブジェクトにボトムアップで移動するメカニズムがある場合、私はできませんAPIで見つけてください。StackExchangeの賢い人、アイデアはありますか?
これがDOHである場合、多くの感謝と謝罪!ある種の質問ですが、私はこれに不慣れで、まだ暗闇の中で自分の道を感じています。
回答
それらをコレクションに入れる
IMOは、これを行う最も簡単な方法は、提案されているとおりです。
scene_lights = [ob for ob in scene.objects if ob.type == 'LIGHT']
1つのライトオブジェクトは、シーン内のライトのいずれかまたはすべてと同じライトデータを持つことができます。ライトが少ない場合でも、データがシーン内のオブジェクトに属していることを確認すると、上記よりも効率が低下する可能性があります。
シーン内にオブジェクトが多すぎて反復処理が非効率的であると思われる場合は、nameまたはIDプロパティを使用してそれらをコレクションにリンクし、コレクションにライトオブジェクト用としてタグを付けることを検討してください。
lightcol = bpy.data.collections.get("Lights")
if not lightcol:
lightcol = bpy.data.collections.new("Lights")
scene.collection.children.link(lightcol) # or wherever
# populate it.
for lt in scene_lights:
lightcol.objects.link(lt)
このコレクション内にコレクションを作成して、ライトタイプでさらに分類することができます
ポーリングされたPointerProperty
@brockmannが述べたように、マテリアルの例である、ポーリングされたポインタプロパティの使用も検討できます。
UILayout.prop_searchへのカスタム検索データ
一方、ライトの場合、ポインタプロパティタイプはbpy.types.Object
、であり、pollメソッドはタイプに対してテストします。ライトタイプにも簡単に拡張可能
以下のスクリプトを使用してください。
import bpy
light_set = set(bpy.data.lights.keys())
obj_set = set(bpy.data.objects.keys())
# light data doesn't update by deleting:
light_set.intersection_update(obj_set)
light_objects = [bpy.data.objects[name] for name in light_set]