Page MenuHome

exposed_addon_keymap.py

exposed_addon_keymap.py

bl_info = {
"name": "Exposed addon keymap",
"description": "Test addon to let user edit addon keymap",
"author": "Samuel Bernou",
"version": (0, 1, 0),
"blender": (2, 95, 0),
"location": "Addon preferences",
"warning": "",
"doc_url": "",
"category": "Object" }
import bpy
import os
## --- custom kmi draw for addon->user Kms (without delete button)
def draw_kmi(km, kmi, layout):
map_type = kmi.map_type
## col = _indented_layout(layout)
# layout.label(text=f'{km.name} - {km.space_type} - {km.region_type}') # debug
# layout.label(text=f'{km.name}')
col = layout.column()
if kmi.show_expanded:
col = col.column(align=True)
box = col.box()
else:
box = col.column()
split = box.split()
# header bar
row = split.row(align=True)
row.prop(kmi, "show_expanded", text="", emboss=False)
row.prop(kmi, "active", text="", emboss=False)
if km.is_modal:
row.separator()
row.prop(kmi, "propvalue", text="")
else:
row.label(text=kmi.name)
row = split.row()
row.prop(kmi, "map_type", text="")
if map_type == 'KEYBOARD':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'MOUSE':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'NDOF':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'TWEAK':
subrow = row.row()
subrow.prop(kmi, "type", text="")
subrow.prop(kmi, "value", text="")
elif map_type == 'TIMER':
row.prop(kmi, "type", text="")
else:
row.label()
### / Hided delete button
if (not kmi.is_user_defined) and kmi.is_user_modified:
row.operator("preferences.keyitem_restore", text="", icon='BACK').item_id = kmi.id
else:
pass ### NO REMOVE
# row.operator(
# "preferences.keyitem_remove",
# text="",
# # Abusing the tracking icon, but it works pretty well here.
# icon=('TRACKING_CLEAR_BACKWARDS' if kmi.is_user_defined else 'X')
# ).item_id = kmi.id
### Hided delete button /
# Expanded, additional event settings
if kmi.show_expanded:
box = col.box()
split = box.split(factor=0.4)
sub = split.row()
if km.is_modal:
sub.prop(kmi, "propvalue", text="")
else:
# One day...
# sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="")
sub.prop(kmi, "idname", text="")
if map_type not in {'TEXTINPUT', 'TIMER'}:
sub = split.column()
subrow = sub.row(align=True)
if map_type == 'KEYBOARD':
subrow.prop(kmi, "type", text="", event=True)
subrow.prop(kmi, "value", text="")
subrow_repeat = subrow.row(align=True)
subrow_repeat.active = kmi.value in {'ANY', 'PRESS'}
subrow_repeat.prop(kmi, "repeat", text="Repeat")
elif map_type in {'MOUSE', 'NDOF'}:
subrow.prop(kmi, "type", text="")
subrow.prop(kmi, "value", text="")
subrow = sub.row()
subrow.scale_x = 0.75
subrow.prop(kmi, "any", toggle=True)
subrow.prop(kmi, "shift", toggle=True)
subrow.prop(kmi, "ctrl", toggle=True)
subrow.prop(kmi, "alt", toggle=True)
subrow.prop(kmi, "oskey", text="Cmd", toggle=True)
subrow.prop(kmi, "key_modifier", text="", event=True)
# Operator properties
box.template_keymap_item_properties(kmi)
## Modal key maps attached to this operator
# if not km.is_modal:
# kmm = kc.keymaps.find_modal(kmi.idname)
# if kmm:
# draw_km(display_keymaps, kc, kmm, None, layout + 1)
# layout.context_pointer_set("keymap", km)
###---User pref
class keymaptest_addon_prefs(bpy.types.AddonPreferences):
bl_idname = __name__
def draw(self, context):
layout = self.layout
layout.label(text='Registered Addons keymaps')
box = layout.box()
box.label(text='Addon keymap (not saved in pref when edited)')
for akm, akmi in addon_keymaps:
## akm and akmi are "addon" keymap/item stored in global addon_keymap dict
## customised function to draw kmi
## because we want to enable the user to disable or customize, but NOT delete !
draw_kmi(akm, akmi, box) # addon keymap, modification not saved in prefs
# box.label(text=f'akmi_id: {akmi.id}')
layout.separator()
box = layout.box()
box.label(text='User keymap - using get(idname)')
for akm, akmi in addon_keymaps:
## if we want this keymap to be exposed and editable by the user and saved in user prefs
## we have to get the related added keymap in "user" keymap
km = bpy.context.window_manager.keyconfigs.user.keymaps.get(akm.name)
# Except here, using get(idname) we dont know what we get... (we'll get twice first idname )
kmi = km.keymap_items.get(akmi.idname)
draw_kmi(km, kmi, box) # user keymap used by get, modification correctly saved in prefs
# box.label(text=f'kmi_id: {kmi.id} (akmi_id in loop: {akmi.id})')
## We got same User kmi twice since we cannot know which is related to addon-kmi using get !
###--- Keymaps
addon_keymaps = []
def register_keymaps():
addon_kms = bpy.context.window_manager.keyconfigs.addon
# Moving origin point utility, cursor/geometry. (same idname, but hold different properties)
km = addon_kms.keymaps.new(name = "3D View", space_type = "VIEW_3D")
kmi = km.keymap_items.new("object.origin_set", type = 'F5', value = "PRESS", ctrl = True, shift = True, alt = True)
kmi.properties.type = 'ORIGIN_CURSOR'
addon_keymaps.append((km, kmi))
kmi = km.keymap_items.new("object.origin_set", type = 'F6', value = "PRESS", ctrl = True, shift = True, alt = True)
kmi.properties.type = 'ORIGIN_GEOMETRY'
addon_keymaps.append((km, kmi))
def unregister_keymaps():
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
###---- register
def register():
if bpy.app.background:
return
bpy.utils.register_class(keymaptest_addon_prefs)
register_keymaps()
def unregister():
if bpy.app.background:
return
unregister_keymaps()
bpy.utils.unregister_class(keymaptest_addon_prefs)
if __name__ == "__main__":
register()

File Metadata

Mime Type
text/x-c++
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a6/93/12f7a826743f015481a7b06ad19c

Event Timeline