WM: Operator to set the tool by name

Needed to bind keys to tools (T55036).
This commit is contained in:
2018-05-13 08:59:50 +02:00
parent 03281c080c
commit cee39da318
2 changed files with 115 additions and 36 deletions

View File

@@ -2326,6 +2326,25 @@ class WM_OT_app_template_install(Operator):
return {'RUNNING_MODAL'}
class WM_OT_tool_set_by_name(Operator):
"""Set the tool by name (for keymaps)"""
bl_idname = "wm.tool_set_by_name"
bl_label = "Set Tool By Name"
name = StringProperty(
name="Text",
description="Display name of the tool",
)
def execute(self, context):
from bl_ui.space_toolsystem_common import activate_by_name
if activate_by_name(context, self.name):
return {'FINISHED'}
else:
self.report({'WARNING'}, f"Tool {self.name!r} not found.")
return {'CANCELLED'}
classes = (
BRUSH_OT_active_index_set,
WM_OT_addon_disable,
@@ -2380,4 +2399,5 @@ classes = (
WM_OT_owner_disable,
WM_OT_owner_enable,
WM_OT_url_open,
WM_OT_tool_set_by_name,
)

View File

@@ -39,6 +39,7 @@ if "_icon_cache" in locals():
# (filename -> icon_value) map
_icon_cache = {}
def _keymap_fn_from_seq(keymap_data):
# standalone
@@ -91,6 +92,7 @@ ToolDef = namedtuple(
)
del namedtuple
def from_dict(kw_args):
"""
Use so each tool can avoid defining all members of the named tuple.
@@ -116,6 +118,7 @@ def from_dict(kw_args):
kw["keymap"] = keymap
return ToolDef(**kw)
def from_fn(fn):
"""
Use as decorator so we can define functions.
@@ -186,11 +189,13 @@ class ToolSelectPanelHelper:
Flattens, skips None and calls generators.
"""
for item in tools:
if item is not None:
if type(item) is tuple:
if item is None:
yield None
elif type(item) is tuple:
for sub_item in item:
if sub_item is not None:
if _item_is_fn(sub_item):
if sub_item is None:
yield None
elif _item_is_fn(sub_item):
yield from sub_item(context)
else:
yield sub_item
@@ -200,6 +205,68 @@ class ToolSelectPanelHelper:
else:
yield item
@staticmethod
def _tools_flatten_with_tool_index(tools):
for item in tools:
if item is None:
yield None, -1
elif type(item) is tuple:
i = 0
for sub_item in item:
if sub_item is None:
yield None
elif _item_is_fn(sub_item):
for item_dyn in sub_item(context):
yield item_dyn, i
i += 1
else:
yield sub_item, i
i += 1
else:
if _item_is_fn(item):
for item_dyn in item(context):
yield item_dyn, -1
else:
yield item, -1
@staticmethod
def _tool_get_active(context, with_icon=False):
"""
Return the active Python tool definition and icon name.
"""
workspace = context.workspace
cls = ToolSelectPanelHelper._tool_class_from_space_type(workspace.tool_space_type)
if cls is not None:
tool_def_active, index_active = ToolSelectPanelHelper._tool_vars_from_active_with_index(context)
context_mode = context.mode
for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context)):
if item is not None:
tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
if (tool_def == tool_def_active):
if with_icon:
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
else:
icon_value = 0
return (item, icon_value)
return None, 0
@staticmethod
def _tool_get_by_name(context, text):
"""
Return the active Python tool definition and index (if in sub-group, else -1).
"""
workspace = context.workspace
cls = ToolSelectPanelHelper._tool_class_from_space_type(workspace.tool_space_type)
if cls is not None:
context_mode = context.mode
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
@staticmethod
def _tool_vars_from_def(item, context_mode):
# For now be strict about whats in this dict
@@ -284,7 +351,6 @@ class ToolSelectPanelHelper:
icon_name = item.icon
cls._km_action_simple(kc, context_mode, text, keymap_data)
# -------------------------------------------------------------------------
# Layout Generators
#
@@ -455,31 +521,9 @@ class ToolSelectPanelHelper:
# Signal to finish any remaining layout edits.
ui_gen.send(None)
@staticmethod
def _active_tool(context, with_icon=False):
"""
Return the active Python tool definition and icon name.
"""
workspace = context.workspace
cls = ToolSelectPanelHelper._tool_class_from_space_type(workspace.tool_space_type)
if cls is not None:
tool_def_active, index_active = ToolSelectPanelHelper._tool_vars_from_active_with_index(context)
context_mode = context.mode
for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context)):
tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
if (tool_def == tool_def_active):
if with_icon:
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
else:
icon_value = 0
return (item, icon_value)
return None, 0
@staticmethod
def draw_active_tool_header(context, layout):
item, icon_value = ToolSelectPanelHelper._active_tool(context, with_icon=True)
item, icon_value = ToolSelectPanelHelper._tool_get_active(context, with_icon=True)
if item is None:
return
# Note: we could show 'item.text' here but it makes the layout jitter when switcuing tools.
@@ -541,6 +585,21 @@ class WM_MT_toolsystem_submenu(Menu):
index += 1
def activate_by_name(context, text):
item, index = ToolSelectPanelHelper._tool_get_by_name(context, text)
if item is not None:
context_mode = context.mode
tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
bpy.ops.wm.tool_set(
keymap=tool_def[0] or "",
manipulator_group=tool_def[1] or "",
data_block=tool_def[2] or "",
index=index,
)
return True
return False
classes = (
WM_MT_toolsystem_submenu,
)