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.
This commit is contained in:
Campbell Barton 2018-05-30 22:15:10 +02:00
parent 264a4a8f97
commit 16d3f4db4c
2 changed files with 79 additions and 24 deletions

View File

@ -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.")

View File

@ -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):