WM: Operator to set the tool by name
Needed to bind keys to tools (T55036).
This commit is contained in:
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user