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[item.name]
layout.label(text=Am.name)
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 = item.name
row.scale_x = 0.875
else:
layout.label(text="")
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 = layout.box().column()
coll.separator(factor=1.5)
#particle counter
A = bpy.context.object
Am = [m for m in A.modifiers if m.name[: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.separator(factor=0.5)
rwoo.template_list("SCATTER_UL_ui_list", "", obj, "ui_list", obj, "ui_list_index")
rwoo.separator(factor=0.5)
rwoo = coll.row()
rwoo.separator(factor=0.5)
rwoobox = rwoo.box()
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
rwoo.separator(factor=0.5)
coll.separator(factor=1)
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):
update_uilist()
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 = [m.name for m in A.modifiers if m.type == 'DISPLACE']
A.ui_list.clear()
for s in sc:
item = A.ui_list.add()
item.idx = len(A.ui_list)
item.name = s
def register():
bpy.utils.register_class(TEST_OT_update)
bpy.utils.register_class(UIListPanelExample)
bpy.utils.register_class(SCATTER_UL_ui_list)
bpy.utils.register_class(SCATTER_ui_list_propGroup)
#reg UI list related
bpy.types.Object.ui_list = CollectionProperty(type=SCATTER_ui_list_propGroup)
bpy.types.Object.ui_list_index = IntProperty()
def unregister():
bpy.utils.unregister_class(TEST_OT_update)
bpy.utils.unregister_class(UIListPanelExample)
bpy.utils.unregister_class(SCATTER_UL_ui_list)
bpy.utils.unregister_class(SCATTER_ui_list_propGroup)
#unreg UI list related
del bpy.types.Object.ui_list
if __name__ == "__main__":
register()
#create ui list on launch
update_uilist()
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 )
...rest 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(m.name)
...rest 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 ?