Fix T66655: Add-on tool keymap not working after restart
authorCampbell Barton <ideasman42@gmail.com>
Fri, 27 Mar 2020 06:15:12 +0000 (17:15 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 27 Mar 2020 06:38:13 +0000 (17:38 +1100)
- Use addon keyconfig for registered tools so reloading the keymap
  doesn't clear them.

- Ensure there is a default keymap, needed for addon keymaps
  to be available in the user keyconfig.

release/scripts/modules/bpy/utils/__init__.py
release/scripts/startup/bl_ui/space_toolsystem_common.py

index 3d36f3eb510739b5edb17c8e88b0987d741972da..19450bb38ec590205a70d320c223f796b43ca1e0 100644 (file)
@@ -830,9 +830,13 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False):
                 context_descr = context_mode.replace("_", " ").title()
             from bpy import context
             wm = context.window_manager
-            kc = wm.keyconfigs.default
+            keyconfigs = wm.keyconfigs
+            kc_default = keyconfigs.default
+            # Note that Blender's default tools use the default key-config for both.
+            # We need to use the add-ons for 3rd party tools so reloading the key-map doesn't clear them.
+            kc = keyconfigs.addon
             if callable(keymap_data[0]):
-                cls._km_action_simple(kc, context_descr, tool_def.label, keymap_data)
+                cls._km_action_simple(kc_default, kc, context_descr, tool_def.label, keymap_data)
         return tool_def
 
     tool_converted = tool_from_class(tool_cls)
@@ -955,12 +959,13 @@ def unregister_tool(tool_cls):
     if keymap_data is not None:
         from bpy import context
         wm = context.window_manager
-        kc = wm.keyconfigs.default
-        km = kc.keymaps.get(keymap_data[0])
-        if km is None:
-            print("Warning keymap {keymap_data[0]!r} not found!")
-        else:
-            kc.keymaps.remove(km)
+        keyconfigs = wm.keyconfigs
+        for kc in (keyconfigs.default, keyconfigs.addon):
+            km = kc.keymaps.get(keymap_data[0])
+            if km is None:
+                print(f"Warning keymap {keymap_data[0]!r} not found in {kc.name!r}!")
+            else:
+                kc.keymaps.remove(km)
 
 
 # -----------------------------------------------------------------------------
index 796c089906d1ee969b7ddad82a4a98e37c16a40c..ace39a4cdf3dcd22ac9db032fec42ef3ede6078b 100644 (file)
@@ -449,19 +449,27 @@ class ToolSelectPanelHelper:
         return context.button_operator.name
 
     @classmethod
-    def _km_action_simple(cls, kc, context_descr, label, keymap_fn):
+    def _km_action_simple(cls, kc_default, kc, context_descr, label, keymap_fn):
         km_idname = f"{cls.keymap_prefix:s} {context_descr:s}, {label:s}"
         km = kc.keymaps.get(km_idname)
+        km_kwargs = dict(space_type=cls.bl_space_type, region_type='WINDOW', tool=True)
         if km is None:
-            km = kc.keymaps.new(km_idname, space_type=cls.bl_space_type, region_type='WINDOW', tool=True)
+            km = kc.keymaps.new(km_idname, **km_kwargs)
             keymap_fn[0](km)
+            print(len(km.keymap_items))
+            if km.keymap_items:
+                print(km.keymap_items[0].to_string())
         keymap_fn[0] = km.name
 
+        # Ensure we have a default key map, so the add-ons keymap is properly overlayed.
+        if kc_default is not kc:
+            kc_default.keymaps.new(km_idname, **km_kwargs)
+
     @classmethod
     def register(cls):
         wm = bpy.context.window_manager
         # Write into defaults, users may modify in preferences.
-        kc = wm.keyconfigs.default
+        kc_default = wm.keyconfigs.default
 
         # Track which tool-group was last used for non-active groups.
         # Blender stores the active tool-group index.
@@ -470,7 +478,7 @@ class ToolSelectPanelHelper:
         cls._tool_group_active = {}
 
         # ignore in background mode
-        if kc is None:
+        if kc_default is None:
             return
 
         for context_mode, tools in cls.tools_all():
@@ -482,7 +490,7 @@ class ToolSelectPanelHelper:
             for item in cls._tools_flatten_with_keymap(tools):
                 keymap_data = item.keymap
                 if callable(keymap_data[0]):
-                    cls._km_action_simple(kc, context_descr, item.label, keymap_data)
+                    cls._km_action_simple(kc_default, kc_default, context_descr, item.label, keymap_data)
 
     @classmethod
     def keymap_ui_hierarchy(cls, context_mode):