Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py1
-rw-r--r--release/scripts/presets/keyconfig/Blender.py16
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py416
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py14
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py15
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c40
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c4
-rw-r--r--source/blender/editors/screen/area.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect.c4
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h11
-rw-r--r--source/blender/makesrna/intern/rna_workspace_api.c9
-rw-r--r--source/blender/windowmanager/WM_api.h28
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c124
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c24
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c5
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(
- &region->handlers, WM_event_get_keymap_from_toolsystem_fallback, area);
- WM_event_add_keymap_handler_dynamic(
- &region->handlers, WM_event_get_keymap_from_toolsystem, area);
+ if (flag & ED_KEYMAP_GIZMO) {
+ WM_event_add_keymap_handler_dynamic(
+ &region->handlers, WM_event_get_keymap_from_toolsystem_fallback, area);
+ }
+ else {
+ WM_event_add_keymap_handler_dynamic(
+ &region->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) {