diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-10-28 14:43:15 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-10-28 14:59:59 +0300 |
commit | de152d072488d1f122b732feaad8b0b4f554f07d (patch) | |
tree | 0a0f1d89daf02d7bc50365ab18b2a7ae1ff5f3fd /release | |
parent | df9f1d91daec6c3a613dcc177104d55a7197fbc9 (diff) |
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
Diffstat (limited to 'release')
3 files changed, 127 insertions, 9 deletions
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, |