Why does my UI Panel not work?

Why does this code not work? When I click the ‘Add Array (no spacing)’ button I created in the ‘n’ menu, nothing happens. The ‘Duplicate Objects’ operator/button works fine.

import bpy

class addArray(bpy.types.Operator):
    bl_label = "Add Array (no spacing)"
    bl_idname = "mesh.add_array"
    
    def addArray(self, context):
        bpy.ops.object.modifier_add(type="ARRAY")
        bpy.context.object.modifiers["Array"].count = 10
        for m in context.active_object.modifiers:
            if m.type=='ARRAY':
                bpy.ops.object.modifiers_apply(name=m.name)
                
def register():
    bpy.utils.register_class(ultimatePanel)
def unregister():
    bpy.utils.unregister_class(ultimatePanel)
    
bpy.utils.register_class(addArray)

class ultimatePanel(bpy.types.Panel):        
    bl_label = "Ultimate Duplication"
    bl_idname = "Ultimate_PT_Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Ultimate Duplication'
    
    def draw(self, context):
        layout = self.layout
        # col = layout.column()
        row = layout.row()
        row.operator("object.duplicate_move", icon="DUPLICATE")
        row = layout.row()
        row.operator("mesh.add_array", icon="MOD_ARRAY")
        
        

def register():
    bpy.utils.register_class(ultimatePanel)
def unregister():
    bpy.utils.unregister_class(ultimatePanel)
    
if __name__ == "__main__":
    register()

your panel is registered but you didn’t register your operator. any class you create that you want Blender to know about needs to be registered.

should be modifier_apply, not modifiers_apply. when i respond with code it’s all off the top of my head so it’s probably best to double check the API docs to be sure :slight_smile:

1 Like

actually i did register my operator

def register():
    bpy.utils.register_class(ultimatePanel)
def unregister():
    bpy.utils.unregister_class(ultimatePanel)
    
bpy.utils.register_class(addArray)
import bpy

class addArray(bpy.types.Operator):
    bl_label = "Add Array (no spacing)"
    bl_idname = "mesh.add_array"
    
    def addArray(self, context):
        bpy.ops.object.modifier_add(type="ARRAY")
        bpy.context.object.modifiers["Array"].count = 10
        for m in bpy.context.active_object.modifiers:
            if m.type=='ARRAY':
                bpy.ops.object.modifier_apply(name=m.name)
                
def register():
    bpy.utils.register_class(ultimatePanel)
def unregister():
    bpy.utils.unregister_class(ultimatePanel)
    
bpy.utils.register_class(addArray)

class ultimatePanel(bpy.types.Panel):        
    bl_label = "Ultimate Duplication"
    bl_idname = "Ultimate_PT_Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Ultimate Duplication'
    
    def draw(self, context):
        layout = self.layout
        # col = layout.column()
        row = layout.row()
        row.operator("object.duplicate_move", icon="DUPLICATE")
        row = layout.row()
        row.operator("mesh.add_array", icon="MOD_ARRAY")
        
    
if __name__ == "__main__":
    register()

this code still doesn’t work. know why?

any errors? are you able to confirm it’s registered successfully, ie) in the console can you type bpy.types.MESH_OT_add_array and confirm the operator is registered with Blender?

image

1 Like
import bpy

class MESH_OT_Add_Array(bpy.types.Operator):
    bl_label = "Add Array (no spacing)"
    bl_idname = "mesh.add_array"
    
    def execute(self, context):
        bpy.ops.object.modifier_add(type='ARRAY')
        bpy.context.object.modifiers["Array"].count = 10
        for m in bpy.context.active_object.modifiers:
            if m.type=='ARRAY':
                bpy.ops.object.modifier_apply(modifier=m.name)
        return {'FINISHED'}

class ULTIMATE_PT_Panel(bpy.types.Panel):        
    bl_label = "Ultimate Duplication"
    bl_idname = "ULTIMATE_PT_Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Ultimate Duplication'
    
    def draw(self, context):
        layout = self.layout
        # col = layout.column()
        row = layout.row()
        row.operator("object.duplicate_move", icon="DUPLICATE")
        row = layout.row()
        row.operator("mesh.add_array", icon="MOD_ARRAY")

def register():
    bpy.utils.register_class(ULTIMATE_PT_Panel)
    bpy.utils.register_class(MESH_OT_Add_Array)    
def unregister():
    bpy.utils.unregister_class(ULTIMATE_PT_Panel)
    bpy.utils.unregister_class(MESH_OT_Add_Array)    

if __name__ == "__main__":
    register()

forgot to add it says this in the terminal (mac big sur)


Screen Shot 2021-11-23 at 9.48.24 AM

can this function be named anything other then execute?
and this seems to have worked, thank you both for your time

no. execute is part of the operator base class you are extending when you create your class. without an execute or invoke function registration will fail

The execute() method of an operator is used by default immediately, if there´s no invoke() method.
See operator context: op_context . There is no ‘EXEC_MYMETHOD’ or anything similar. But you can call your own method via execute:

class MESH_OT_Add_Array(bpy.types.Operator):
    bl_label = "Add Array (no spacing)"
    bl_idname = "mesh.add_array"
    
    def execute(self, context):
        return self.addArray(context)

    def addArray(self, context):
        bpy.ops.object.modifier_add(type='ARRAY')
        bpy.context.object.modifiers["Array"].count = 10
        for m in bpy.context.active_object.modifiers:
            if m.type=='ARRAY':
                bpy.ops.object.modifier_apply(modifier=m.name)
        return {'FINISHED'}