Wie finde ich * effizient * alle Lichter in einer Szene?
Ich möchte eine benutzerdefinierte UI-Liste mit allen Lichtern in der aktuellen Szene füllen, bin mir aber nicht sicher, wie ich das am besten machen kann. Wir könnten iterieren bpy.context.scene.objects
und validieren object.type == 'LIGHT'
, um Dinge herauszufiltern und dann zu verwenden objects[i].data
, um das tatsächliche Licht zu erhalten, aber das scheint mir klobig und nicht performant zu sein, insbesondere für Szenen mit einer großen Anzahl von Objekten.
Idealerweise möchte ich bpy.data.lights
diesen viel kleineren Datensatz anhand der Szene (n), in der jedes Licht verwendet wird, untersuchen und dann filtern. Aber bpy.data.lights
wie kann ich bei gegebenem Licht das Objekt finden, das es verwendet, und von dort aus das user_scene
Attribut dieses Objekts überprüfen ? Dies scheint mir viel schneller zu sein, als die data
Attribute einer Unmenge von Objekten von oben nach unten zu durchlaufen , aber wenn es einen Mechanismus gibt, um von unten nach oben von einem Licht zu den Objekten zu gelangen, die es verwenden, kann ich das nicht finde es in der API. Irgendwelche Ideen, klügere Leute von StackExchange?
Vielen Dank und Entschuldigung, wenn dies ein DOH ist! Art von Frage, ich bin neu in diesem Bereich und fühle mich immer noch im Dunkeln herum.
Antworten
Legen Sie sie in eine Sammlung
IMO ist der einfachste Weg, dies zu tun, wie vorgeschlagen
scene_lights = [ob for ob in scene.objects if ob.type == 'LIGHT']
Ein Lichtobjekt kann dieselben Lichtdaten haben wie einige oder alle Lichter in einer Szene. Selbst wenn nur wenige Lichter vorhanden sind, kann sich die Überprüfung, ob die Daten zu einem Objekt in der Szene gehören, als weniger effizient als oben erweisen.
Wenn Sie der Meinung sind, dass die Szene so viele Objekte enthält, dass das Iterieren ineffizient ist, sollten Sie sie mit einer oder mehreren Sammlungen verknüpfen, indem Sie den Namen oder die ID-Eigenschaft verwenden, um die Sammlung als für leichte Objekte zu kennzeichnen.
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)
Könnte Sammlungen innerhalb dieser Sammlung erstellen, um sie weiter nach Lichttyp zu kategorisieren
Polled PointerProperty
Wie von @brockmann erwähnt, kann auch die Verwendung einer Polled-Pointer-Eigenschaft in Betracht gezogen werden, ein Beispiel für Materialien
Benutzerdefinierte Suchdaten für UILayout.prop_search
Im Fall von Lichtern wäre der Zeigereigenschaftstyp bpy.types.Object
und die Abfragemethode würde gegen den Typ testen. Könnte leicht auf Lichttyp erweitert werden
Verwenden Sie das folgende Skript:
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]