diff options
16 files changed, 517 insertions, 208 deletions
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index afa04a18ef6..3f0248970c6 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -858,6 +858,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): "description": getattr(tool_cls, "bl_description", tool_cls.__doc__), "icon": getattr(tool_cls, "bl_icon", None), "cursor": getattr(tool_cls, "bl_cursor", None), + "options": getattr(tool_cls, "bl_options", None), "widget": getattr(tool_cls, "bl_widget", None), "widget_properties": getattr(tool_cls, "bl_widget_properties", None), "keymap": getattr(tool_cls, "bl_keymap", None), diff --git a/release/scripts/presets/keyconfig/Blender.py b/release/scripts/presets/keyconfig/Blender.py index eb66c961472..1690b03184a 100644 --- a/release/scripts/presets/keyconfig/Blender.py +++ b/release/scripts/presets/keyconfig/Blender.py @@ -54,6 +54,19 @@ class Prefs(bpy.types.KeyConfigPreferences): default='PLAY', update=update_fn, ) + rmb_action: EnumProperty( + name="Right Mouse Select Action", + items=( + ('TWEAK', "Select & Tweak", + "Right mouse always tweaks"), + ('FALLBACK_TOOL', "Selection Tool", + "Right mouse uses the selection tool"), + ), + description=( + "Default action for the right mouse button" + ), + update=update_fn, + ) use_alt_click_leader: BoolProperty( name="Alt Click Tool Prompt", description=( @@ -179,6 +192,8 @@ class Prefs(bpy.types.KeyConfigPreferences): if is_select_left: col.row().prop(self, "gizmo_action", text="Activate Gizmo Event", expand=True) + else: + col.row().prop(self, "rmb_action", text="Right Mouse Select Action", expand=True) # Checkboxes sub-layout. col = layout.column() @@ -232,6 +247,7 @@ def load(): kc_prefs.select_mouse == 'LEFT' and kc_prefs.gizmo_action == 'DRAG' ), + use_fallback_tool=(True if (kc_prefs.select_mouse == 'LEFT') else (kc_prefs.rmb_action == 'FALLBACK_TOOL')), use_alt_click_leader=kc_prefs.use_alt_click_leader, use_pie_click_drag=kc_prefs.use_pie_click_drag, ), diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 44b77ab2aac..6a3064fc820 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -46,6 +46,8 @@ class Params: "use_select_all_toggle", # Activate gizmo on drag (which support it). "use_gizmo_drag", + # Use the fallback tool instead of tweak for RMB select. + "use_fallback_tool", # Use pie menu for tab by default (swap 'Tab/Ctrl-Tab'). "use_v3d_tab_menu", # Use extended pie menu for shading. @@ -59,6 +61,15 @@ class Params: "v3d_tilde_action", # Alt-MMB axis switching 'RELATIVE' or 'ABSOLUTE' axis switching. "v3d_alt_mmb_drag_action", + + # Convenience variables: + # (derived from other settings). + # + # This case needs to be checked often, + # convenience for: `params.use_fallback_tool if params.select_mouse == 'RIGHT' else False`. + "use_fallback_tool_rmb", + # Convenience for: `'CLICK' if params.use_fallback_tool_rmb else params.select_mouse_value`. + "select_mouse_value_fallback", ) def __init__( @@ -72,6 +83,7 @@ class Params: spacebar_action='TOOL', use_select_all_toggle=False, use_gizmo_drag=True, + use_fallback_tool=False, use_v3d_tab_menu=False, use_v3d_shade_ex_pie=False, use_v3d_mmb_pan=False, @@ -96,6 +108,9 @@ class Params: self.context_menu_event = {"type": 'W', "value": 'PRESS'} self.cursor_set_event = {"type": 'LEFTMOUSE', "value": 'CLICK'} self.cursor_tweak_event = None + self.use_fallback_tool = use_fallback_tool + self.use_fallback_tool_rmb = use_fallback_tool + self.select_mouse_value_fallback = 'CLICK' if self.use_fallback_tool_rmb else self.select_mouse_value else: # Left mouse select uses Click event for selection. This is a little # less immediate, but is needed to distinguish between click and tweak @@ -115,6 +130,10 @@ class Params: self.cursor_set_event = {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True} self.cursor_tweak_event = {"type": 'EVT_TWEAK_R', "value": 'ANY', "shift": True} + self.use_fallback_tool = True + self.use_fallback_tool_rmb = False + self.select_mouse_value_fallback = self.select_mouse_value + self.use_mouse_emulate_3_button = use_mouse_emulate_3_button @@ -148,6 +167,15 @@ NUMBERS_0 = ('ZERO', 'ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIG # ------------------------------------------------------------------------------ +# Generic Utilities + +def _fallback_id(text, fallback): + if fallback: + return text + " (fallback)" + return text + + +# ------------------------------------------------------------------------------ # Keymap Item Wrappers def op_menu(menu, kmi_args): @@ -882,20 +910,25 @@ def km_uv_editor(params): items.extend([ # Selection modes. *_template_items_uv_select_mode(params), + *_template_uv_select( + type=params.select_mouse, + value=('CLICK' if params.use_fallback_tool_rmb else params.select_mouse_value), + legacy=params.legacy, + ), ("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None), - ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value}, - {"properties": [("deselect_all", not params.legacy)]}), - ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True}, - {"properties": [("extend", True)]}), ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None), ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True}, {"properties": [("extend", True)]}), - ("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None), - ("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "shift": True, "alt": True}, + ("uv.select_edge_ring", + {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None), + ("uv.select_edge_ring", + {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "shift": True, "alt": True}, {"properties": [("extend", True)]}), - ("uv.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, + ("uv.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "ctrl": True}, {"properties": [("use_fill", False)]}), - ("uv.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "shift": True}, + ("uv.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "ctrl": True, "shift": True}, {"properties": [("use_fill", True)]}), ("uv.select_split", {"type": 'Y', "value": 'PRESS'}, None), ("uv.select_box", {"type": 'B', "value": 'PRESS'}, @@ -1196,20 +1229,11 @@ def km_view3d(params): ("view3d.view_axis", {"type": 'NDOF_BUTTON_TOP', "value": 'PRESS', "shift": True}, {"properties": [("type", 'TOP'), ("align_active", True)]}), # Selection. - *(( - "view3d.select", - {"type": params.select_mouse, "value": params.select_mouse_value, **{m: True for m in mods}}, - {"properties": [(c, True) for c in props]}, - ) for props, mods in ( - (("deselect_all",) if not params.legacy else (), ()), - (("toggle",), ("shift",)), - (("center", "object"), ("ctrl",)), - (("enumerate",), ("alt",)), - (("toggle", "center"), ("shift", "ctrl")), - (("center", "enumerate"), ("ctrl", "alt")), - (("toggle", "enumerate"), ("shift", "alt")), - (("toggle", "center", "enumerate"), ("shift", "ctrl", "alt")), - )), + *_template_view3d_select( + type=params.select_mouse, + value=('CLICK' if params.use_fallback_tool_rmb else params.select_mouse_value), + legacy=params.legacy, + ), ("view3d.select_box", {"type": 'B', "value": 'PRESS'}, None), ("view3d.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True}, {"properties": [("mode", 'ADD')]}), @@ -3203,7 +3227,7 @@ def km_grease_pencil(_params): return keymap -def _grease_pencil_selection(params): +def _grease_pencil_selection(params, use_select_mouse=True): return [ # Select all *_template_items_select_actions(params, "gpencil.select_all"), @@ -3225,13 +3249,12 @@ def _grease_pencil_selection(params): {"properties": [("mode", 'ADD')]}), ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "shift": True, "ctrl": True, "alt": True}, {"properties": [("mode", 'SUB')]}), - ("gpencil.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True}, - {"properties": [("extend", True), ("toggle", True)]}), - # Whole stroke select - ("gpencil.select", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, - {"properties": [("entire_strokes", True)]}), - ("gpencil.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True}, - {"properties": [("extend", True), ("entire_strokes", True)]}), + *_template_view3d_gpencil_select( + type=params.select_mouse, + value=params.select_mouse_value_fallback, + legacy=params.legacy, + use_select_mouse=use_select_mouse, + ), # Select linked ("gpencil.select_linked", {"type": 'L', "value": 'PRESS'}, None), ("gpencil.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), @@ -3266,9 +3289,6 @@ def km_grease_pencil_stroke_edit_mode(params): # Interpolation ("gpencil.interpolate", {"type": 'E', "value": 'PRESS', "ctrl": True}, None), ("gpencil.interpolate_sequence", {"type": 'E', "value": 'PRESS', "shift": True, "ctrl": True}, None), - # Normal select - ("gpencil.select", {"type": params.select_mouse, "value": params.select_mouse_value}, - {"properties": [("deselect_all", not params.legacy)]}), # Selection *_grease_pencil_selection(params), # Duplicate and move selected points @@ -3560,7 +3580,7 @@ def km_grease_pencil_stroke_sculpt_mode(params): items.extend([ # Selection - *_grease_pencil_selection(params), + *_grease_pencil_selection(params, use_select_mouse=False), # Brush strength ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True}, @@ -3846,7 +3866,7 @@ def km_grease_pencil_stroke_vertex_mode(params): items.extend([ # Selection - *_grease_pencil_selection(params), + *_grease_pencil_selection(params, use_select_mouse=False), # Brush strength ("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True}, {"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}), @@ -4267,7 +4287,8 @@ def km_curve(params): {"properties": [("deselect", False)]}), ("curve.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True}, {"properties": [("deselect", True)]}), - ("curve.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, None), + ("curve.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "ctrl": True}, None), ("curve.separate", {"type": 'P', "value": 'PRESS'}, None), ("curve.split", {"type": 'Y', "value": 'PRESS'}, None), ("curve.extrude_move", {"type": 'E', "value": 'PRESS'}, None), @@ -4348,6 +4369,80 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal return items +def _template_view3d_select(*, type, value, legacy): + return [( + "view3d.select", + {"type": type, "value": value, **{m: True for m in mods}}, + {"properties": [(c, True) for c in props]}, + ) for props, mods in ( + (("deselect_all",) if not legacy else (), ()), + (("toggle",), ("shift",)), + (("center", "object"), ("ctrl",)), + (("enumerate",), ("alt",)), + (("toggle", "center"), ("shift", "ctrl")), + (("center", "enumerate"), ("ctrl", "alt")), + (("toggle", "enumerate"), ("shift", "alt")), + (("toggle", "center", "enumerate"), ("shift", "ctrl", "alt")), + )] + + +def _template_view3d_select_for_fallback(params, fallback): + if (not fallback) and params.use_fallback_tool_rmb: + # Needed so we have immediate select+tweak when the default select tool is active. + return _template_view3d_select( + type=params.select_mouse, + value=params.select_mouse_value, + legacy=params.legacy, + ) + return [] + + +def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=True): + return [ + *([] if not use_select_mouse else [ + ("gpencil.select", {"type": type, "value": value}, + {"properties": [("deselect_all", not legacy)]})]), + ("gpencil.select", {"type": type, "value": value, "shift": True}, + {"properties": [("extend", True), ("toggle", True)]}), + # Whole stroke select + ("gpencil.select", {"type": type, "value": value, "alt": True}, + {"properties": [("entire_strokes", True)]}), + ("gpencil.select", {"type": type, "value": value, "shift": True, "alt": True}, + {"properties": [("extend", True), ("entire_strokes", True)]}), + ] + + +def _template_view3d_gpencil_select_for_fallback(params, fallback): + if (not fallback) and params.use_fallback_tool_rmb: + # Needed so we have immediate select+tweak when the default select tool is active. + return _template_view3d_gpencil_select( + type=params.select_mouse, + value=params.select_mouse_value, + legacy=params.legacy, + ) + return [] + + +def _template_uv_select(*, type, value, legacy): + return [ + ("uv.select", {"type": type, "value": value}, + {"properties": [("deselect_all", not legacy)]}), + ("uv.select", {"type": type, "value": value, "shift": True}, + {"properties": [("extend", True)]}), + ] + + +def _template_uv_select_for_fallback(params, fallback): + if (not fallback) and params.use_fallback_tool_rmb: + # Needed so we have immediate select+tweak when the default select tool is active. + return _template_uv_select( + type=params.select_mouse, + value=params.select_mouse_value, + legacy=params.legacy, + ) + return [] + + def km_image_paint(params): items = [] keymap = ( @@ -4651,9 +4746,11 @@ def km_mesh(params): ("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None), ("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True, "alt": True}, {"properties": [("toggle", True)]}), - ("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, + ("mesh.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "ctrl": True}, {"properties": [("use_fill", False)]}), - ("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True}, + ("mesh.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "shift": True, "ctrl": True}, {"properties": [("use_fill", True)]}), *_template_items_select_actions(params, "mesh.select_all"), ("mesh.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), @@ -4801,7 +4898,8 @@ def km_armature(params): ("armature.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True}, {"properties": [("deselect", True)]}), ("armature.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), - ("armature.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, None), + ("armature.shortest_path_pick", + {"type": params.select_mouse, "value": params.select_mouse_value_fallback, "ctrl": True}, None), # Editing. op_menu("VIEW3D_MT_edit_armature_delete", {"type": 'X', "value": 'PRESS'}), op_menu("VIEW3D_MT_edit_armature_delete", {"type": 'DEL', "value": 'PRESS'}), @@ -5825,38 +5923,60 @@ def km_image_editor_tool_uv_cursor(params): ) -def km_image_editor_tool_uv_select(params): +def km_image_editor_tool_uv_select(params, *, fallback): return ( - "Image Editor Tool: Uv, Tweak", + _fallback_id("Image Editor Tool: Uv, Tweak", fallback), {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select(params, "uv.select", "uv.cursor_set", extend="extend")}, + {"items": [ + *([] if fallback else _template_items_tool_select(params, "uv.select", "uv.cursor_set", extend="extend")), + *([] if (not params.use_fallback_tool_rmb) else _template_uv_select( + type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), + ]}, ) -def km_image_editor_tool_uv_select_box(params): +def km_image_editor_tool_uv_select_box(params, *, fallback): return ( - "Image Editor Tool: Uv, Select Box", + _fallback_id("Image Editor Tool: Uv, Select Box", fallback), {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple("uv.select_box", type=params.tool_tweak, value='ANY')}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "uv.select_box", + type=params.select_tweak if fallback else params.tool_tweak, + value='ANY')), + *_template_uv_select_for_fallback(params, fallback), + ]}, ) -def km_image_editor_tool_uv_select_circle(params): +def km_image_editor_tool_uv_select_circle(params, *, fallback): return ( - "Image Editor Tool: Uv, Select Circle", + _fallback_id("Image Editor Tool: Uv, Select Circle", fallback), {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "uv.select_circle", type=params.tool_mouse, value='PRESS', - properties=[("wait_for_input", False)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "uv.select_circle", + type=params.select_tweak if fallback else params.tool_mouse, + value='ANY' if fallback else 'PRESS', + properties=[("wait_for_input", False)])), + # No selection fallback since this operates on press. + ]}, ) -def km_image_editor_tool_uv_select_lasso(params): +def km_image_editor_tool_uv_select_lasso(params, *, fallback): return ( - "Image Editor Tool: Uv, Select Lasso", + _fallback_id("Image Editor Tool: Uv, Select Lasso", fallback), {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple("uv.select_lasso", type=params.tool_tweak, value='ANY')}, + + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "uv.select_lasso", + type=params.select_tweak if fallback else params.tool_tweak, + value='ANY') + ), + *_template_uv_select_for_fallback(params, fallback), + ]}, ) @@ -5923,47 +6043,53 @@ def km_image_editor_tool_uv_scale(params): ) -def km_node_editor_tool_select(params): +def km_node_editor_tool_select(params, *, fallback): return ( - "Node Tool: Tweak", + _fallback_id("Node Tool: Tweak", fallback), {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'}, {"items": [ - ("node.select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("deselect_all", not params.legacy)]}), + *([] if fallback else [ + ("node.select", {"type": params.select_mouse, "value": 'PRESS'}, + {"properties": [("deselect_all", not params.legacy)]}), + ]), ]}, ) -def km_node_editor_tool_select_box(params): +def km_node_editor_tool_select_box(params, *, fallback): return ( - "Node Tool: Select Box", + _fallback_id("Node Tool: Select Box", fallback), {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "node.select_box", type=params.tool_tweak, value='ANY', - properties=[("tweak", True)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "node.select_box", type=params.tool_tweak, value='ANY', + properties=[("tweak", True)], + )), + ]}, ) -def km_node_editor_tool_select_lasso(params): +def km_node_editor_tool_select_lasso(params, *, fallback): return ( - "Node Tool: Select Lasso", + _fallback_id("Node Tool: Select Lasso", fallback), {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "node.select_lasso", type=params.tool_mouse, value='PRESS', - properties=[("tweak", True)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "node.select_lasso", type=params.tool_mouse, value='PRESS', + properties=[("tweak", True)])) + ]}, ) -def km_node_editor_tool_select_circle(params): +def km_node_editor_tool_select_circle(params, *, fallback): return ( - "Node Tool: Select Circle", + _fallback_id("Node Tool: Select Circle", fallback), {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "node.select_circle", type=params.tool_mouse, value='PRESS', - properties=[("wait_for_input", False)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "node.select_circle", type=params.tool_mouse, value='PRESS', + properties=[("wait_for_input", False)])), + ]}, ) @@ -5989,38 +6115,61 @@ def km_3d_view_tool_cursor(params): ) -def km_3d_view_tool_select(params): +def km_3d_view_tool_select(params, *, fallback): return ( - "3D View Tool: Tweak", + _fallback_id("3D View Tool: Tweak", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select(params, "view3d.select", "view3d.cursor3d", extend="toggle")}, + {"items": [ + *([] if fallback else _template_items_tool_select( + params, "view3d.select", "view3d.cursor3d", extend="toggle")), + *([] if (not params.use_fallback_tool_rmb) else _template_view3d_select( + type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), + ]}, ) -def km_3d_view_tool_select_box(params): +def km_3d_view_tool_select_box(params, *, fallback): return ( - "3D View Tool: Select Box", + _fallback_id("3D View Tool: Select Box", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions("view3d.select_box", type=params.tool_tweak, value='ANY')}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions( + "view3d.select_box", + type=params.select_tweak if fallback else params.tool_tweak, + value='ANY')), + *_template_view3d_select_for_fallback(params, fallback), + ]}, ) -def km_3d_view_tool_select_circle(params): +def km_3d_view_tool_select_circle(params, *, fallback): return ( - "3D View Tool: Select Circle", + _fallback_id("3D View Tool: Select Circle", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "view3d.select_circle", type=params.tool_mouse, value='PRESS', - properties=[("wait_for_input", False)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "view3d.select_circle", + # Why circle select should be used on tweak? + # So that RMB or Shift-RMB is still able to set an element as active. + type=params.select_tweak if fallback else params.tool_mouse, + value='ANY' if fallback else 'PRESS', + properties=[("wait_for_input", False)])), + # No selection fallback since this operates on press. + ]}, ) -def km_3d_view_tool_select_lasso(params): +def km_3d_view_tool_select_lasso(params, *, fallback): return ( - "3D View Tool: Select Lasso", + _fallback_id("3D View Tool: Select Lasso", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions("view3d.select_lasso", type=params.tool_tweak, value='ANY')}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions( + "view3d.select_lasso", + type=params.select_tweak if fallback else params.tool_tweak, + value='ANY')), + *_template_view3d_select_for_fallback(params, fallback), + ]} ) @@ -6845,38 +6994,57 @@ def km_3d_view_tool_paint_gpencil_interpolate(params): ]}, ) -def km_3d_view_tool_edit_gpencil_select(params): +def km_3d_view_tool_edit_gpencil_select(params, *, fallback): return ( - "3D View Tool: Edit Gpencil, Tweak", + _fallback_id("3D View Tool: Edit Gpencil, Tweak", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select(params, "gpencil.select", "view3d.cursor3d", extend="toggle")}, + {"items": [ + *([] if fallback else _template_items_tool_select( + params, "gpencil.select", "view3d.cursor3d", extend="toggle")), + *([] if (not params.use_fallback_tool_rmb) else _template_view3d_gpencil_select( + type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), + ]}, ) - -def km_3d_view_tool_edit_gpencil_select_box(params): +def km_3d_view_tool_edit_gpencil_select_box(params, *, fallback): return ( - "3D View Tool: Edit Gpencil, Select Box", + _fallback_id("3D View Tool: Edit Gpencil, Select Box", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions("gpencil.select_box", type=params.tool_tweak, value='ANY')}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions( + "gpencil.select_box", type=params.select_tweak if fallback else params.tool_tweak, value='ANY')), + *_template_view3d_gpencil_select_for_fallback(params, fallback), + ]}, ) - -def km_3d_view_tool_edit_gpencil_select_circle(params): +def km_3d_view_tool_edit_gpencil_select_circle(params, *, fallback): return ( - "3D View Tool: Edit Gpencil, Select Circle", + _fallback_id("3D View Tool: Edit Gpencil, Select Circle", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions_simple( - "gpencil.select_circle", type=params.tool_mouse, value='PRESS', - properties=[("wait_for_input", False)], - )}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple( + "gpencil.select_circle", + # Why circle select should be used on tweak? + # So that RMB or Shift-RMB is still able to set an element as active. + type=params.select_tweak if fallback else params.tool_mouse, + value='ANY' if fallback else 'PRESS', + properties=[("wait_for_input", False)])), + # No selection fallback since this operates on press. + ]}, ) -def km_3d_view_tool_edit_gpencil_select_lasso(params): +def km_3d_view_tool_edit_gpencil_select_lasso(params, *, fallback): return ( - "3D View Tool: Edit Gpencil, Select Lasso", + _fallback_id("3D View Tool: Edit Gpencil, Select Lasso", fallback), {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select_actions("gpencil.select_lasso", type=params.tool_tweak, value='ANY')}, + {"items": [ + *([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions( + "gpencil.select_lasso", + type=params.select_tweak if fallback else params.tool_tweak, + value='ANY')), + *_template_view3d_gpencil_select_for_fallback(params, fallback), + ]} ) @@ -7184,25 +7352,25 @@ def generate_keymaps(params=None): km_image_editor_tool_generic_sample(params), km_image_editor_tool_uv_cursor(params), - km_image_editor_tool_uv_select(params), - km_image_editor_tool_uv_select_box(params), - km_image_editor_tool_uv_select_circle(params), - km_image_editor_tool_uv_select_lasso(params), + *(km_image_editor_tool_uv_select(params, fallback=fallback) for fallback in (False, True)), + *(km_image_editor_tool_uv_select_box(params, fallback=fallback) for fallback in (False, True)), + *(km_image_editor_tool_uv_select_circle(params, fallback=fallback) for fallback in (False, True)), + *(km_image_editor_tool_uv_select_lasso(params, fallback=fallback) for fallback in (False, True)), km_image_editor_tool_uv_rip_region(params), km_image_editor_tool_uv_sculpt_stroke(params), km_image_editor_tool_uv_move(params), km_image_editor_tool_uv_rotate(params), km_image_editor_tool_uv_scale(params), - km_node_editor_tool_select(params), - km_node_editor_tool_select_box(params), - km_node_editor_tool_select_lasso(params), - km_node_editor_tool_select_circle(params), + *(km_node_editor_tool_select(params, fallback=fallback) for fallback in (False, True)), + *(km_node_editor_tool_select_box(params, fallback=fallback) for fallback in (False, True)), + *(km_node_editor_tool_select_lasso(params, fallback=fallback) for fallback in (False, True)), + *(km_node_editor_tool_select_circle(params, fallback=fallback) for fallback in (False, True)), km_node_editor_tool_links_cut(params), km_3d_view_tool_cursor(params), - km_3d_view_tool_select(params), - km_3d_view_tool_select_box(params), - km_3d_view_tool_select_circle(params), - km_3d_view_tool_select_lasso(params), + *(km_3d_view_tool_select(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_select_box(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_select_circle(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_select_lasso(params, fallback=fallback) for fallback in (False, True)), km_3d_view_tool_transform(params), km_3d_view_tool_move(params), km_3d_view_tool_rotate(params), @@ -7273,10 +7441,10 @@ def generate_keymaps(params=None): km_3d_view_tool_paint_gpencil_cutter(params), km_3d_view_tool_paint_gpencil_eyedropper(params), km_3d_view_tool_paint_gpencil_interpolate(params), - km_3d_view_tool_edit_gpencil_select(params), - km_3d_view_tool_edit_gpencil_select_box(params), - km_3d_view_tool_edit_gpencil_select_circle(params), - km_3d_view_tool_edit_gpencil_select_lasso(params), + *(km_3d_view_tool_edit_gpencil_select(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_edit_gpencil_select_box(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_edit_gpencil_select_circle(params, fallback=fallback) for fallback in (False, True)), + *(km_3d_view_tool_edit_gpencil_select_lasso(params, fallback=fallback) for fallback in (False, True)), km_3d_view_tool_edit_gpencil_extrude(params), km_3d_view_tool_edit_gpencil_radius(params), km_3d_view_tool_edit_gpencil_bend(params), diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index 28549098e51..1c3dbded083 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -118,6 +118,8 @@ ToolDef = namedtuple( "draw_settings", # Optional draw cursor. "draw_cursor", + # Various options, see: `bpy.types.WorkSpaceTool.setup` options argument. + "options", ) ) del namedtuple @@ -133,6 +135,7 @@ def from_dict(kw_args): "description": None, "icon": None, "cursor": None, + "options": None, "widget": None, "widget_properties": None, "keymap": None, @@ -536,6 +539,7 @@ class ToolSelectPanelHelper: visited.add(km_name) yield (km_name, cls.bl_space_type, 'WINDOW', []) + yield (km_name + " (fallback)", cls.bl_space_type, 'WINDOW', []) # ------------------------------------------------------------------------- # Layout Generators @@ -988,16 +992,22 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): gizmo_group = item.widget or "" + idname_fallback = (item_fallback and item_fallback.idname) or "" + keymap_fallback = (item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "" + if keymap_fallback: + keymap_fallback = keymap_fallback + " (fallback)" + tool.setup( idname=item.idname, keymap=item.keymap[0] if item.keymap is not None else "", cursor=item.cursor or 'DEFAULT', + options=item.options or set(), gizmo_group=gizmo_group, data_block=item.data_block or "", operator=item.operator or "", index=index, - idname_fallback=(item_fallback and item_fallback.idname) or "", - keymap_fallback=(item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "", + idname_fallback=idname_fallback, + keymap_fallback=keymap_fallback, ) if ( diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index c5191e80aef..a513ab4b2d4 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -105,6 +105,7 @@ class _defs_view3d_generic: icon="ops.generic.cursor", keymap="3D View Tool: Cursor", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -143,6 +144,7 @@ class _defs_view3d_generic: icon="ops.view3d.ruler", widget="VIEW3D_GGT_ruler", keymap="3D View Tool: Measure", + options={'KEYMAP_FALLBACK'}, ) @@ -237,6 +239,7 @@ class _defs_annotate: cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn.with_args(draw_settings=draw_settings_common) @@ -248,6 +251,7 @@ class _defs_annotate: cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate Line", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn.with_args(draw_settings=draw_settings_common) @@ -259,6 +263,7 @@ class _defs_annotate: cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate Polygon", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -274,6 +279,7 @@ class _defs_annotate: cursor='ERASER', keymap="Generic Tool: Annotate Eraser", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @@ -543,6 +549,7 @@ class _defs_view3d_add: widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -569,6 +576,7 @@ class _defs_view3d_add: widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -594,6 +602,7 @@ class _defs_view3d_add: widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -619,6 +628,7 @@ class _defs_view3d_add: widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -643,6 +653,7 @@ class _defs_view3d_add: widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @@ -1089,6 +1100,7 @@ class _defs_edit_mesh: widget=None, keymap=(), draw_settings=draw_settings, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -1695,6 +1707,7 @@ class _defs_image_generic: ), icon="ops.generic.cursor", keymap=(), + options={'KEYMAP_FALLBACK'}, ) # Currently a place holder so we can switch away from the annotation tool. @@ -1846,6 +1859,7 @@ class _defs_image_uv_edit: # TODO: generic operator (UV version of `VIEW3D_GGT_tool_generic_handle_free`). widget=None, keymap=(), + options={'KEYMAP_FALLBACK'}, ) @@ -1879,6 +1893,7 @@ class _defs_image_uv_sculpt: operator="sculpt.uv_sculpt_stroke", keymap="Image Editor Tool: Uv, Sculpt Stroke", draw_cursor=draw_cursor, + options={'KEYMAP_FALLBACK'}, ), ) diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 672f1b64943..3a5d65475f7 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -350,24 +350,28 @@ static void menu_types_add_from_keymap_items(bContext *C, if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll(C, keymap)) { - LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { - if (kmi->flag & KMI_INACTIVE) { - continue; - } - if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { - char menu_idname[MAX_NAME]; - RNA_string_get(kmi->ptr, "name", menu_idname); - MenuType *mt = WM_menutype_find(menu_idname, false); - - if (mt && BLI_gset_add(menu_tagged, mt)) { - /* Unlikely, but possible this will be included twice. */ - BLI_linklist_prepend(menuid_stack_p, mt); - - void **kmi_p; - if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { - *kmi_p = kmi; + wmEventHandler_KeymapResult km_result; + WM_event_get_keymaps_from_handler(wm, handler, &km_result); + for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { + wmKeyMap *keymap = km_result.keymaps[km_index]; + if (keymap && WM_keymap_poll(C, keymap)) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { + if (kmi->flag & KMI_INACTIVE) { + continue; + } + if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { + char menu_idname[MAX_NAME]; + RNA_string_get(kmi->ptr, "name", menu_idname); + MenuType *mt = WM_menutype_find(menu_idname, false); + + if (mt && BLI_gset_add(menu_tagged, mt)) { + /* Unlikely, but possible this will be included twice. */ + BLI_linklist_prepend(menuid_stack_p, mt); + + void **kmi_p; + if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { + *kmi_p = kmi; + } } } } diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index ae37d6c8deb..5faafa77bba 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -461,7 +461,7 @@ void MESH_GGT_spin(struct wmGizmoGroupType *gzgt) gzgt->name = "Mesh Spin Init"; gzgt->idname = "MESH_GGT_spin"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_3D; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -1063,7 +1063,7 @@ void MESH_GGT_spin_redo(struct wmGizmoGroupType *gzgt) gzgt->name = "Mesh Spin Redo"; gzgt->idname = "MESH_GGT_spin_redo"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_3D; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 9546035375c..c71e68df2fd 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1735,10 +1735,14 @@ static void ed_default_handlers( WM_event_add_keymap_handler(handlers, keymap); } if (flag & ED_KEYMAP_TOOL) { - WM_event_add_keymap_handler_dynamic( - ®ion->handlers, WM_event_get_keymap_from_toolsystem_fallback, area); - WM_event_add_keymap_handler_dynamic( - ®ion->handlers, WM_event_get_keymap_from_toolsystem, area); + if (flag & ED_KEYMAP_GIZMO) { + WM_event_add_keymap_handler_dynamic( + ®ion->handlers, WM_event_get_keymap_from_toolsystem_fallback, area); + } + else { + WM_event_add_keymap_handler_dynamic( + ®ion->handlers, WM_event_get_keymap_from_toolsystem, area); + } } if (flag & ED_KEYMAP_FRAMES) { /* frame changing/jumping (for all spaces) */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c index 441182d7a5f..918ecb14752 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c @@ -58,7 +58,7 @@ void VIEW3D_GGT_mesh_preselect_elem(wmGizmoGroupType *gzgt) gzgt->name = "Mesh Preselect Element"; gzgt->idname = "VIEW3D_GGT_mesh_preselect_elem"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_3D; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; @@ -95,7 +95,7 @@ void VIEW3D_GGT_mesh_preselect_edgering(wmGizmoGroupType *gzgt) gzgt->name = "Mesh Preselect Edge Ring"; gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_3D; gzgt->gzmap_params.spaceid = SPACE_VIEW3D; gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index e0294d3534c..a0856588a58 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -29,6 +29,15 @@ extern "C" { #endif +/** #bToolRef_Runtime.flag */ +enum { + /** + * This tool should use the fallback key-map. + * Typically gizmos handle this but some tools (such as the knife tool) don't use a gizmo. + */ + TOOLREF_FLAG_FALLBACK_KEYMAP = (1 << 0), +}; + # # typedef struct bToolRef_Runtime { @@ -47,6 +56,8 @@ typedef struct bToolRef_Runtime { /** Index when a tool is a member of a group. */ int index; + /** Options: `TOOLREF_FLAG_*`. */ + int flag; } bToolRef_Runtime; /* Stored per mode. */ diff --git a/source/blender/makesrna/intern/rna_workspace_api.c b/source/blender/makesrna/intern/rna_workspace_api.c index a2bb89dd5ee..15230f1198b 100644 --- a/source/blender/makesrna/intern/rna_workspace_api.c +++ b/source/blender/makesrna/intern/rna_workspace_api.c @@ -29,6 +29,7 @@ #include "DNA_object_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "RNA_enum_types.h" /* own include */ @@ -51,6 +52,7 @@ static void rna_WorkSpaceTool_setup(ID *id, const char *data_block, const char *op_idname, int index, + int options, const char *idname_fallback, const char *keymap_fallback) { @@ -62,6 +64,7 @@ static void rna_WorkSpaceTool_setup(ID *id, STRNCPY(tref_rt.data_block, data_block); STRNCPY(tref_rt.op, op_idname); tref_rt.index = index; + tref_rt.flag = options; /* While it's logical to assign both these values from setup, * it's useful to stored this in DNA for re-use, exceptional case: write to the 'tref'. */ @@ -131,6 +134,11 @@ void RNA_api_workspace_tool(StructRNA *srna) PropertyRNA *parm; FunctionRNA *func; + static EnumPropertyItem options_items[] = { + {TOOLREF_FLAG_FALLBACK_KEYMAP, "KEYMAP_FALLBACK", 0, "Fallback", ""}, + {0, NULL, 0, NULL, NULL}, + }; + func = RNA_def_function(srna, "setup", "rna_WorkSpaceTool_setup"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Set the tool settings"); @@ -146,6 +154,7 @@ void RNA_api_workspace_tool(StructRNA *srna) RNA_def_string(func, "data_block", NULL, MAX_NAME, "Data Block", ""); RNA_def_string(func, "operator", NULL, MAX_NAME, "Operator", ""); RNA_def_int(func, "index", 0, INT_MIN, INT_MAX, "Index", "", INT_MIN, INT_MAX); + RNA_def_enum_flag(func, "options", options_items, 0, "Tool Options", ""); RNA_def_string(func, "idname_fallback", NULL, MAX_NAME, "Fallback Identifier", ""); RNA_def_string(func, "keymap_fallback", NULL, KMAP_MAX_NAME, "Fallback Key Map", ""); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 28d3cb326ae..4fe1530628b 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -262,14 +262,21 @@ struct wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *han wmKeyMap *keymap, int priority); -typedef struct wmKeyMap *(wmEventHandler_KeymapDynamicFn)(wmWindowManager *wm, - struct wmEventHandler_Keymap *handler) - ATTR_WARN_UNUSED_RESULT; - -struct wmKeyMap *WM_event_get_keymap_from_toolsystem_fallback( - struct wmWindowManager *wm, struct wmEventHandler_Keymap *handler); -struct wmKeyMap *WM_event_get_keymap_from_toolsystem(struct wmWindowManager *wm, - struct wmEventHandler_Keymap *handler); +typedef struct wmEventHandler_KeymapResult { + wmKeyMap *keymaps[3]; + int keymaps_len; +} wmEventHandler_KeymapResult; + +typedef void(wmEventHandler_KeymapDynamicFn)(wmWindowManager *wm, + struct wmEventHandler_Keymap *handler, + struct wmEventHandler_KeymapResult *km_result); + +void WM_event_get_keymap_from_toolsystem_fallback(struct wmWindowManager *wm, + struct wmEventHandler_Keymap *handler, + wmEventHandler_KeymapResult *km_result); +void WM_event_get_keymap_from_toolsystem(struct wmWindowManager *wm, + struct wmEventHandler_Keymap *handler, + wmEventHandler_KeymapResult *km_result); struct wmEventHandler_Keymap *WM_event_add_keymap_handler_dynamic( ListBase *handlers, wmEventHandler_KeymapDynamicFn *keymap_fn, void *user_data); @@ -281,8 +288,9 @@ void WM_event_set_keymap_handler_post_callback(struct wmEventHandler_Keymap *han wmKeyMapItem *kmi, void *user_data), void *user_data); -wmKeyMap *WM_event_get_keymap_from_handler(wmWindowManager *wm, - struct wmEventHandler_Keymap *handler); +void WM_event_get_keymaps_from_handler(wmWindowManager *wm, + struct wmEventHandler_Keymap *handler, + struct wmEventHandler_KeymapResult *km_result); wmKeyMapItem *WM_event_match_keymap_item(struct bContext *C, wmKeyMap *keymap, diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index 213a3c2e342..22bdf65a169 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -265,6 +265,8 @@ void WM_gizmogroup_ensure_init(const bContext *C, wmGizmoGroup *gzgroup) { /* prepare for first draw */ if (UNLIKELY((gzgroup->init_flag & WM_GIZMOGROUP_INIT_SETUP) == 0)) { + + gzgroup->use_fallback_keymap = true; gzgroup->type->setup(C, gzgroup); /* Not ideal, initialize keymap here, needed for RNA runtime generated gizmos. */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ae09786356a..14fcc1d69cc 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2989,9 +2989,18 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers /* Handle all types here. */ if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - action |= wm_handlers_do_keymap_with_keymap_handler( - C, event, handlers, handler, keymap, do_debug_handler); + wmEventHandler_KeymapResult km_result; + WM_event_get_keymaps_from_handler(wm, handler, &km_result); + int action_iter = WM_HANDLER_CONTINUE; + for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { + wmKeyMap *keymap = km_result.keymaps[km_index]; + action_iter |= wm_handlers_do_keymap_with_keymap_handler( + C, event, handlers, handler, keymap, do_debug_handler); + if (action_iter & WM_HANDLER_BREAK) { + break; + } + } + action |= action_iter; /* Clear the tool-tip whenever a key binding is handled, without this tool-tips * are kept when a modal operators starts (annoying but otherwise harmless). */ @@ -3905,17 +3914,34 @@ wmEventHandler_Keymap *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap * * Follow #wmEventHandler_KeymapDynamicFn signature. */ -wmKeyMap *WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, - wmEventHandler_Keymap *handler) +void WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, + wmEventHandler_Keymap *handler, + wmEventHandler_KeymapResult *km_result) { + memset(km_result, 0x0, sizeof(*km_result)); + + const char *keymap_id_list[ARRAY_SIZE(km_result->keymaps)]; + int keymap_id_list_len = 0; + ScrArea *area = handler->dynamic.user_data; handler->keymap_tool = NULL; bToolRef_Runtime *tref_rt = area->runtime.tool ? area->runtime.tool->runtime : NULL; - if (tref_rt && tref_rt->keymap_fallback[0]) { - const char *keymap_id = NULL; + if (tref_rt && tref_rt->keymap[0]) { + keymap_id_list[keymap_id_list_len++] = tref_rt->keymap; + } + + bool is_gizmo_visible = false; + bool is_gizmo_highlight = false; + + if (tref_rt && tref_rt->keymap_fallback[0]) { + bool add_keymap = false; /* Support for the gizmo owning the tool keymap. */ - if (tref_rt->gizmo_group[0] != '\0' && tref_rt->keymap_fallback[0] != '\0') { + + if (tref_rt->flag & TOOLREF_FLAG_FALLBACK_KEYMAP) { + add_keymap = true; + } + if (tref_rt->gizmo_group[0] != '\0') { wmGizmoMap *gzmap = NULL; wmGizmoGroup *gzgroup = NULL; LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { @@ -3931,32 +3957,49 @@ wmKeyMap *WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, if (gzgroup->type->flag & WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP) { /* If all are hidden, don't override. */ if (gzgroup->use_fallback_keymap) { + is_gizmo_visible = true; wmGizmo *highlight = wm_gizmomap_highlight_get(gzmap); - if (highlight == NULL) { - keymap_id = tref_rt->keymap_fallback; + if (highlight) { + is_gizmo_highlight = true; } + add_keymap = true; } } } } + if (add_keymap) { + keymap_id_list[keymap_id_list_len++] = tref_rt->keymap_fallback; + } + } - if (keymap_id && keymap_id[0]) { - wmKeyMap *km = WM_keymap_list_find_spaceid_or_empty( - &wm->userconf->keymaps, keymap_id, area->spacetype, RGN_TYPE_WINDOW); - /* We shouldn't use keymaps from unrelated spaces. */ - if (km != NULL) { - handler->keymap_tool = area->runtime.tool; - return km; - } - printf( - "Keymap: '%s' not found for tool '%s'\n", tref_rt->keymap, area->runtime.tool->idname); + if (is_gizmo_visible && !is_gizmo_highlight) { + if (keymap_id_list_len == 2) { + SWAP(const char *, keymap_id_list[0], keymap_id_list[1]); } } - return NULL; + + for (int i = 0; i < keymap_id_list_len; i++) { + const char *keymap_id = keymap_id_list[i]; + BLI_assert(keymap_id && keymap_id[0]); + + wmKeyMap *km = WM_keymap_list_find_spaceid_or_empty( + &wm->userconf->keymaps, keymap_id, area->spacetype, RGN_TYPE_WINDOW); + /* We shouldn't use keymaps from unrelated spaces. */ + if (km == NULL) { + printf("Keymap: '%s' not found for tool '%s'\n", keymap_id, area->runtime.tool->idname); + continue; + } + handler->keymap_tool = area->runtime.tool; + km_result->keymaps[km_result->keymaps_len++] = km; + } } -wmKeyMap *WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, wmEventHandler_Keymap *handler) +void WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, + wmEventHandler_Keymap *handler, + wmEventHandler_KeymapResult *km_result) { + memset(km_result, 0x0, sizeof(*km_result)); + ScrArea *area = handler->dynamic.user_data; handler->keymap_tool = NULL; bToolRef_Runtime *tref_rt = area->runtime.tool ? area->runtime.tool->runtime : NULL; @@ -3968,13 +4011,14 @@ wmKeyMap *WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, wmEventHandle /* We shouldn't use keymaps from unrelated spaces. */ if (km != NULL) { handler->keymap_tool = area->runtime.tool; - return km; + km_result->keymaps[km_result->keymaps_len++] = km; + } + else { + printf( + "Keymap: '%s' not found for tool '%s'\n", tref_rt->keymap, area->runtime.tool->idname); } - printf( - "Keymap: '%s' not found for tool '%s'\n", tref_rt->keymap, area->runtime.tool->idname); } } - return NULL; } struct wmEventHandler_Keymap *WM_event_add_keymap_handler_dynamic( @@ -5088,18 +5132,22 @@ void WM_set_locked_interface(wmWindowManager *wm, bool lock) /** \name Event / Keymap Matching API * \{ */ -wmKeyMap *WM_event_get_keymap_from_handler(wmWindowManager *wm, wmEventHandler_Keymap *handler) +void WM_event_get_keymaps_from_handler(wmWindowManager *wm, + wmEventHandler_Keymap *handler, + wmEventHandler_KeymapResult *km_result) { - wmKeyMap *keymap; if (handler->dynamic.keymap_fn != NULL) { - keymap = handler->dynamic.keymap_fn(wm, handler); + handler->dynamic.keymap_fn(wm, handler, km_result); BLI_assert(handler->keymap == NULL); } else { - keymap = WM_keymap_active(wm, handler->keymap); + memset(km_result, 0x0, sizeof(*km_result)); + wmKeyMap *keymap = WM_keymap_active(wm, handler->keymap); BLI_assert(keymap != NULL); + if (keymap != NULL) { + km_result->keymaps[km_result->keymaps_len++] = keymap; + } } - return keymap; } wmKeyMapItem *WM_event_match_keymap_item(bContext *C, wmKeyMap *keymap, const wmEvent *event) @@ -5128,11 +5176,15 @@ wmKeyMapItem *WM_event_match_keymap_item_from_handlers(bContext *C, else if (handler_base->poll == NULL || handler_base->poll(CTX_wm_region(C), event)) { if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll(C, keymap)) { - wmKeyMapItem *kmi = WM_event_match_keymap_item(C, keymap, event); - if (kmi != NULL) { - return kmi; + wmEventHandler_KeymapResult km_result; + WM_event_get_keymaps_from_handler(wm, handler, &km_result); + for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { + wmKeyMap *keymap = km_result.keymaps[km_index]; + if (WM_keymap_poll(C, keymap)) { + wmKeyMapItem *kmi = WM_event_match_keymap_item(C, keymap, event); + if (kmi != NULL) { + return kmi; + } } } } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index f955abaed53..e5aedfc7f47 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -462,7 +462,9 @@ bool WM_keymap_poll(bContext *C, wmKeyMap *keymap) /* Empty key-maps may be missing more there may be a typo in the name. * Warn early to avoid losing time investigating each case. * When developing a customized Blender though you may want empty keymaps. */ - if (!U.app_template[0]) { + if (!U.app_template[0] && + /* Fallback key-maps may be intentionally empty, don't flood the output. */ + !BLI_str_endswith(keymap->idname, " (fallback)")) { CLOG_WARN(WM_LOG_KEYMAPS, "empty keymap '%s'", keymap->idname); } } @@ -1402,15 +1404,19 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll((bContext *)C, keymap)) { - wmKeyMapItem *kmi = wm_keymap_item_find_in_keymap( - keymap, opname, properties, is_strict, params); - if (kmi != NULL) { - if (r_keymap) { - *r_keymap = keymap; + wmEventHandler_KeymapResult km_result; + WM_event_get_keymaps_from_handler(wm, handler, &km_result); + for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { + wmKeyMap *keymap = km_result.keymaps[km_index]; + if (WM_keymap_poll((bContext *)C, keymap)) { + wmKeyMapItem *kmi = wm_keymap_item_find_in_keymap( + keymap, opname, properties, is_strict, params); + if (kmi != NULL) { + if (r_keymap) { + *r_keymap = keymap; + } + return kmi; } - return kmi; } } } diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 5eaf026191f..0c24520d565 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -326,7 +326,10 @@ void WM_toolsystem_ref_set_from_runtime(struct bContext *C, bool use_fallback_keymap = false; if (tref->idname_fallback[0] || tref->runtime->keymap_fallback[0]) { - if (tref_rt->gizmo_group[0]) { + if (tref_rt->flag & TOOLREF_FLAG_FALLBACK_KEYMAP) { + use_fallback_keymap = true; + } + else if (tref_rt->gizmo_group[0]) { wmGizmoGroupType *gzgt = WM_gizmogrouptype_find(tref_rt->gizmo_group, false); if (gzgt) { if (gzgt->flag & WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP) { |