Page MenuHome

Modal keymap customization from an addon is not restored properly
Confirmed, HighPublicBUG

Tokens
"Like" token, awarded by maxivz."Burninate" token, awarded by zgorg."Like" token, awarded by bblanimation."Like" token, awarded by brilliant_ape."Like" token, awarded by deadpin."Like" token, awarded by aliasguru.
Authored By
Roger B (rboxman), Jan 22 2019

Description

System Information
Operating system: Win10
Graphics card: nVidia Quadro 600

Blender Version
Broken: 2.80 (sub 41), branch: master, commit date: 2019-01-22 16:54, hash: 25889423d324
Worked: unsure

Short description of error
It seems that if an addon makes a customization to a modal keymap, this customization only works until you restart blender. After restart, the keymap is not restored properly (left blank) and the only way to fix is to disable/re-enable the addon again.

Exact steps for others to reproduce the error

  • Install and Enable the attached .py addon
    • It adds a modal keymap for circle select (makes it so that circle select is active only if you hold down the C key)
  • Save Preferences
  • Notice that things work correctly. Circle select is only active while holding down the C key
  • Restart blender
  • Notice the keymap no longer works. Check the keymap in user preferences and notice that the new entry is actually blanked out

Event Timeline

The same issue happens when you define a complete new tool with a shortcut using bl_keymap. On first Add-on activation, the shortcut works. On restarting Blender, it is non-functional. But if you reload all scripts while Blender is still running, the shortcut works again. I have used this class from the Templates to verify this behavior:

bl_info = {
    "name": "Shortcutter",
    "author": "Bug Reporter",
    "version": (1, 0),
    "blender": (2, 80, 0),
}

import bpy
from bpy.types import WorkSpaceTool

class MyTool(WorkSpaceTool):
    bl_space_type='VIEW_3D'
    bl_context_mode='OBJECT'

    # The prefix of the idname should be your add-on name.
    bl_idname = "my_template.my_circle_select"
    bl_label = "My Circle Select"
    bl_description = (
        "This is a tooltip\n"
        "with multiple lines"
    )
    bl_icon = "ops.generic.select_circle"
    bl_widget = None
    bl_keymap = (
        ("view3d.select_circle", {"type": 'LEFTMOUSE', "value": 'PRESS'},
         {"properties": [("wait_for_input", False)]}),
        ("view3d.select_circle", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
         {"properties": [("mode", 'SUB'), ("wait_for_input", False)]}),
    )

    def draw_settings(context, layout, tool):
        props = tool.operator_properties("view3d.select_circle")
        layout.prop(props, "mode")
        layout.prop(props, "radius")


def register():
    bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)

def unregister():
    bpy.utils.unregister_tool(MyTool)

if __name__ == "__main__":
    register()

Is this something that's on the ToDo list for 2.81 already? Or is there a workaround for it? Not being able to have modifier keys for custom tools limits the use quite a bit.

when will solve this problem? I can't advance because of it in my development

Hi @Max Derksen (Derksen) , if you are looking for a workaound for the problem of custom tools not working on Blender restart, you will find it in addons/mesh_snap_utilities_line/__init__.py
A simplified version of it is in: https://raw.githubusercontent.com/Shriinivas/blenderbezierutils/master/blenderbezierutils.py
(Essentially, you would need to register the tool and keymap in some roundabout way)

@Shrinivas (Shrinivas) (Shrinivas) , thanks, I'll try this for the instrument. What about saving the shortcuts in the settings addon? that doesn't work either

@Max Derksen (Derksen) Maybe there is also an option for saving the shortcuts in the workaround. Just check keys.py in snap utilities.
I am an add-on developer and faced the same issue in my tool. I got the pointer about this workaround from one of the users (thanks @yoshiki nosaka (sakana3)).

-- (zgorg) added a subscriber: -- (zgorg).EditedOct 23 2019, 5:16 PM

I think this is a high priority subject around keys save and more clear information about this
I tried to modify a key and at the same add another one. I had to change addon_keymaps to user_keymaps = [] but I could not register the other shortcut at the same time so I put user_keymaps in the settings too and I get back and all the default keys in mesh of all maps were erased. I had a save. but doing this because my shortcut was never registred. I see kmi.active=True on old scripts but I never found an explanation. some people use timers other handlers and I saw an update on a property from addon pref. why to go there? well I'm still a noob but it's not possible to improve this to be more easy to use? I think this is a priority as the fact to have new keys in new versions added to own keys config. I don't show the answer of Brecht about this again...I saw a script to find duplicates that's a good begining

I have a key reappearing even when the addon is totally uninstall. I even purge py cache (to see if any effect). It should be a problem in user.pref. but really I don't get it and still reading more infos. I found this https://blenderartists.org/t/key-config-confusion/637985/4 the last comment. it is maybe a little hard, and maybe he didn't understand how it's working. but please provide more clear info about all this. I can disable the key but not erase it. and it's getting back when I uninstall another addon with the same class in. so I changed the name class. no effect.
I found the actual help was in 2.73 and maybe before. this is a good example but plz do more that put 2.8 in the BL at first. I watch several "multi" addons and they are all reporting some issues about this. so with my little beginner level it's just a pita

Philipp Oeser (lichtwerk) raised the priority of this task from 50 to High.Nov 6 2019, 7:25 PM

This looks like it could use some attention? (will dare setting to High prio...)

I think problem hidden here

\blender-2.82-e5b788bad8bc-windows64\2.82\scripts\modules\bpy\utils\__init__.py
# Convert the class into a ToolDef.
def tool_from_class(tool_cls):
    # Convert class to tuple, store in the class for removal.
    tool_def = ToolDef.from_dict({
        "idname": tool_cls.bl_idname,
        "label": tool_cls.bl_label,
        "description": getattr(tool_cls, "bl_description", tool_cls.__doc__),
        "icon": getattr(tool_cls, "bl_icon", None),
        "cursor": getattr(tool_cls, "bl_cursor", None),
        "widget": getattr(tool_cls, "bl_widget", None),
        "keymap": getattr(tool_cls, "bl_keymap", None),
        "data_block": getattr(tool_cls, "bl_data_block", None),
        "operator": getattr(tool_cls, "bl_operator", None),
        "draw_settings": getattr(tool_cls, "draw_settings", None),
        "draw_cursor": getattr(tool_cls, "draw_cursor", None),
    })
    tool_cls._bl_tool = tool_def

    keymap_data = tool_def.keymap
    if keymap_data is not None:
        if context_mode is None:
            context_descr = "All"
        else:
            context_descr = context_mode.replace("_", " ").title()
        from bpy import context
        wm = context.window_manager
        kc = wm.keyconfigs.default  #  <-------------------------<-----------------------< HERE
        if callable(keymap_data[0]):
            cls._km_action_simple(kc, context_descr, tool_def.label, keymap_data)
    return tool_def

I've tested it with kc = wm.keyconfigs.user, everything work's well.
API: keyconfigs.default
API: keyconfigs.user

If it's so, then one line in function unregister_tool (scripts\modules\bpy\utils\__init__.py) should be changed same way from

kc = wm.keyconfigs.default

to

kc = wm.keyconfigs.user

otherwise addon will throw error when you deactivate it

@Cirno (Cirno)
All good for now, thanks for quick workaround

Tested the fix provided by @Cirno (Cirno) and can confirm this works! Attatching a diff for merging in case one of the devs wants to use it.

I want to bump this, since fix seems to be really so simple (one line of code). @Campbell Barton (campbellbarton)