How to detect "click" event in Blender Python

Hi,

I am finding a way how to detect click event in Blender’s Python API. I already found out that DOUBLE_CLICK event is not supposed to work, and for some reason it’s not even considered a bug:
https://developer.blender.org/T69235

But I was very disappointed that not only DOUBLE_CLICK but also regular CLICK event doesn’t work. Now, how am I supposed to be able to exit modal operator using right mouse click without triggering right mouse context menu at the same time? Right now, I am unable to. If I use RIGHTMOUSE event of PRESS or RELEASE type, it triggers context menu also, which is RIGHTMOUSE CLICK. I want it to register as RIGHTMOUSE CLICK event too so that exiting my modal operator overrides it and does not open context menu.

CLICK_DRAG don’t detected too.

Someone know how to detect click_drag or click or double_click event before press and release events? I need to use press, click, click_drag and double_click for diferent things.

Please check out https://docs.blender.org/api/blender2.8/bpy.types.Operator.html#modal-execution

The example provided there is really useful for a first contact with modal operators. I think it covers the aspects you need, check it out!

Also, you did not provided any code so we can help you further but probably you want to return {‘FINISHED’} when event.type == ‘RIGHTMOUSE’ inside your modal function, that will tell Blender to finish that operator successfully. (ops!, note: in this case no need to specify if it’s press or click or release if you just want that key to finish the operator. Also note that - even if click events are not triggered or that nice to go - you can detect a click manually with press and release and also to click drag as with ‘event’ you have access to mouse position plus you can set a manual threshold to start an action :D).

release is working with mousemove but not leftclick for example.
double clic I found some answer but nothing really working
time.time() with an event not working (to hold press). alone without any other event yes.
left+double click, +click drag same…strange

1 Like

to do a click_drag you can do this:
for example lasso on right clic

if event.type == 'RIGHTMOUSE':
    if event.value == 'PRESS':
        bpy.ops.view3d.select_lasso('INVOKE_DEFAULT',mode='ADD')

but if you want to add something else on the release like toggle selection it wont work.
you will need to use a shift for example there I add a ctrl to do a sub lasso

elif event.type == 'RIGHTMOUSE':
    if event.shift:
        bpy.ops.view3d.select_lasso('INVOKE_DEFAULT',mode='ADD')
        return {'PASS_THROUGH'}
    if event.ctrl:
        bpy.ops.view3d.select_lasso('INVOKE_DEFAULT',mode='SUB')
        return {'PASS_THROUGH'} 
    if event.value == 'RELEASE':
        bpy.ops.object.select_all(action='TOGGLE')

I didn’t find a way to do a double click but you can use is_repeat to do something different if you hold the key (the time the key is repeated)
for example I do a pass_through on the enter ‘ret’ because I need it to confirm G R S (if I do for example G 2X enter) and I do something between because after doing my G 2X enter something else happen. but to show that you can use a key to do something but this is not detected as a ‘press’

            if context.mode == 'OBJECT':
                context.scene.cursor.location = bpy.data.objects['XCursor'].location
                context.scene.cursor.rotation_mode='XYZ' 
                context.scene.cursor.rotation_euler=bpy.data.objects['XCursor'].rotation_euler
                return {'PASS_THROUGH'}

and if I hold it

        elif event.type in {'RET','NUMPAD_ENTER'} :
            if event.is_repeat:
                self.confirm_cancel(context)
                return {'FINISHED'}

so together

        elif event.type in {'RET','NUMPAD_ENTER'} :
            if event.is_repeat:
                self.confirm_cancel(context)
                return {'FINISHED'}
            if context.mode == 'OBJECT':
                context.scene.cursor.location = bpy.data.objects['XCursor'].location
                context.scene.cursor.rotation_mode='XYZ' 
                context.scene.cursor.rotation_euler=bpy.data.objects['XCursor'].rotation_euler
                return {'PASS_THROUGH'}
            else:
                self.confirm_cursor_pos(context)
                return {'PASS_THROUGH'}
2 Likes