1
$\begingroup$

I have a dynamic list of variables from an external xml and want to fill them dynamically into a CollectionProperty at runtime. My problem is that I cant quite access all the variables for the ui drawing. See the draw_ui code. Excerpts from my code:

#PropertyGroup for access in ui drawing
class PropertyCollection(bpy.types.PropertyGroup):
    string_property: bpy.props.StringProperty()
    bool_property: bpy.props.BoolProperty()
    int_property: bpy.props.IntProperty()
    float_property: bpy.props.FloatProperty()

#filling PropertyGroup from external file
for key, value in some_external_dict.items():
    item = bpy.context.scene.entity_properties .add()
    if var['Type'] == 'Bool':
        item.bool_value = value
    elif var['Type'] == 'Int':
        item.int_value = value
    elif var['Type'] == 'Float':
        item.float_value = value
    elif var['Type'] == 'String':
        item.string_value = value
    item.name = var['Name']

def draw_ui(context, layout):
    properties = context.scene.external_properties

    ###How to iterate through the Collection Property?###
    for i, item in enumerate(properties):
        box.prop(item, ???, text=item.name)

class SomePanel_PT_CREATE(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Category'
    bl_label = "Label"
    bl_idname = "SomePanel_PT_CREATE"

    @classmethod
    def poll(cls, context):
        return True
    
    def execute(self, context, event):
        pass
    
    def invoke(self, context, event):
        pass

    def draw(self, context):
        draw_ui(context, self.layout)

    def register():
        bpy.types.Scene.entity_properties = bpy.props.CollectionProperty(type=PropertyCollection)
$\endgroup$

1 Answer 1

1
$\begingroup$

If I understand correctly you should use another property to store the property name. Something like that

class PropertyCollection(bpy.types.PropertyGroup):
    string_property: bpy.props.StringProperty()
    bool_property: bpy.props.BoolProperty()
    int_property: bpy.props.IntProperty()
    float_property: bpy.props.FloatProperty()
    my_property: bpy.props.StringProperty()

for key, value in some_external_dict.items():
    item = bpy.context.scene.entity_properties.add()
    if var['Type'] == 'Bool':
        item.bool_value = value
        item.my_property = "bool_property"
    elif var['Type'] == 'Int':
        item.int_value = value
        item.my_property = "int_property"
    elif var['Type'] == 'Float':
        item.float_value = value
        item.my_property = "float_property"
    elif var['Type'] == 'String':
        item.string_value = value
        item.my_property = "string_property"
    item.name = var['Name']

def draw_ui(context, layout):
    properties = context.scene.external_properties
    for i, item in enumerate(properties):
        box.prop(item, item.my_property, text=item.name)
$\endgroup$
2
  • $\begingroup$ You are correct. I falsely assumed you had to pick which property gets instantiated. In reality the whole collection gets instantiated. Thank you! $\endgroup$
    – rbx 775
    Nov 6, 2023 at 22:55
  • $\begingroup$ Yup as long as you define properties in the property group class they are all instantiated and available. Note this might cause unnecessary bloat in your file size if you have a lot of unused properties. In this case I don't think it matters though $\endgroup$
    – Gorgious
    Nov 7, 2023 at 6:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .