5
$\begingroup$

I'd like to track mouse movement with the MOUSEMOVE event only while LMB is held down, but can't seem to get the two to play nicely together.

What I tried was:

if event.type == 'LEFTMOUSE':
    if event.value == 'PRESS':
        *some initialization code*
        if event.type == 'MOUSEMOVE':
            *the rest of the code that relies on mouse movement data*

Is there a way to do this?

$\endgroup$
6
$\begingroup$

If event.type is LEFTMOUSE, how could it be MOUSEMOVE at the same time?
(exclude quantum mechanics)

The modal() method is called for every event, so you need to "remember" the left mouse state for the subsequent calls on MOUSEMOVE events:

import bpy
from bpy.props import IntProperty, FloatProperty


class ModalOperator(bpy.types.Operator):
    """Move an object with the mouse, example"""
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    first_mouse_x = IntProperty()
    first_value = FloatProperty()

    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':
            if self.lmb:
                delta = self.first_mouse_x - event.mouse_x
                context.object.location.x = self.first_value + delta * 0.01

        elif event.type == 'LEFTMOUSE':
            # we could handle PRESS and RELEASE individually if necessary
            self.lmb = event.value == 'PRESS'

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            context.object.location.x = self.first_value
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        # variable to remember left mouse button state    
        self.lmb = False

        if context.object:
            self.first_mouse_x = event.mouse_x
            self.first_value = context.object.location.x

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "No active object, could not finish")
            return {'CANCELLED'}


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


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


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.modal_operator('INVOKE_DEFAULT')
$\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.