5
$\begingroup$

I want to invoke an operator when rendering is finished.

import bpy

class FooOp(bpy.types.Operator):
    bl_idname = "development.fooop"
    bl_label = "Foo"

    @classmethod
    def poll(cls,context):
        return True

    def invoke(self,context,event):
        self.report({'INFO'},"running FooOp!")
        return {'FINISHED'}

def make_foo(scene):
    bpy.ops.development.fooop('INVOKE_DEFAULT')

bpy.app.handlers.render_complete.append(make_foo)
bpy.utils.register_class(FooOp)

When rendering finishes, this error message is printed to the terminal:

Traceback (most recent call last):
  File "/Users/reillyi/Dropbox/blender_dev/addons/render_notification/call_operator.blend/Text", line 16, in make_foo
  File "/Applications/Blender/blender.app/Contents/MacOS/2.71/scripts/modules/bpy/ops.py", line 186, in __call__
    ret = op_call(self.idname_py(), C_dict, kw, C_exec, C_undo)
RuntimeError: Operator bpy.ops.development.fooop.poll() Missing 'window' in context

If I replace line 16, calling my FooOp operator, with

bpy.ops.mesh.primitive_torus_add()

Then a torus is created with no problem.

Can you help?

$\endgroup$

1 Answer 1

5
$\begingroup$

If you're only going to call this operator from the callback, you don't really need to use an operator.

However, the reason that your operator fails is that it doesn't support execution rather than invocation.

Add a method called execute with (self, context) as the arguments. If you want to use the invoke() method's code, just call self.invoke and pass None for the event (be careful with this). The execute() method should return a set for the result just as invoke() does, so if you're using invoke's body, just return the result of self.invoke(context, None).

Finally, call the operator as 'EXEC_DEFAULT' instead of 'INVOKE_DEFAULT'

import bpy

class FooOp(bpy.types.Operator):
    bl_idname = "development.fooop"
    bl_label = "Foo"

    @classmethod
    def poll(cls,context):
        return True

    def execute(self, context):
        return self.invoke(context, None)

    def invoke(self,context,event):
        self.report({'INFO'},"running FooOp!")
        return {'FINISHED'}

def make_foo(scene):
    bpy.ops.development.fooOp('EXEC_DEFAULT')


bpy.app.handlers.render_complete.append(make_foo)
bpy.utils.register_class(FooOp)
$\endgroup$
2
  • $\begingroup$ Thanks! The reason that I need an operator here is that I really want to run a modal operator when rendering is done. However, when I try to do this, by modifying the invoke method to have context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} and add a modal method def modal(self,context,event): return({'FINISHED','PASS_THROUGH'}) then blender segfaults! Any advice? $\endgroup$
    – S_FLUID
    Sep 5, 2014 at 19:40
  • $\begingroup$ The question in this comment is now its own question: blender.stackexchange.com/questions/15841/… $\endgroup$
    – S_FLUID
    Sep 14, 2014 at 20:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .