I wanted to draw a UIList consisting of modifiers. This UI List should only contain GeometryNodes modifier and those starts with a particular name like Terrain_
I have gone through multiple resources like questions asked by other users and now the below code successfully creates a UI List that consists of all the modifiers on the object
is it possible to show only those modifiers which meet these two particular conditions:-
- Modifier type is ‘NODES’
- Name of modifier starts with Terrain_
I can get the desired modifiers using this method but I don’t know how to imply this condition in the code
a = bpy.context.active_object
ml = [m for m in a.modifiers if m.type == 'NODES' and m.name.startswith("Terrain_")]
for x in ml:
print(x.name)
Is there any way to deal with this problem??
Complete code:
import bpy
class OBJECT_OT_modifier_move(bpy.types.Operator): #move active modifier down in stack
bl_idname = "object.modifier_move"
bl_label = "Modifier Action"
direction: bpy.props.EnumProperty(items=(('UP', 'Up', ""),
('DOWN', 'Down', ""),))
def execute(self, context):
ob = context.object
idx = ob.modifier_active_index
try:
mod = ob.modifiers[idx]
except IndexError:
pass
else:
if self.direction == 'DOWN' and idx < len(ob.modifiers) - 1:
if bpy.ops.object.modifier_move_down(modifier=mod.name) == {'FINISHED'}:
ob.modifier_active_index += 1
elif self.direction == 'UP' and idx >= 1:
if bpy.ops.object.modifier_move_up(modifier=mod.name) == {'FINISHED'}:
ob.modifier_active_index -= 1
return {"FINISHED"}
class MODIFIER_OT_DeleteItem(bpy.types.Operator):
"""Delete the selected item from the list."""
bl_idname = "modifier.delete_item"
bl_label = "Deletes a scatter item"
def execute(self, context):
ob = context.active_object
idx = ob.modifier_active_index
am = ob.modifiers.active
try:
mod = ob.modifiers[idx]
except IndexError:
pass
else:
ob.modifiers.remove(am)
if idx >= 1:
ob.modifier_active_index -= 1
return{'FINISHED'}
class MODIFIER_UL_listtype(bpy.types.UIList): #custom UIList type for modifiers
def draw_item(self, context, layout, data, item, active_data, active_propname, index):
modifiers = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(modifiers, "name", text="", emboss=False, icon="NODETREE")
show = layout.row(align=True)
show.prop(item, "show_viewport", text="")
show.prop(item, "show_render", text="")
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label("", icon="NODETREE")
class OBJECT_PT_Modifiers(bpy.types.Panel): #panel draw class
"""Creates a Panel in the Object properties window"""
bl_label = "Modifiers"
bl_idname = "OBJECT_PT_Modifiers"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
ob = bpy.context.object
rows = 2
row = layout.row()
row.template_list("MODIFIER_UL_listtype", "", ob, "modifiers", ob, "modifier_active_index", rows=rows)
col = row.column(align=True)
col.operator("object.modifier_add", icon='ADD', text="")# This operator will be replaced with the original which will create a geometry nodes modifier with a particular name starting with Terrain_
col.operator("modifier.delete_item", icon='REMOVE', text="")
col.separator()
col.operator("object.modifier_move", text='', icon='TRIA_UP').direction = 'UP'
col.operator("object.modifier_move", text='', icon='TRIA_DOWN').direction = 'DOWN'
def register():
bpy.utils.register_class(OBJECT_OT_modifier_move)
bpy.utils.register_class(MODIFIER_OT_DeleteItem)
bpy.utils.register_class(MODIFIER_UL_listtype)
bpy.utils.register_class(OBJECT_PT_Modifiers)
bpy.types.Object.modifier_active_index = bpy.props.IntProperty()
def unregister():
bpy.utils.unregister_class(OBJECT_OT_modifier_move)
bpy.utils.unregister_class(MODIFIER_OT_DeleteItem)
bpy.utils.unregister_class(MODIFIER_UL_listtype)
bpy.utils.unregister_class(OBJECT_PT_Modifiers)
del bpy.types.Object.modifier_active_index
if __name__ == "__main__":
register()