CollectionProperty of Object.children

Hey there,
I am trying to create a template_list that shows all the children of the selected object. I have created a recursive function that goes through all children and puts them into an Array. Is there a way to feed this array into a CollectionProperty. Best, it keeps itself up to date based on current existing children.

I haven’t found something yet.

Can somebody help me here? Or point me to something that could help me?

template_list is designed for CollectionProperties, which is like a 1-dimensional array of hashmaps (or in python lingo: a list of dicts).
It’s not really suitable for nesting like you desire.

I don’t think template_list is needed for what you want. You could just do something like:

import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Children"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        start_ob = context.object

        def child(ob, level=0):
            row = layout.row()
                
            for i in range(level*3):
                row.separator() # FIXME
            row.label(icon="FILE_PARENT" if level else "OBJECT_DATA")
            row.prop(ob, "name", text="")
            for child_ob in ob.children:
                child(child_ob, level+1)
                
        child(start_ob)


def register():
    bpy.utils.register_class(HelloWorldPanel)


def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)


if __name__ == "__main__":
    register()

This reminds me of a problem I had some time ago. I tried to save a python dict in a collection property or something like that. While this worked, it wasn’t saved in the blend file so the next time I opened the file the data was lost.

Instead I stored a written representation of the data in a string property, reserving some characters as delimiters at various levels. This is not a terribly elegant solution, but it worked for me.

@ThomasL: only bpy.props properties are stored, but not dicts you add to a PropertyGroup or similar. ID properties support lists, but I believe they actually marshall it to a string and unmarshall again on load. So that’s basically the same as to store a stringified representation of your data in a StringProperty. Note that you can use Python’s json.dumps() and json.unpacks() to do that. You might wanna consider to store the data in a separate JSON file then however (or as hidden Text object in the blend?)

import bpy
import json

data = {
    'foo': 'bar',
    'arr': [
        1, 2, 3, False, True, None
    ],
    'num': 123.456e-2
}


str = json.dumps(data)
print(str)
# {"foo": "bar", "arr": [1, 2, 3, false, true, null], "num": 1.23456}


text = bpy.data.texts.new(".hidden_file")
text.write(str)


print(json.loads(text.as_string()))
#{'foo': 'bar', 'arr': [1, 2, 3, False, True, None], 'num': 1.23456}


for area in bpy.context.screen.areas:
    if area.type == "TEXT_EDITOR":
        area.spaces.active.text = text
        break

CoDEmanX,
thanks for your help here. Yes… I thought that CollectionProperties can be a problem. I already did your approach, but that way can be problematic if I have lots of children. I did put this children props into a layout.box. Is it possible to add a scrollbar to a box? Also I would like to add the behavior to select objects from that list with a simple callback update function.

I have hacked something together which is not very clean and I probably have to change it. I have an update handler running which constantly adds and removes items to the collection property. But this is totally overkill and I think I should change this ^^

Anyway… thanks for your suggestions! Will try something more!

You can’t add scrollbars. However, you might wanna take a look at how the Icons addon does some sort of “scrolling” using a regular int propery slider.

You could limit the number of levels shown, like only children and grand children. Or add a property to collapse/expand levels below the immediate children.

What do you mean by selecting objects? Is it supposed to change the active object? You could use the outliner for this instead…
Or do you mean to let the user select certain objects, then do some action on the selection? I can see several solutions, but it depends on whether the user needs to operate on one object or a group of objects.