Skip to content

Commit 3c9c5ae

Browse files
Merge pull request #23 from SpectralVectors/keymap-fix
Keymap, Cursor Reset Fix, Distance Removed
2 parents 19c7480 + 258b228 commit 3c9c5ae

3 files changed

Lines changed: 96 additions & 98 deletions

File tree

Preferences.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
import bpy
2+
from bpy.props import (
3+
BoolProperty,
4+
FloatProperty,
5+
)
6+
from bpy.types import AddonPreferences
27

38

49
def update_node_keymap(self, context):
510
wm = context.window_manager
6-
kc = wm.keyconfigs.user
7-
for key in kc.keymaps['Node Editor'].keymap_items:
11+
active_kc = wm.keyconfigs.active
12+
for key in active_kc.keymaps['Node Editor'].keymap_items:
813
if (
914
key.idname == "wm.call_menu"
1015
and key.type == "RIGHTMOUSE"
1116
):
1217
key.active = not key.active
1318

19+
addon_kc = wm.keyconfigs.addon
20+
for key in addon_kc.keymaps['Node Editor'].keymap_items:
1421
if (
1522
key.idname == "blui.right_mouse_navigation"
1623
and key.type == "RIGHTMOUSE"
1724
):
1825
key.active = not key.active
1926

2027

21-
class RightMouseNavigationPreferences(bpy.types.AddonPreferences):
28+
class RightMouseNavigationPreferences(AddonPreferences):
2229
bl_idname = __package__
2330

24-
time: bpy.props.FloatProperty(
31+
time: FloatProperty(
2532
name="Time Threshold",
2633
description="How long you have hold right mouse to open menu",
27-
default=0.3,
34+
default=1.0,
2835
min=0.1,
29-
max=2
36+
max=10,
3037
)
3138

32-
distance: bpy.props.FloatProperty(
33-
name="Distance Threshold",
34-
description="How far you have to move the mouse to trigger navigation",
35-
default=20,
36-
min=1,
37-
max=200
38-
)
39-
40-
reset_cursor_on_exit: bpy.props.BoolProperty(
39+
reset_cursor_on_exit: BoolProperty(
4140
name="Reset Cursor on Exit",
42-
description="After exiting navigation, this determines if the cursor resets to where RMB was clicked (if checked) or stays in the center (if unchecked)",
43-
default=True
41+
description="After exiting navigation, this determines if the cursor stays "
42+
"where RMB was clicked (if unchecked) or resets to the center (if checked)",
43+
default=False,
4444
)
4545

46-
enable_for_node_editors: bpy.props.BoolProperty(
46+
enable_for_node_editors: BoolProperty(
4747
name="Enable for Node Editors",
4848
description="Right Mouse will pan the view / open the Node Add/Search Menu",
4949
default=False,
@@ -55,14 +55,12 @@ def draw(self, context):
5555

5656
box = layout.box()
5757
box.label(text="Menu / Movement", icon='DRIVER_DISTANCE')
58-
row = box.row()
59-
row.prop(self, 'time')
60-
row.prop(self, 'distance')
58+
box.prop(self, 'time')
6159

6260
row = layout.row()
6361
box = row.box()
6462
box.label(text="Cursor", icon='ORIENTATION_CURSOR')
6563
box.prop(self, 'reset_cursor_on_exit')
6664
box = row.box()
6765
box.label(text='Node Editor', icon='NODETREE')
68-
box.prop(self, 'enable_for_node_editors')
66+
box.prop(self, 'enable_for_node_editors')

RightMouseNavigation.py

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
import bpy, ctypes, math, sys
1+
import bpy
2+
from bpy.types import Operator
3+
import ctypes
4+
import sys
25

3-
class BLUI_OT_right_mouse_navigation(bpy.types.Operator):
6+
7+
class BLUI_OT_right_mouse_navigation(Operator):
48
"""Timer that decides whether to display a menu after Right Click"""
59
bl_idname = "blui.right_mouse_navigation"
610
bl_label = "Right Mouse Navigation"
711
bl_options = {'REGISTER', 'UNDO'}
812

913
_timer = None
1014
_count = 0
11-
_move_distance = 0
1215
MOUSE_RIGHTUP = 0x0010
1316
_finished = False
1417
_callMenu = False
@@ -27,34 +30,44 @@ class BLUI_OT_right_mouse_navigation(bpy.types.Operator):
2730
'PAINT_VERTEX': 'VIEW3D_PT_paint_vertex_context_menu',
2831
'PAINT_WEIGHT': 'VIEW3D_PT_paint_weight_context_menu',
2932
'PAINT_TEXTURE': 'VIEW3D_PT_paint_texture_context_menu',
30-
'SCULPT': 'VIEW3D_PT_sculpt_context_menu'}
33+
'SCULPT': 'VIEW3D_PT_sculpt_context_menu',
34+
}
3135

3236
def modal(self, context, event):
3337

3438
preferences = context.preferences
3539
addon_prefs = preferences.addons[__package__].preferences
40+
enable_nodes = addon_prefs.enable_for_node_editors
41+
42+
space_type = context.space_data.type
3643

37-
if context.space_data.type == 'VIEW_3D':
44+
if space_type == 'VIEW_3D':
3845
# Check if the Viewport is Perspective or Orthographic
3946
if bpy.context.region_data.is_perspective:
4047
self._ortho = False
4148
else:
4249
self._back_to_ortho = True
4350

44-
# The _finished Boolean acts as a flag to exit the modal loop,
51+
# The _finished Boolean acts as a flag to exit the modal loop,
4552
# it is not made True until after the cancel function is called
4653
if self._finished:
4754

4855
def reset_cursor():
4956
# Reset blender window cursor to previous position
50-
context.window.cursor_warp(self.view_x, self.view_y)
57+
area = context.area
58+
x = area.x
59+
y = area.y
60+
x += int(area.width / 2)
61+
y += int(area.height / 2)
62+
bpy.context.window.cursor_warp(x, y)
5163

5264
if self._callMenu:
5365
# Always reset the cursor if menu is called, as that implies a canceled navigation
54-
reset_cursor()
66+
if addon_prefs.reset_cursor_on_exit and not space_type == 'NODE_EDITOR':
67+
reset_cursor()
5568
self.callMenu(context)
5669
else:
57-
# Exit of a full navigation. Only reset the cursor if the preference (default False) is enabled
70+
# Exit of a full navigation. Only reset the cursor if the preference is enabled
5871
if addon_prefs.reset_cursor_on_exit:
5972
reset_cursor()
6073

@@ -63,44 +76,37 @@ def reset_cursor():
6376

6477
return {'CANCELLED'}
6578

66-
if context.space_data.type == 'VIEW_3D' or addon_prefs.enable_for_node_editors and context.space_data.type == 'NODE_EDITOR':
67-
# Calculate mousemove distance before it reaches threshold
68-
if event.type == "MOUSEMOVE" and self._move_distance < addon_prefs.distance:
69-
xDelta = event.mouse_x - event.mouse_prev_x
70-
yDelta = event.mouse_y - event.mouse_prev_y
71-
deltaDistance = math.sqrt(xDelta*xDelta + yDelta*yDelta)
72-
self._move_distance += deltaDistance
73-
79+
if space_type == 'VIEW_3D' or space_type == 'NODE_EDITOR' and enable_nodes:
7480
if event.type in {'RIGHTMOUSE'}:
7581
if event.value in {'RELEASE'}:
76-
if sys.platform == 'win32':
82+
if sys.platform.startswith('win'):
7783
# This fakes a Right Mouse Up event using Ctypes
7884
ctypes.windll.user32.mouse_event(self.MOUSE_RIGHTUP)
7985
# This brings back our mouse cursor to use with the menu
8086
context.window.cursor_modal_restore()
81-
# If the length of time you've been holding down
82-
# Right Mouse and Mouse move distance is longer than the threshold value,
87+
# If the length of time you've been holding down
88+
# Right Mouse and Mouse move distance is longer than the threshold value,
8389
# then set flag to call a context menu
84-
if self._move_distance < addon_prefs.distance and self._count < addon_prefs.time:
90+
if self._count < addon_prefs.time:
8591
self._callMenu = True
8692
self.cancel(context)
87-
# We now set the flag to true to exit the modal operator on the next loop through
93+
# We now set the flag to true to exit the modal operator on the next loop
8894
self._finished = True
8995
return {'PASS_THROUGH'}
9096

9197
if event.type == 'TIMER':
9298
if self._count <= addon_prefs.time:
93-
self._count += 0.01
99+
self._count += 0.1
94100
return {'PASS_THROUGH'}
95101

96102
def callMenu(self, context):
97103
if context.space_data.type == 'NODE_EDITOR':
98104
if context.space_data.node_tree:
99-
bpy.ops.wm.search_menu('INVOKE_DEFAULT')
105+
bpy.ops.wm.search_single_menu('INVOKE_DEFAULT', menu_idname='NODE_MT_add')
100106
else:
101107
try:
102108
bpy.ops.wm.call_menu(name=self.menu_by_mode[context.mode])
103-
except:
109+
except RuntimeError:
104110
bpy.ops.wm.call_panel(name=self.menu_by_mode[context.mode])
105111

106112
def invoke(self, context, event):
@@ -112,30 +118,32 @@ def invoke(self, context, event):
112118
def execute(self, context):
113119
preferences = context.preferences
114120
addon_prefs = preferences.addons[__package__].preferences
121+
enable_nodes = addon_prefs.enable_for_node_editors
122+
123+
space_type = context.space_data.type
115124

116125
# Execute is the first thing called in our operator, so we start by
117126
# calling Blender's built-in Walk Navigation
118-
if context.space_data.type == 'VIEW_3D':
127+
if space_type == 'VIEW_3D':
119128
bpy.ops.view3d.walk('INVOKE_DEFAULT')
120129
# Adding the timer and starting the loop
121130
wm = context.window_manager
122131
self._timer = wm.event_timer_add(0.1, window=context.window)
123132
wm.modal_handler_add(self)
124133
return {'RUNNING_MODAL'}
125134

126-
elif addon_prefs.enable_for_node_editors and context.space_data.type == 'NODE_EDITOR':
135+
elif space_type == 'NODE_EDITOR' and enable_nodes:
127136
bpy.ops.view2d.pan('INVOKE_DEFAULT')
128-
129137
wm = context.window_manager
130138
# Adding the timer and starting the loop
131-
self._timer = wm.event_timer_add(0.1, window=context.window)
139+
self._timer = wm.event_timer_add(0.01, window=context.window)
132140
wm.modal_handler_add(self)
133141
return {'RUNNING_MODAL'}
134-
135-
elif context.space_data.type == 'IMAGE_EDITOR':
142+
143+
elif space_type == 'IMAGE_EDITOR':
136144
bpy.ops.wm.call_panel(name="VIEW3D_PT_paint_texture_context_menu")
137145
return {'FINISHED'}
138146

139147
def cancel(self, context):
140148
wm = context.window_manager
141-
wm.event_timer_remove(self._timer)
149+
wm.event_timer_remove(self._timer)

0 commit comments

Comments
 (0)