1
$\begingroup$

I'm trying to understand how to populate an UIList with certain collections based on their name. I am trying to extend this very useful answer by @batFINGER In addition, I would like to be able to show a button/operator alongside each collection shown in the same row, if that's possible. Based on this answer collections can be iterated and returned using a BoolProperty:

import bpy

def traverse_tree(t):
    yield t
    for child in t.children:
        yield from traverse_tree(child)

coll = bpy.context.scene.collection

for c in traverse_tree(coll):
    if c.col_prop.tag:
        print(c.name)

class CollectionPropertyArchive(bpy.types.PropertyGroup):
    tag: BoolProperty(default=False)


def register():
    bpy.utils.register_class(CollectionPropertyArchive)            
    bpy.types.Collection.col_prop = bpy.props.PointerProperty(
            type = CollectionPropertyArchive)

def unregister():

    bpy.utils.unregister_class(CollectionPropertyArchive)

Q: How to populate an UIlist with certain collections?

$\endgroup$
  • $\begingroup$ @brockmann My mistake. Thanks for correcting. $\endgroup$ – Ray Mairlot Mar 31 at 12:15
  • $\begingroup$ No problem, I really appreciate that you're trying to keep things organized @RayMairlot $\endgroup$ – brockmann Mar 31 at 12:26
2
+50
$\begingroup$

Go get the UIList for materials for 2.8x from Create an interface which is similar to the material list box

Set the type of the PointerProperty to bpy.types.Collection in order to store a pointer to the collection per item added to the PropertyGroup. No matter if the user adds new objects, changes the name of the collection or anything else, it always returns the reference added to the list:

class CUSTOM_objectCollection(PropertyGroup):
    #name: StringProperty() -> Instantiated by default
    coll_ptr: PointerProperty(
        name="Collection",
        type=bpy.types.Collection)

Edit the draw_item method to display the items properly (you can use a label too):

def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
    split = layout.split(factor=0.3)
    split.label(text="Index: %d" % (index))
    split.prop(item.coll_ptr, "name", text="", emboss=False, icon="COLLECTION_NEW")

The last tiny bit you have to implement is a new operator to append the collections to your UIList. To get the idea I modified CUSTOM_OT_actionsoperator to add the active collection to the list. Just add a new item and assign the collection object to the coll_ptr variable declared before:

if self.action == 'ADD':
    act_coll = context.view_layer.active_layer_collection.collection
    if act_coll.name in [c[1].name for c in scn.custom.items()]:
        info = '"%s" already in the list' % (act_coll.name)
    else:
        item = scn.custom.add()
        item.coll_ptr = act_coll
        item.name = item.coll_ptr.name
        scn.custom_index = (len(scn.custom)-1)
        info = '%s added to list' % (item.name)

    self.report({'INFO'}, info)

enter image description here

Once a few items have been added to the list, you can use the console to make sure all is working. You can easily print the names of the collections, the objects per collection or whatever...

>>> for coll in C.scene.custom:
...     print (coll.coll_ptr.name)
...     
Collection
Collection 2


>>> for coll in C.scene.custom:
...     for ob in coll.coll_ptr.objects:
...         print (ob)
...         
<bpy_struct, Object("Cube")>
<bpy_struct, Object("Light")>
<bpy_struct, Object("Camera")>

To set the selected collection of the list as active collection in the Outliner, you can use a callback for custom_index property see: https://docs.blender.org/api/current/bpy.props.html#update-example

enter image description here

Note: You don't need that extra bool, just add the collection to the list when adding a new one to the scene.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks to you now, I understood something more and I was also able to build a callback function that activates the collection in the outsider which is updated through IntProperty to which the UIList index refers $\endgroup$ – Noob Cat Feb 29 at 19:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.