Skip to content

Quicker Text Editing in Blender (Part 6): Saving Preferences and The ‘Right’ Keymap

There’s the keymap (shakes head and frowns); and the keymap (smiles and nods)

Context

When making videos in Blender’s VSE I work with a lot of text sequences. I’ve been on a quest to speed up how I work with them, by creating an addon that lets the user define hotkeys for common actions, like setting colour, location, size, etc.

Reference from Preset (Preference) to KeyMapItem

Previously, we looked at creating a panel to show in Blender’s addon preferences, and data structures for storing preferences.It got kind of confusing, but we came up with what in python amounted to a list (CollectionProperty) of dicts (PropertyGroup). There was some difficulty in linking the properties we implemented — for colour presets: name, colour, key — with the key binding. We were able to store values in both the preference properties and the key properties, but updating one would not update the other.

I got around this by including another bit of data in the preference properties: the id of the created KeyMapItem, stored as keymapid. With this, I could walk the list of properties, and for each one use the saved keymapid with from id() (a KeyMapItems method) to access each KeyMapItem with the key binding. But this was to be a temporary victory, as you’ll see later in the post…

Dirty Bits and the ‘Update Keymap’ Button

One thing that puzzled me greatly was that the presets/bindings weren’t updating properly. For example, I’d add a binding, change the colour, test it and it would set the text colour to the preset default (which was red). Strangely, if I added another preset, the first preset I added would work correctly — ie set the text to the colour I chose — but the new binding wouldn’t work. Even more oddly, if I accessed the properties using Blender’s python console, the preset colours on the hotkeys that weren’t working were the ones I had set them to, not the default!

Moreover, setting the .active property to True caused the colour preset to work properly… even though .active was already true! After much searching I tracked down a thread where someone had implemented an operator that worked as a dirty bit/flag, doing essentially the same thing I had in the console by setting the KeyMapItem’s active property to itself.

class SAMPLE_OT_DirtyKeymap(bpy.types.Operator) :
    bl_idname = "addon.sample_dirty_keymap"
    bl_label = "Save Keymap"

    def execute(self, context):
        km = context.window_manager.keyconfigs.user.keymaps["MyAddon"] :
        km.show_expanded_items = km.show_expanded_items
        for kmi in km.keymap_items :
            kmi.active = kmi.active
        context.preferences.is_dirty = True
        return {'FINISHED'}

via sakana3 at https://devtalk.blender.org/t/how-to-draw-a-custom-keymapitem-properties/13059/5

For the sake of my sanity, I borrowed the operator and added it to the preferences panel as an ‘update keymap’ button. Remember: if it’s stupid and it works, it’s not stupid!

Which Keymap is the Correct Keymap?

Hitherto, I had been using context.window_manager.keyconfigs.addon.keymaps['Sequencer']as the keymap to add key bindings to, as that was what I saw in examples and replies to threads on BlenderArtists when I asked about implementing parts of this addon.

But there was a problem: restarting Blender lost the key bindings. An addon where you have to redo the key bindings every time you load up Blender is not exactly living up to the name of ‘quicker text editing’ !

I’m not the only person who has had this issue: BSE QA, BA thread, another BSE Q, and another BSE Q… The last one is especially interesting- the answer points to window_manager.keyconfigs.addon (with a link to the API reference†), but the comments are telling:

“The API page confuses me. Should this entry also be available through the wm.keyconfigs.user? – Marty Fouts
1 @MartyFouts Yes, it is also available through wm.keyconfigs.user. I do not know the reason for this design decision either and would have to look it up. – Robert Gützkow

†: The API page even states: “[keyconfigs.]addon: Key configuration that can be extended by add-ons, and is added to the active configuration when handling events”

In the absence of a definitive answer on the difference between the two, I’m going to stick to using the one that isn’t lost on Blender exit!

Can I see some ID?

After changing the Blender data structure in which I was storing key mappings, I ran into yet another issue- I was no longer able to access the key bindings by id, as I described doing earlier in this post. I stuck my hair back in so that i could pull it out again, and tried to figure out why. Long story short, it seemed that the ids were changing, which there should probably be a note in the documentation about.

I was able to confirm that ids change by adding four presets (KeyMapItems) checking the ids, deleting two of the KeyMapItems, and checking the ids again. It started with -7, -8, -9, -10; I removed -7 and -8, and I was left with: -7, -8 !

Next Steps

If you made it through Part 4 and this part, good on you! Figuring out the foibles of this part of the Blender API has been confusing for me, and I have context for it. At this point, unless I read otherwise, I’ll draw the following conclusions:

  • store custom addon key mappings in window_manager.keyconfigs.user, not in window_manager.keyconfigs.addon
  • store associated information (eg the colour for set_text_colour) in the KeyMapItem operator properties itself

For now, I am going to convert the addon to use that approach and test it. If all goes well, it should suffice for a functional release.

2 thoughts on “Quicker Text Editing in Blender (Part 6): Saving Preferences and The ‘Right’ Keymap”

  1. Pingback: Quicker Text Editing in Blender (Part 7): QTE Beta Release – Rob's Blog

  2. Pingback: Quicker Text Editing in Blender (Part 12): Preferences + Properties = Bugs – Rob's Blog

Tell us what's on your mind

Discover more from Rob's Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading