[Bf-blender-cvs] [de152d07248] master: Tool System: Use tapping Alt as a leader key to switch tools

Campbell Barton noreply at git.blender.org
Mon Oct 28 13:00:58 CET 2019


Commit: de152d072488d1f122b732feaad8b0b4f554f07d
Author: Campbell Barton
Date:   Mon Oct 28 22:43:15 2019 +1100
Branches: master
https://developer.blender.org/rBde152d072488d1f122b732feaad8b0b4f554f07d

Tool System: Use tapping Alt as a leader key to switch tools

Now tapping Alt prompts for a second input to switch tools.

Initial implementation of T69992

===================================================================

M	release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_operators/wm.py

===================================================================

diff --git a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
index bedad638dbe..da4a47783ad 100644
--- a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
+++ b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py
@@ -25,7 +25,7 @@ __all__ = (
     "generate",
 )
 
-def generate(context, space_type):
+def generate(context, space_type, use_fallback_keys=True, use_reset=True):
     """
     Keymap for popup toolbar, currently generated each time.
     """
@@ -66,7 +66,7 @@ def generate(context, space_type):
     # to 'drop' currently active tools (it's basically a 'none' tool).
     # so this allows us to quickly go back to a state that allows
     # a shortcut based workflow (before the tool system was added).
-    use_tap_reset = True
+    use_tap_reset = use_reset
     # TODO: support other tools for modes which don't use this tool.
     tap_reset_tool = "builtin.cursor"
     # Check the tool is available in the current context.
@@ -76,11 +76,11 @@ def generate(context, space_type):
     from bl_operators.wm import use_toolbar_release_hack
 
     # Pie-menu style release to activate.
-    use_release_confirm = True
+    use_release_confirm = use_reset
 
     # Generate items when no keys are mapped.
     use_auto_keymap_alpha = False  # Map manually in the default key-map.
-    use_auto_keymap_num = True
+    use_auto_keymap_num = use_fallback_keys
 
     # Temporary, only create so we can pass 'properties' to find_item_from_operator.
     use_hack_properties = True
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index d4c17c542e7..313feed9645 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -412,6 +412,9 @@ def km_window(params):
             ("wm.batch_rename", {"type": 'F2', "value": 'PRESS', "ctrl": True}, None),
             ("wm.search_menu", {"type": 'F3', "value": 'PRESS'}, None),
             op_menu("TOPBAR_MT_file_context_menu", {"type": 'F4', "value": 'PRESS'}),
+            # Alt as "Leader-Key".
+            ("wm.toolbar_prompt", {"type": 'LEFT_ALT', "value": 'CLICK'}, None),
+            ("wm.toolbar_prompt", {"type": 'RIGHT_ALT', "value": 'CLICK'}, None),
         ])
 
         if params.spacebar_action == 'TOOL':
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 13689b35748..037303a08e1 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1744,27 +1744,141 @@ class WM_OT_toolbar(Operator):
             WM_OT_toolbar._key_held = event.type
             return self.execute(context)
 
-    def execute(self, context):
+    @staticmethod
+    def keymap_from_toolbar(context, space_type, use_fallback_keys=True, use_reset=True):
         from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
         from bl_keymap_utils import keymap_from_toolbar
 
-        space_type = context.space_data.type
         cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
         if cls is None:
-            return {'CANCELLED'}
+            return None, None
 
-        wm = context.window_manager
-        keymap = keymap_from_toolbar.generate(context, space_type)
+        return cls, keymap_from_toolbar.generate(
+            context,
+            space_type,
+            use_fallback_keys=use_fallback_keys,
+            use_reset=use_reset,
+        )
+
+    def execute(self, context):
+        space_type = context.space_data.type
+        cls, keymap = self.keymap_from_toolbar(context, space_type)
+        if keymap is None:
+            return {'CANCELLED'}
 
         def draw_menu(popover, context):
             layout = popover.layout
             layout.operator_context = 'INVOKE_REGION_WIN'
             cls.draw_cls(layout, context, detect_layout=False, scale_y=1.0)
 
+        wm = context.window_manager
         wm.popover(draw_menu, ui_units_x=8, keymap=keymap)
         return {'FINISHED'}
 
 
+class WM_OT_toolbar_prompt(Operator):
+    """Leader key like functionality for accessing tools"""
+    bl_idname = "wm.toolbar_prompt"
+    bl_label = "Toolbar Prompt"
+
+    def modal(self, context, event):
+        event_type = event.type
+        event_value = event.value
+
+        keymap = self._keymap
+
+        if event_type in {'LEFTMOUSE', 'RIGHTMOUSE', 'MIDDLEMOUSE', 'ESC'}:
+            context.workspace.status_text_set(None)
+            return {'CANCELLED', 'PASS_THROUGH'}
+
+        item = keymap.keymap_items.match_event(event)
+        if item is not None:
+            idname = item.idname
+            properties = item.properties
+            if idname == "wm.tool_set_by_id":
+                tool_idname = properties["name"]
+                bpy.ops.wm.tool_set_by_id(name=tool_idname)
+
+            context.workspace.status_text_set(None)
+            return {'FINISHED'}
+
+        return {'RUNNING_MODAL'}
+
+    def invoke(self, context, event):
+        space_type = context.space_data.type
+        cls, keymap = WM_OT_toolbar.keymap_from_toolbar(
+            context,
+            space_type,
+            use_fallback_keys=False,
+            use_reset=False,
+        )
+        if keymap is None:
+            return {'CANCELLED'}
+
+        self._init_event_type = event.type
+
+        # Strip Left/Right, since "Left Alt" isn't especially useful.
+        init_event_type_as_text = self._init_event_type.title().split("_")
+        if init_event_type_as_text[0] in {"Left", "Right"}:
+            del init_event_type_as_text[0]
+        init_event_type_as_text = " ".join(init_event_type_as_text)
+
+        def status_text_fn(self, context):
+            from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
+
+            # The keymap doesn't have the same order the tools are declared in,
+            # while we could support this, it's simpler to apply order here.
+            tool_map_id_to_order = {}
+            # Map the
+            tool_map_id_to_label = {}
+            for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context)):
+                if item is not None:
+                    tool_map_id_to_label[item.idname] = item.label
+                    tool_map_id_to_order[item.idname] = len(tool_map_id_to_order)
+
+            layout = self.layout
+            if True:
+                box = layout.row(align=True).box()
+                box.scale_x = 0.8
+                box.label(text=init_event_type_as_text)
+
+            status_items = []
+
+            for item in keymap.keymap_items:
+                name = item.name
+                key_str = item.to_string()
+                # These are duplicated from regular numbers.
+                if key_str.startswith("Numpad "):
+                    continue
+                properties = item.properties
+                idname = item.idname
+                if idname == "wm.tool_set_by_id":
+                    tool_idname = properties["name"]
+                    name = tool_map_id_to_label[tool_idname]
+                    name = name.replace("Annotate ", "")
+                else:
+                    continue
+
+                status_items.append((tool_idname, name, item))
+
+            status_items.sort(
+                key=lambda a: tool_map_id_to_order[a[0]]
+            )
+
+            flow = layout.grid_flow(columns=len(status_items), align=True, row_major=True)
+
+            for _, name, item in status_items:
+                row = flow.row(align=True)
+                row.template_event_from_keymap_item(item, text=name)
+
+        self._keymap = keymap
+
+        context.workspace.status_text_set(status_text_fn)
+
+        context.window_manager.modal_handler_add(self)
+        return {'RUNNING_MODAL'}
+
+
 class BatchRenameAction(bpy.types.PropertyGroup):
     # category: StringProperty()
     type: EnumProperty(
@@ -2430,6 +2544,7 @@ classes = (
     WM_OT_tool_set_by_id,
     WM_OT_tool_set_by_index,
     WM_OT_toolbar,
+    WM_OT_toolbar_prompt,
     BatchRenameAction,
     WM_OT_batch_rename,
     WM_MT_splash,



More information about the Bf-blender-cvs mailing list