Official keymap example does not work?

I followed the example at https://docs.blender.org/manual/en/latest/advanced/scripting/addon_tutorial.html?highlight=keymap#keymap to somehow get my custom operator to be called upon pressing Ctrl+Shift+T. However, Blender complains about the line kmi.properties.total = 4. Without it the addon can be loaded, but the keymap does not work. What’s wrong? Here is the whole addon:

bl_info = {
	"name": "Foo",
	"description": "Bar",
	"author": "Zyl",
	"version": (0, 1),
	"blender": (2, 80, 0),
	"category": "3D View",
	"warning": "Windows only"
}

import bpy
import bmesh

class Foo(bpy.types.Operator):
	"""Foo"""
	bl_idname = "view_3d.foo"
	bl_label = "Foo"
	bl_options = { 'REGISTER' }
	def execute(self, context):
		print("Executing")
		return {'FINISHED'}

addon_keymaps = []

def register_keymaps():
	print("Registering keymaps")
	wm = bpy.context.window_manager
	kc = wm.keyconfigs.addon
	if kc:
		km = kc.keymaps.new(name = "Window", space_type = 'VIEW_3D', region_type = 'WINDOW', modal = False)
		kmi = km.keymap_items.new(Foo.bl_idname, "T", "PRESS", ctrl=True, shift=True)
		kmi.properties.total = 4
		addon_keymaps.append((km, kmi))

def unregister_keymaps():
	for km, kmi in addon_keymaps:
		km.keymap_items.remove(kmi)
	addon_keymaps.clear()

def register():
	bpy.utils.register_class(Foo)
	register_keymaps()

def unregister():
	unregister_keymaps()
	bpy.utils.unregister_class(Foo)

I have been trying all sorts of things for 3 hours but cannot figure this out. This is the error:

Traceback (most recent call last):
  File "C:\Program Files\Blender Foundation\Blender\2.80\scripts\modules\addon_utils.py", line 384, in enable
    mod.register()
  File "C:\Users\Zyl\AppData\Roaming\Blender Foundation\Blender\2.80\scripts\addons\foo.py", line 53, in register
    register_keymaps()
  File "C:\Users\Zyl\AppData\Roaming\Blender Foundation\Blender\2.80\scripts\addons\foo.py", line 43, in register_keymaps
    kmi.properties.total = 4
AttributeError: 'VIEW_3D_OT_foo' object has no attribute 'total'

Try to add property definition to you operator class(yep its look like example is wrong):

class Foo(bpy.types.Operator):
	"""Foo"""
	bl_idname = "view_3d.foo"
	bl_label = "Foo"
	bl_options = { 'REGISTER' }
	
	total: bpy.props.IntProperty(name="Total", default=4)
	
	def execute(self, context):
		print("Executing")
		return {'FINISHED'}

Thank you. The error message no longer appears. However, Ctrl+Shift+T still does nothing with the 3D view having focus. See anything else wrong with this?

You’ll have to verify that there are no downstream conflicts since you have your keymap item bound to a very vague keymap. ‘Window’ is about as high level as you can get, as far as keymaps go. There is likely something at a lower level that is consuming your event and preventing your keymap item from being triggered.

Thanks for replying. I tried all other region_type enums (‘HEADER’, ‘CHANNELS’, ‘TEMPORARY’, ‘UI’, ‘TOOLS’, ‘TOOL_PROPS’, ‘PREVIEW’) but still no luck. Isn’t there a single working example I can just copy anywhere? I tried looking into the scripts folder of Blender and searched for keymap with winGrep to find some sort of reference but it’s all quite complicated. I found the following style which I also tried:

		kmi = (
			"Foo",
			{"space_type": 'VIEW_3D', "region_type": 'TOOLS'},
			{"items": [(Foo.bl_idname, {"type": 'T', "value": 'PRESS', "ctrl": True, "shift": True}, {"properties": [("total", 4)]})]},
		)

It loads, but still nothing.

sorry, I know it’s confusing because there’s a lot of overloaded terminology, but I was talking about your keymap region name, not your keymap item region_type

when you call kc.keymaps.new(name=“Window”) you’re creating a keymap that works in any area that is inherited from Window (which is everything). To make a keymap that works in edit mesh mode, you’ll want to use “Mesh”. If you want one that works in object mode, you’d use “Object Mode”. The region name in keymaps.new is not actually an enum- there are 190(!!) different keymaps in the default keyconfig and they’re not documented anywhere as far as I’m aware. Worst of all, some take priority over others, and this is not documented anywhere either- you’ll have to learn by trial and error unfortunately.

To see all of the potential keymaps, run this script:

import bpy

for i, km in enumerate(bpy.context.window_manager.keyconfigs.default.keymaps):
    print(f"{i}\t{km.name}")

Also, as a somewhat related side-note, when you should always check to see if a keymap already exists before calling keymaps.new().

# There's a more 'pythonic' way to do this with one line of code but it's 
# not as easily readable for people new to python.
if "Mesh" not in kc.keymaps:
    kc.keymaps.new(name="Mesh", etc)
km = kc.keymaps["Mesh"]
1 Like

Ah I thought that was just some arbitrary name. I set it to 3D View and now it works. Thanks a lot! Maybe we should make a Github repo with user documentation when official docs are such a trainwreck?