1
$\begingroup$

I'm currently working on a python tool using a modal operator. Now I know to finish the operation I can use:

if event.type == 'LEFTMOUSE':
    return {'FINISHED'}

However it seems not to count as a 'LEFTMOUSE' when I click (select) an object! I also tried 'SELECTMOUSE' which doesn't do anything.

What I would like to do is store the clicked object, and then automatically finish the modal operator.

Any ideas? Thanks in advance!

$\endgroup$
1
$\begingroup$

Why type.event ?

You should get your event.type, and you may want to compare the event.value as well:

def modal(self, context, event):
    if event.type in {"LEFTMOUSE"} and event.value == "RELEASE":
        return {'FINISHED'}
    return {'PASS_THROUGH'}

Also, it might be possible that an event been stop propagate in most of the event handling system. You might need to check the context carefully to see what is the main problem.

$\endgroup$
  • 1
    $\begingroup$ sorry I actually meant event.type and also got that right in my script. when I use the value RELEASE, clicking an object does end the modal but therefore doesn't select the object... $\endgroup$ – Mantikator May 14 at 8:32
  • $\begingroup$ So you want to check something after you click and select an object? I don't know if it is safe to do relative thing in a same event loop. Interesting problem, I will test a little bit for it. $\endgroup$ – Hikariztw May 14 at 11:59
1
$\begingroup$

I have a solution and it's actually very simple:

class OBJECT_OT_do_stuff(bpy.types.Operator):
    bl_idname = "object.do_stuff"
    bl_label = "Do Stuff"

    origSel: None

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def modal(self, context, event):
        # Update selection
        curSel = context.selected_objects[-1]

        # On selecting new object
        if curSel is not self.origSel:
            print("selection was changed")
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            print("cancelled operation")
            return {'CANCELLED'}

        else:
            return {'PASS_THROUGH'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.origSel = context.object
        # Execute Modal Operation
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

I assigned an attribute that in the invoke function gets filled with the active object. Then the modal function keeps comparing the current selection to the previous one!

An important thing to note is that in order for that to work you need to call the function with the invoke argument :bpy.ops.object.do_stuff('INVOKE_DEFAULT')

$\endgroup$
  • 1
    $\begingroup$ Using the last in the selected list could make this a little random, Would use curSel = context.object $\endgroup$ – batFINGER May 15 at 8:50
  • $\begingroup$ You're right, thanks $\endgroup$ – Mantikator May 15 at 14:24

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.