Creating an UI list procedurally?

Hello i’m trying to implement an UI list feature in my addon, so let’s take the case of creating a UI list of all 'DISPLACE' modifier, for testing purpose

let’s try to show all “DISPLACE” modifiers of context object to the user in an UI list form:

this is the code i wrote for that

import bpy
from bpy.props import StringProperty, IntProperty, BoolProperty, FloatProperty, EnumProperty, PointerProperty, CollectionProperty

class SCATTER_UL_ui_list(bpy.types.UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):

        if self.layout_type in {'DEFAULT', 'COMPACT'}:
            if item:
                layout= layout.row(align=True)
                layout.scale_y = 1.2

                A  = bpy.context.object
                Am = A.modifiers[]                

                row = layout.row(align=True)
                row.prop(Am ,"show_viewport", text="" )
                row.prop(Am ,"show_render"  , text="" )
                #of course will create error because of course, will need to update this list again and again and again... 
                #the need of updating this list shouldn't be like this in the first place
                row.operator('object.modifier_remove',  text="" , icon='CANCEL').modifier = 
                row.scale_x = 0.875


class UIListPanelExample(bpy.types.Panel):

    bl_idname      = 'TEST_PT_my_panel'
    bl_space_type  = "VIEW_3D"
    bl_category    = "Scatter BETA"
    bl_region_type = "UI"
    bl_label       = "TEST"
    bl_context     = "objectmode"

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

        obj = bpy.context.object
        coll =

        #particle counter
        A  = bpy.context.object
        Am = [m for m in A.modifiers if[:7] == 'SCATTER']
        Am_count = str(len(Am)).zfill(2)
        As = [m for m in Am if m.particle_system.settings['is_selected'] == 1]
        As_count = str(len(As)).zfill(2)

        rwoo = coll.row()
        rwoo.template_list("SCATTER_UL_ui_list", "", obj, "ui_list", obj, "ui_list_index")

        rwoo = coll.row()
        rwoobox =

        rwoo2 = rwoobox.row(align=False)
        rwoo2.operator(TEST_OT_update.bl_idname, text="Redraw" , icon='SORT_DESC'  )
        rwoo2.operator("object.modifier_add", text="Add displace modif" , icon='ADD').type='DISPLACE' #+ again, the need to re update the list, over and over... 
        rwoo2.scale_y = 0.9


class SCATTER_ui_list_propGroup(bpy.types.PropertyGroup):
    name : StringProperty()    #name="Name",subtype='NONE',default="default name")
    idx  : IntProperty()      #name="Index",subtype='NONE',default=0,min=0)

class TEST_OT_update(bpy.types.Operator):
    bl_idname = "test.update"
    bl_label = ""
    bl_description = ""

    def execute(self, context):
        return {'FINISHED'}

#create/refresh ui list of all scatter modifier in context obj 
#need to be used on addon register, on any .blend opening, any modifier removal, any modifier creation, and change of active object
def update_uilist():

    A = bpy.context.object
    sc = [ for m in A.modifiers if m.type == 'DISPLACE']

    for s in sc:
        item = A.ui_list.add()
        item.idx = len(A.ui_list) = s

def register():
    #reg UI list related
    bpy.types.Object.ui_list       = CollectionProperty(type=SCATTER_ui_list_propGroup)
    bpy.types.Object.ui_list_index = IntProperty()

def unregister():
    #unreg UI list related
    del bpy.types.Object.ui_list

if __name__ == "__main__":

    #create ui list on launch

The problem with that code is that the CollectionProperty approach require to constantly update the list. on any active object context change, on any modifier addition/removal, on blender launch, and addon load/unload

so my question is what follows: is there any procedural solutions to create an UI list witouth the need of constatly update it every time ?

a bit like this really simple code below ( in the way it is just dispaying everything in that list and nothing else ) of the code...
def draw...:
    a = bpy.context.object
    displace_list = [m for m in a.modifiers if m.type == 'DISPLACE']

    for m in displace_list:
        layout.label( of the code...

ps: in my case, all i care in ui list are the scrolling abilities, maybe there’s a simple solution for that ?

1 Like