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$
    – Scalia
    Oct 15 '14 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 '14 at 22:45
  • $\begingroup$ Sorry can't help then i do simple stuff. i.e. 9-10 lines each. $\endgroup$
    – Scalia
    Oct 16 '14 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 '18 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 '19 at 2:37
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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.