Como encontrar * eficientemente * todas as luzes em uma cena?

Nov 26 2020

Gostaria de preencher uma lista de IU personalizada com todas as luzes que estão na cena atual, mas não tenho certeza da melhor maneira de fazer isso. Poderíamos iterar bpy.context.scene.objectse validar object.type == 'LIGHT'para filtrar as coisas e então usar objects[i].datapara obter a luz real, mas isso me parece desajeitado e sem desempenho, especialmente para cenas que têm um grande número de objetos.

Idealmente, gostaria de detalhar bpy.data.lightse filtrar esse conjunto de dados muito menor com base na (s) cena (s) em que cada luz é usada. Mas, dada uma luz bpy.data.lights, como posso encontrar o objeto que está usando, e a partir daí verificar o user_sceneatributo desse objeto ? Isso me parece ser muito mais rápido do que iterar de cima para baixo sobre os dataatributos de um zilhão de objetos , mas se houver um mecanismo para ir de baixo para cima a partir de uma luz para o (s) objeto (s) que a está usando, então não posso encontre-o na API. Alguma ideia, pessoal mais inteligente do StackExchange?

Muito obrigado e desculpas se este é um DOH! tipo de pergunta, eu sou novo nisso e ainda estou tateando no escuro.

Respostas

2 batFINGER Nov 27 2020 at 11:28

Coloque-os em uma coleção

IMO a maneira mais simples de fazer isso é, conforme sugerido

scene_lights = [ob for ob in scene.objects if ob.type == 'LIGHT']

Um objeto de luz pode ter os mesmos dados de luz que qualquer uma ou todas as luzes em uma cena. Mesmo se houver poucas luzes, verificar se os dados pertencem a um objeto na cena pode ser menos eficiente do que acima.

Se você sentir que há tantos objetos na cena que iterar sobre eles é ineficiente, considere vinculá-los a uma (s) coleção (ões) usando a propriedade de nome ou ID para marcar a coleção como sendo de objetos leves.

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)

Pode fazer coleções dentro desta coleção para categorizar ainda mais por tipo de luz

Polled PointerProperty

Como mencionado por @brockmann também pode considerar o uso de uma propriedade de ponteiro sondado, um exemplo para materiais

Dados de pesquisa personalizados para UILayout.prop_search

ao passo que, no caso de luzes, o tipo de propriedade de ponteiro seria bpy.types.Object, e o método de votação seria testado em relação ao tipo. Pode ser facilmente estendido para o tipo de luz

MohammadHosseinJamshidi Nov 27 2020 at 04:20

use o script abaixo:

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]