1
$\begingroup$

i was working on a code to print this word (extruded) for every time i use extrude region tool bpy.ops.mesh.extrude_region_move

so i created this code

import bpy

class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def execute(self, context):
        print("This is the modal operator")
        return {'FINISHED'}

    def modal(self, context, event):
        if bpy.ops.mesh.extrude_region_move != None:
            print("extruded")



        return {'PASS_THROUGH'}




    def invoke(self, context, event):
        print("This is the invoker")

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

bpy.utils.register_class(ModalOperator)

bpy.ops.object.modal_operator('INVOKE_DEFAULT')

but the problem is this line run for every extrude that happen before not only the new ones so how to fix it ?

the line to get the extrude events

    if bpy.ops.mesh.extrude_region_move != None:
        print("extruded")



    return {'PASS_THROUGH'}
$\endgroup$
1
$\begingroup$

Look at context.active_operator

As long as there is a registered operator bpy.ops.mesh.extrude_region_move != None will always be true. bpy.ops.mesh.extrude_region_move is a callable method, which will never be None

Could check the value of the active operator. Script below prints to console if the extrude and move operator is the last operator called. It will keep printing (modally) until another operator is called. Would need to add some logic, a class property perhaps, to make it notify only once.

import bpy

class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"
    #save_op = None

    def execute(self, context):
        print("This is the modal operator")
        return {'FINISHED'}

    def modal(self, context, event):
        active_op = context.active_operator
        idname = getattr(active_op, "bl_idname")
        if idname == "MESH_OT_extrude_region_move":
            print("extruded")
            # set some var here to run once and check equality
            # self.save_op = active_op

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        print("This is the invoker")

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

bpy.utils.register_class(ModalOperator)

bpy.ops.object.modal_operator('INVOKE_DEFAULT')

could look at the index in window manager operators collection. (py console code)

>>> [o.bl_idname for o in C.window_manager.operators]
['OBJECT_OT_editmode_toggle', 'MESH_OT_extrude_region_move']

Get the transform constraint axis

>>> op = C.window_manager.operators['MESH_OT_extrude_region_move']
>>> op.macros['TRANSFORM_OT_translate'].properties['constraint_axis'].to_list()
[0, 0, 1]
$\endgroup$
  • $\begingroup$ i tried to set the var like that to make it run only once but i still get the same problem repeating output def modal(self, context, event): valo = 0 active_op = context.active_operator idname = getattr(active_op, "bl_idname") if idname == "MESH_OT_extrude_region_move" and valo == 0: print("extruded") valo = 1 print(valo) # set some var here to run once and check equality # self.save_op = active_op return {'PASS_THROUGH'} $\endgroup$ – shar Feb 17 '18 at 20:29
  • $\begingroup$ It needs to be a class property or have global scope, you are setting valo to 0 every time modal is run. $\endgroup$ – batFINGER Feb 17 '18 at 21:21

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.