As pink vertex pointed out, the method needs to called execute
.
What happens here?
An operator added to a panel shows as button, and if you click it, Blender will try to invoke it by default (which means it looks for an invoke()
method in the operator).
Since your operator has no invoke()
, it will try to execute it instead (thus try to call execute()
). Your operator doesn't have it, and Blender gives up with the error mesasge:
wm_operator_invoke: invalid operator call 'OBJECT_OT_my_operator'
So it means it couldn't find a method for the operator context (invoke
for a button in a panel by default), nor an alternative (execute
).
You can override the operator context in layouts if you need to. If your operator defines invoke()
and execute()
alongside, you might want a button in a panel that executes the operator, and not invoke it. Create a layout sub-element (column, row, ...) and set its operator_context
attribute to the context you want to run it in (see API docs):
import bpy
class OBJECT_OT_my_operator(bpy.types.Operator):
bl_idname = "object.my_operator"
bl_label = "My Operator"
def invoke(self, context, event):
print("hello invoke")
return {'FINISHED'}
def execute(self, context):
print("hello execute")
return {'FINISHED'}
def draw(self, context):
layout = self.layout
layout.operator(OBJECT_OT_my_operator.bl_idname, text="Operator 1 - invoke (default)")
col = layout.column()
col.operator_context = 'EXEC_DEFAULT'
col.operator(OBJECT_OT_my_operator.bl_idname, text="Operator 1 - execute")
def register():
bpy.utils.register_class(OBJECT_OT_my_operator)
bpy.types.RENDER_PT_render.append(draw)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_my_operator)
bpy.types.RENDER_PT_render.remove(draw)
if __name__ == "__main__":
register()
exec
should beexecute
$\endgroup$