4
$\begingroup$

in my add on, every execution of my operator, I change my icon cursor. (see code) I have to repeat these two lines of code in all operators or there is a solution to change icon when an operator is running?

def execute(self,context):
    bpy.context.window.cursor_set("WAIT")
    ....
    My code
    .....

    bpy.context.window.cursor_set("DEFAULT")
    return {'FINISHED'}
$\endgroup$
3
  • $\begingroup$ Tested it with time module: bpy.context.window.cursor_set("WAIT") time.sleep(5) bpy.context.window.cursor_set("DEFAULT") Code works. What is your issue? $\endgroup$
    – p2or
    Commented Feb 14, 2015 at 17:29
  • $\begingroup$ yes the code works perfectly. my question is this: If I have 10 operators, I have to put this code in each operator? $\endgroup$ Commented Feb 14, 2015 at 17:40
  • 1
    $\begingroup$ You could probably write a decorator function if you find yourself writing repetitive code like that, but this is more like a stackoverflow general python question then.. $\endgroup$
    – zeffii
    Commented Feb 14, 2015 at 19:52

1 Answer 1

6
$\begingroup$

Using a decorator in an Operator class. Notice the repeating code is defined once in the decorator and any* function which you want to wrap that code around can be decorated with the @mouse_change

import bpy
import time

# declare the decorator
def mouse_change(func):
    def add_mouse_change(*args):
        bpy.context.window.cursor_set("WAIT")
        func(*args)
        bpy.context.window.cursor_set("DEFAULT")
    return add_mouse_change


class SimpleCBOperator(bpy.types.Operator):
    bl_idname = "node.some_callback_identifier"
    bl_label = "Short Name"

    fn_name = bpy.props.StringProperty(default='')

    @mouse_change
    def dispatch(self, context, type_op):

        if type_op == 'some_named_function':
            time.sleep( 5 )
            print(type_op)

        elif type_op == 'some_named_other_function':
            time.sleep( 5 )
            print(type_op)

    def execute(self, context):
        self.dispatch(context, self.fn_name)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleCBOperator)

def unregister():
    bpy.utils.unregister_class(SimpleCBOperator)

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.node.some_callback_identifier(fn_name='some_named_function')

*The way I wrote the decorator function won't let you decorate the execute function.

you would have less code, and arguably more understandable code, by dropping the decorator entirely and going with a dispatch-callback pattern..

class SimpleCBOperator(bpy.types.Operator):
    bl_idname = "node.some_callback_identifier"
    bl_label = "Short Name"

    fn_name = bpy.props.StringProperty(default='')

    def dispatch(self, context, type_op):
        cursor_set = bpy.context.window.cursor_set
        cursor_set("WAIT")

        if type_op == 'some_named_function':
            pass

        elif type_op == 'some_named_other_function':
            pass

        cursor_set("DEFAULT")

    def execute(self, context):
        self.dispatch(context, self.fn_name)
        return {'FINISHED'}

The drawback of using a single operator 'callback' with an internal dispatch, is that the tooltip wouldn't be unique per fn_name. These are at least a few options to look into.

$\endgroup$

You must log in to answer this question.

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