3
$\begingroup$

I'm making a simple script that will move some vertices by using modal operator. I'm using mouse position value as a variable but I noticed when the cursor is outside of blender's window it stops incrementing the value. For example, blender's normal scaling operator keeps gettign the mouse position even if the mouse is outside of the window.

How to get the mouse position even if it's outside of the window? or is there better way to do it? Below is a script that I'm testing on.

Thank you.

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

# Init
def __init__(self):
    print("init")

# invoke
def invoke(self, context, event):
    print("invoke");
    self.init_loc_x = context.object.location.x
    self.init_loc_x = context.object.location.y
    self.mouse_initial_x = event.mouse_x
    self.mouse_initial_y = event.mouse_y
    self.value = 0
    #self.value = event.mouse_xa
    self.execute(context)
    context.window_manager.modal_handler_add(self)
    return {'RUNNING_MODAL'}

# Actual content
def execute(self, context):
    print("excute");
    context.object.location.x = self.init_loc_x + self.value / 100.0
    return {'FINISHED'}

# While loop
def modal(self, context, event):
    print("modal");
    if event.type == 'MOUSEMOVE':  # Apply
        # Use UP / DOWN
        self.value = event.mouse_y - self.mouse_initial_y
        print(self.value)
        self.execute(context)
    elif event.type == 'LEFTMOUSE':  # Confirm
        return {'FINISHED'}
    elif event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
        context.object.location.x = self.init_loc_x
        return {'CANCELLED'}

    return {'RUNNING_MODAL'}

# End
def __del__(self):
    print("del")
$\endgroup$
  • $\begingroup$ Does the scaling operator ("S") keep getting the event outside the window, or does it reset the mouse location to the opposite of where it exits the region? Eg if it exits right, it reappears left. I wonder if could mouse_x and mouse_prev_x to do something similar. $\endgroup$ – batFINGER Nov 7 '17 at 13:10
  • $\begingroup$ I think that's the way scaling or moving operator are using internally.Forcefully Reset the mouse position if it went out side of the window. $\endgroup$ – Miumiu Nov 8 '17 at 21:08
1
$\begingroup$

The following script will check if the mouse is outside the 3d_view window, not Blender's window. It's not exactly what you asked for, but I hope it'll help:

def click_outside_3d_view(event):
    area, viewport = get_3d_area_region()
    return not (0 < event.mouse_region_x < viewport.width and 0 < event.mouse_region_y < viewport.height)

def get_3d_area_region():
    for window in bpy.context.window_manager.windows:
        for area in window.screen.areas:
            if area.type == 'VIEW_3D':
                for region in area.regions:
                    if region.type == 'WINDOW':
                        return area, region

***** Edit *****

I'm not completely sure, but it seems that the mouse_region_x/y are relative to the original region that the operator was running in. The following code is more foolproof:

def click_inside_3d_view(event):
    for area in get_3d_areas():
        if 0 < event.mouse_x-area.x < area.width and 0 < event.mouse_y-area.y < area.height:
            return True
    return False

def get_3d_areas():
    for screen in bpy.data.screens:
        for area in screen.areas:
            if area.type == 'VIEW_3D':
                yield area
$\endgroup$
  • $\begingroup$ Thank you for the answer! It might help. I think one idea is to reset the mouse position if mouse left the VIEW_3D window. $\endgroup$ – Miumiu Nov 8 '17 at 21:06

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.