From 16d3f4db4cc663be928e9a33a6c659c6d3c95c3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 30 May 2018 22:15:10 +0200 Subject: Tool System: optionally cycle tools in a group Add the ability for key bindings to set a tool-group, which cycles to the next tool when the tool is already active. --- release/scripts/startup/bl_operators/wm.py | 33 +++++++--- .../startup/bl_ui/space_toolsystem_common.py | 70 +++++++++++++++++----- 2 files changed, 79 insertions(+), 24 deletions(-) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 021085b8d75..084f6f84791 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -55,6 +55,15 @@ rna_relative_prop = BoolProperty( default=False, ) +rna_space_type_prop = EnumProperty( + name="Type", + items=tuple( + (e.identifier, e.name, "", e. value) + for e in bpy.types.Space.bl_rna.properties["type"].enum_items + ), + default='EMPTY', + ) + def context_path_validate(context, data_path): try: @@ -2335,21 +2344,27 @@ class WM_OT_tool_set_by_name(Operator): name="Text", description="Display name of the tool", ) - space_type = EnumProperty( - name="Type", - items=tuple( - (e.identifier, e.name, "", e. value) - for e in bpy.types.Space.bl_rna.properties["type"].enum_items - ), - default='EMPTY', + + cycle = BoolProperty( + name="Cycle", + description="Cycle through tools in this group", + default=False, + options={'SKIP_SAVE'}, ) + space_type = rna_space_type_prop + def execute(self, context): - from bl_ui.space_toolsystem_common import activate_by_name + from bl_ui.space_toolsystem_common import ( + activate_by_name, + activate_by_name_or_cycle, + ) space_type = self.space_type if space_type == 'EMPTY': space_type = context.space_data.type - if activate_by_name(context, space_type, self.name): + + fn = activate_by_name_or_cycle if self.cycle else activate_by_name + if fn(context, space_type, self.name): return {'FINISHED'} else: self.report({'WARNING'}, f"Tool {self.name!r} not found.") diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index d8708781c59..cb6d3851d02 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -262,8 +262,8 @@ class ToolSelectPanelHelper: for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)): if item is not None: if item.text == text: - return (item, index) - return None, -1 + return (cls, item, index) + return None, None, -1 @staticmethod def _tool_active_from_context(context, space_type, mode=None, create=False): @@ -564,20 +564,60 @@ class WM_MT_toolsystem_submenu(Menu): ).name = item.text +def _activate_by_item(context, space_type, item, index): + tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True) + tool.setup( + name=item.text, + keymap=item.keymap[0].name if item.keymap is not None else "", + cursor=item.cursor or 'DEFAULT', + manipulator_group=item.widget or "", + data_block=item.data_block or "", + index=index, + ) + + def activate_by_name(context, space_type, text): - item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text) - if item is not None: - tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True) - tool.setup( - name=text, - keymap=item.keymap[0].name if item.keymap is not None else "", - cursor=item.cursor or 'DEFAULT', - manipulator_group=item.widget or "", - data_block=item.data_block or "", - index=index, - ) - return True - return False + cls, item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text) + if item is None: + return False + _activate_by_item(context, space_type, item, index) + return True + + +def activate_by_name_or_cycle(context, space_type, text, offset=1): + + # Only cycle when the active tool is activated again. + cls, item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text) + if item is None: + return False + + tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type) + text_active = getattr(tool_active, "name", None) + + text_current = "" + for item_group in cls.tools_from_context(context): + if type(item_group) is tuple: + index_current = cls._tool_group_active.get(item_group[0].text, 0) + ok = False + for i, sub_item in enumerate(item_group): + if sub_item.text == text: + text_current = item_group[index_current].text + break + if text_current: + break + + if text_current == "": + return activate_by_name(context, space_type, text) + if text_active != text_current: + return activate_by_name(context, space_type, text_current) + + index_found = (tool_active.index + offset) % len(item_group) + + cls._tool_group_active[item_group[0].text] = index_found + + item_found = item_group[index_found] + _activate_by_item(context, space_type, item_found, index_found) + return True def keymap_from_context(context, space_type): -- cgit v1.2.3