2
$\begingroup$

I noticed that when Blender writes out a custom keymap it completely overrides all keys that were assigned previously. I don't want to miss out on any changes in the default key mappings in future versions of blender, so I am trying to make a script that would append the keys I want to use to the defaults.

Here is the script:

import bpy
import os

wm = bpy.context.window_manager
kc = wm.keyconfigs.user

km = kc.keymaps['View2D']
kmi = km.keymap_items.new('view2d.zoom', 'BUTTON4MOUSE', 'PRESS')
kmi = km.keymap_items.new('view2d.zoom', 'BUTTON4MOUSE', 'PRESS', shift=True)
kmi = km.keymap_items.new('view2d.pan', 'BUTTON5MOUSE', 'PRESS')

km = kc.keymaps['View2D Buttons List']
kmi = km.keymap_items.new('view2d.scroller_activate', 'BUTTON4MOUSE', 'PRESS')
kmi = km.keymap_items.new('view2d.pan', 'BUTTON5MOUSE', 'PRESS')
kmi = km.keymap_items.new('view2d.zoom', 'BUTTON4MOUSE', 'PRESS', shift=True)

km = kc.keymaps['3D View']
kmi = km.keymap_items.new('view3d.rotate', 'BUTTON4MOUSE', 'PRESS')
kmi = km.keymap_items.new('view3d.move', 'BUTTON5MOUSE', 'PRESS')
kmi = km.keymap_items.new('view3d.zoom', 'BUTTON4MOUSE', 'PRESS', shift=True, ctrl=True)
kmi = km.keymap_items.new('view3d.dolly', 'BUTTON4MOUSE', 'PRESS', shift=True)

km = kc.keymaps['View3D Fly Modal']
kmi = km.keymap_items.new_modal('PAN_ENABLE', 'BUTTON5MOUSE', 'PRESS', any=True)
kmi = km.keymap_items.new_modal('PAN_DISABLE', 'BUTTON5MOUSE', 'RELEASE', any=True)

km = kc.keymaps['View3D Rotate Modal']
kmi = km.keymap_items.new_modal('CONFIRM', 'BUTTON4MOUSE', 'RELEASE', any=True)

km = kc.keymaps['View3D Move Modal']
kmi = km.keymap_items.new_modal('CONFIRM', 'BUTTON5MOUSE', 'RELEASE', any=True)

km = kc.keymaps['View3D Zoom Modal']
kmi = km.keymap_items.new_modal('CONFIRM', 'BUTTON4MOUSE', 'RELEASE', any=True)

km = kc.keymaps['View3D Dolly Modal']
kmi = km.keymap_items.new_modal('CONFIRM', 'BUTTON4MOUSE', 'RELEASE', any=True)

km = kc.keymaps['Image']
kmi = km.keymap_items.new('image.view_pan', 'BUTTON4MOUSE', 'PRESS')
kmi = km.keymap_items.new('image.view_pan', 'BUTTON5MOUSE', 'PRESS')
kmi = km.keymap_items.new('image.view_zoom', 'BUTTON4MOUSE', 'PRESS', shift=True)

km = kc.keymaps['Node Editor']
kmi = km.keymap_items.new('node.backimage_move', 'BUTTON5MOUSE', 'PRESS', alt=True)

km = kc.keymaps['Clip Editor']
kmi = km.keymap_items.new('clip.view_pan', 'BUTTON4MOUSE', 'PRESS')
kmi = km.keymap_items.new('clip.view_pan', 'BUTTON5MOUSE', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('clip.view_zoom', 'BUTTON4MOUSE', 'PRESS', shift=True)

It works when I manually execute after blender has started, but I tried putting the script in my scripts/startup user folder and it said View2D was not found. So it's executing before View2D keymap context is defined, but I don't know how to make the script execute after everything else has been mapped. Any ideas how to make this work?

$\endgroup$
6
  • $\begingroup$ Would it be possible to define Veiw2D earlier in the script? $\endgroup$
    – ruckus
    Oct 15, 2014 at 22:35
  • $\begingroup$ Defining a new context keymap overwrites defaults... which actually doesn't make much sense because that would mean the default keymaps were already executed. It must not work the way I thought. Still confused. $\endgroup$ Oct 15, 2014 at 22:45
  • $\begingroup$ Sorry can't help then i do simple stuff. i.e. 9-10 lines each. $\endgroup$
    – ruckus
    Oct 16, 2014 at 2:48
  • $\begingroup$ Hey, I know this is old, but I just stumbled over. Couldn't you export the keymap, use a script to overwrite or append to the keymap and then re-import it? You'd have to do that once for each blender-installation, but only once ... Still I agree that a "Partial Keymap"-feature would be cool. $\endgroup$
    – Teck-freak
    Dec 28, 2018 at 22:09
  • $\begingroup$ @Teck-freak Oh wow thanks for the reply. I ended up doing exactly that. Every time I update blender I re-execute the script. Not ideal, but better than nothing. I've been using that same script since 2014. $\endgroup$ Feb 8, 2019 at 2:37

1 Answer 1

2
$\begingroup$

Perhaps you could apply the keymap after startup as an addon, rather than in the startup folder?

Here is an extract of an example script from an addon I wrote to Toggle Emulate MMB & Numpad. I have included some keymap reference documentation in the repository, and commented code that might make it easier for you to set up your own script. I have removed here the superfluous elements for your purposes.

bl_info = {
    "name": "My Custom Keymaps",
    "author": "me",
    "version": (1, 0),
    "blender": (2, 90, 1),
    "location": "...",
    "description": "Loading Custom Keymaps",
    "warning": "",
    "wiki_url": "",
    "category": "Preferences"}

import bpy
import rna_keymap_ui
from bpy.utils import register_class, unregister_class

# Keymap Code

# First, set up a dictionary of key mappings.

# "TEMPLATE": [{"label": "Human readable name of keymap in Blender Keymap UI",
#               "region_type": "WINDOW", //Default is WINDOW (optional)
#               "space_type", "EMPTY", //Default is EMPTY
#               "map_type": "KEYBOARD", //Device to be used (optional)
#               "keymap": "Window", //Name to be chosen from declared list of keymap names
#               "idname": ..., //Specific reference to operator from blender API
#               "type": "", //Key type identifier - choose a specific keyboard button or mouse button, etc...
#               "ctrl": False, //Combination keys for compound hotkeys (optional)
#               ...
#               "value": "PRESS"}, //Whether key will be held, pressed, etc...
#              {...}]

keys = {"MENU": [{"label": "Toggle Emulate 3 Button Mouse",
                  "region_type": "WINDOW",
                  "space_type": "EMPTY",
                  "map_type": "KEYBOARD",
                  "keymap": "Window",
                  "idname": "preferences.toggle_emulate_3_button_mouse",
                  "type": "QUOTE",
                  "ctrl": False,
                  "alt": False,
                  "shift": False,
                  "oskey": False,
                  "value": "PRESS"
                  },
                {"label": "Toggle Emulate Numpad",
                  "region_type": "WINDOW",
                  "space_type": "EMPTY",
                  "map_type": "KEYBOARD",
                  "keymap": "Window",
                  "idname": "preferences.toggle_numpad",
                  "type": "SEMI_COLON",
                  "ctrl": False,
                  "alt": False,
                  "shift": False,
                  "oskey": False,
                  "value": "PRESS"
                  }]}

# Define a function to get a list of key mappings, 'keylists'
def get_keys():
    keylists = []
    keylists.append(keys["MENU"])
    return keylists

# Define a function to register the key mappings templated in the dict as keymaps, using the constructor kc.keymaps.new()        
def register_keymaps(keylists):
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon

    keymaps = []

    for keylist in keylists:
        for item in keylist:
            keymap = item.get("keymap")
            space_type = item.get("space_type", "EMPTY")
            region_type = item.get("region_type", "WINDOW")

            if keymap:
                km = kc.keymaps.new(name=keymap, space_type=space_type, region_type=region_type)
                # km = kc.keymaps.new(name=keymap, space_type=space_type)

                if km:
                    idname = item.get("idname")
                    type = item.get("type")
                    value = item.get("value")

                    shift = item.get("shift", False)
                    ctrl = item.get("ctrl", False)
                    alt = item.get("alt", False)
                    oskey = item.get("oskey", False)

                    kmi = km.keymap_items.new(idname, type, value, shift=shift, ctrl=ctrl, alt=alt, oskey=oskey)

                    if kmi:
                        properties = item.get("properties")

                        if properties:
                            for name, value in properties:
                                setattr(kmi.properties, name, value)

                        keymaps.append((km, kmi))
    return keymaps

# Define a function to unregister the keymaps
def unregister_keymaps(keymaps):
    for km, kmi in keymaps:
        km.keymap_items.remove(kmi)


def register():
    global keymaps
    keys = get_keys()
    keymaps = register_keymaps(keys)




def unregister():
    global keymaps
    for km, kmi in keymaps:
        km.keymap_items.remove(kmi)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .