From 32c5c0928452411674aa47b5aad9e627a5ad940d Mon Sep 17 00:00:00 2001 From: Jaume Bellet Date: Fri, 9 Feb 2024 07:42:35 +0100 Subject: [PATCH 1/5] apply updated diff from https://archive.blender.org/developer/D10635 This patch allows to create a Callback function on python, that is being executed on operator change (set / unset) --- scripts/startup/bl_ui/space_toolsystem_common.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/startup/bl_ui/space_toolsystem_common.py b/scripts/startup/bl_ui/space_toolsystem_common.py index 119d99d2939..f89d2af1d9c 100644 --- a/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/scripts/startup/bl_ui/space_toolsystem_common.py @@ -106,10 +106,16 @@ ToolDef = namedtuple( "draw_cursor", # Various options, see: `bpy.types.WorkSpaceTool.setup` options argument. "options", + # Handlers + "handlers" ) ) del namedtuple +class ToolDefHandlers: + def __init__ (self): + self.set = [] + self.unset = [] def from_dict(kw_args): """ @@ -129,6 +135,7 @@ def from_dict(kw_args): "operator": None, "draw_settings": None, "draw_cursor": None, + "handlers" : ToolDefHandlers() } kw.update(kw_args) @@ -985,6 +992,9 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True) tool_fallback_id = cls.tool_fallback_id + curr_tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type) + curr_item, curr_index = cls._tool_get_by_id(context, getattr(curr_tool, "idname", None)) + if as_fallback: # To avoid complicating logic too much, isolate all fallback logic to this block. # This will set the tool again, using the item for the fallback instead of the primary tool. @@ -1031,6 +1041,12 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): if keymap_fallback: keymap_fallback = keymap_fallback + " (fallback)" + for cb in curr_item.handlers.unset: + cb() + + for cb in item.handlers.set: + cb() + tool.setup( idname=item.idname, keymap=item.keymap[0] if item.keymap is not None else "", -- 2.30.2 From 3143bab74e438787f6f725a558b3c3174ab681c8 Mon Sep 17 00:00:00 2001 From: Jaume Bellet Date: Sun, 11 Feb 2024 18:50:45 +0100 Subject: [PATCH 2/5] bpy.utils.register_tools return the registered tools. added a check before applying unset cb. May be set None when the tool does no exists, for example on blender restart and not being resistered on startup. --- scripts/modules/bpy/utils/__init__.py | 3 ++- scripts/startup/bl_ui/space_toolsystem_common.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/modules/bpy/utils/__init__.py b/scripts/modules/bpy/utils/__init__.py index a8ba8ad6de8..d6ef0c10164 100644 --- a/scripts/modules/bpy/utils/__init__.py +++ b/scripts/modules/bpy/utils/__init__.py @@ -904,7 +904,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): cls._km_action_simple(kc_default, kc, context_descr, tool_def.label, keymap_data) return tool_def - tool_converted = tool_from_class(tool_cls) + tool_created = tool_converted = tool_from_class(tool_cls) if group: # Create a new group @@ -956,6 +956,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): if not changed: tools.extend(tool_def_insert) + return tool_created def unregister_tool(tool_cls): space_type = tool_cls.bl_space_type diff --git a/scripts/startup/bl_ui/space_toolsystem_common.py b/scripts/startup/bl_ui/space_toolsystem_common.py index f89d2af1d9c..50714bc5d8c 100644 --- a/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/scripts/startup/bl_ui/space_toolsystem_common.py @@ -1041,8 +1041,9 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): if keymap_fallback: keymap_fallback = keymap_fallback + " (fallback)" - for cb in curr_item.handlers.unset: - cb() + if curr_item is not None: + for cb in curr_item.handlers.unset: + cb() for cb in item.handlers.set: cb() -- 2.30.2 From 67e3940432e0b00ccd3f8aa08fb738d380e2aad2 Mon Sep 17 00:00:00 2001 From: Jaume Bellet Date: Sun, 11 Feb 2024 19:36:43 +0100 Subject: [PATCH 3/5] added mode on bl_ui.space_toolsystem_common.item_from_id and bypass it until cls.tools_from_context This allows getting the tool when the context does not have the mode set, eg while registiring data. --- scripts/startup/bl_ui/space_toolsystem_common.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/startup/bl_ui/space_toolsystem_common.py b/scripts/startup/bl_ui/space_toolsystem_common.py index 50714bc5d8c..bfb74e90064 100644 --- a/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/scripts/startup/bl_ui/space_toolsystem_common.py @@ -333,11 +333,11 @@ class ToolSelectPanelHelper: return None, None, 0 @classmethod - def _tool_get_by_id(cls, context, idname): + def _tool_get_by_id(cls, context, idname, mode = None): """ Return the active Python tool definition and index (if in sub-group, else -1). """ - for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)): + for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context, mode)): if item is not None: if item.idname == idname: return (item, index) @@ -1172,12 +1172,12 @@ def description_from_id(context, space_type, idname, *, use_operator=True): return "" -def item_from_id(context, space_type, idname): +def item_from_id(context, space_type, idname, mode = None): # Used directly for tooltips. cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type) if cls is None: return None - item, _index = cls._tool_get_by_id(context, idname) + item, _index = cls._tool_get_by_id(context, idname, mode) return item -- 2.30.2 From 7bfb5e6d1ac7a76a9d97d5f1e6eb51ee5375973d Mon Sep 17 00:00:00 2001 From: Jaume Bellet Date: Sun, 11 Feb 2024 20:12:25 +0100 Subject: [PATCH 4/5] Allows to set Tool Handers on class Definition, as unset_cb and set_cb as class functions --- scripts/modules/bpy/utils/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/modules/bpy/utils/__init__.py b/scripts/modules/bpy/utils/__init__.py index d6ef0c10164..719eb649224 100644 --- a/scripts/modules/bpy/utils/__init__.py +++ b/scripts/modules/bpy/utils/__init__.py @@ -885,6 +885,12 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): "draw_settings": getattr(tool_cls, "draw_settings", None), "draw_cursor": getattr(tool_cls, "draw_cursor", None), }) + + if not tool_cls.set_cb is None: + tool_def.handlers.set.append(tool_cls.set_cb) + if not tool_cls.unset_cb is None: + tool_def.handlers.set.append(tool_cls.unset_cb) + tool_cls._bl_tool = tool_def keymap_data = tool_def.keymap -- 2.30.2 From 8f00d31c5d2e1f3b6ff8a1f940c7bc3a92a99d5f Mon Sep 17 00:00:00 2001 From: Jaume Bellet Date: Sun, 11 Feb 2024 21:23:31 +0100 Subject: [PATCH 5/5] fixes py error when cb was not set on workspace tool class --- scripts/modules/bpy/utils/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/modules/bpy/utils/__init__.py b/scripts/modules/bpy/utils/__init__.py index 719eb649224..fd72678c82c 100644 --- a/scripts/modules/bpy/utils/__init__.py +++ b/scripts/modules/bpy/utils/__init__.py @@ -886,9 +886,9 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): "draw_cursor": getattr(tool_cls, "draw_cursor", None), }) - if not tool_cls.set_cb is None: + if hasattr( tool_cls, 'set_cb' ) and callable(tool_cls.set_cb ): tool_def.handlers.set.append(tool_cls.set_cb) - if not tool_cls.unset_cb is None: + if hasattr( tool_cls, 'unset_cb' ) and callable(tool_cls.unset_cb ): tool_def.handlers.set.append(tool_cls.unset_cb) tool_cls._bl_tool = tool_def -- 2.30.2