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$
  • $\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 Feb 14 '15 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$ – Logiquefloue Feb 14 '15 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 Feb 14 '15 at 19:52
5
$\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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.