Monday, July 8, 2013

WIP Bugfix Patch - Displaying shortcuts set using WM_OT_context_* operators

This evening, I decided to spend some time working on a (what I assumed) would be a neat little fix to a problem that's been bugging me for a while (and apparently has also been noticed by others too, as can be seen in this bug report).

Namely, there are many properties that have hotkeys assigned to toggle/cycle through their values, but there is no easy way to see what hotkeys have been assigned for that purpose. Sure, you can fire up the keymaps editor in the User Preferences, but it's quite tricky digging around in there to find what you want, if you even know where to start looking...

It turns out though, the vast majority of these hotkeys are set up so they call one of several operators. Somewhat "conveniently", they are all called something like, "WM_OT_context_*". For example:
  • WM_OT_context_toggle
  • WM_OT_context_toggle_enum
  • WM_OT_context_cycle_enum
  • ...
From this, we can see that clearly there's a good chance that to figure out what hotkeys are bound to a property, we simply need to check which of these operators is applied to said properties. That is the starting point of the patch I attached to the report above (EDIT: and now committed to svn too).

So, does it work?
Well the screenshots above speak for themselves. Pay attention to the second line of each tooltip, then fire up an older copy of Blender and compare ;)

Each of the examples above is located on the 3D View header, but even then, we actually see two types of property there - those that are for the current editor, and those which are scene-wide "toolsettings".
  1. Proportional Editing - OKEY toggles between Proportional Edit being enabled and it being disabled
  2. Transform center points only - Alt , (Alt Comma) toggles between only transforming center points and not doing so...
  3. Use Occlude Geometry - Shift-ZKEY (that's my own little hotkey tweak, since I tend to need to toggle this quite a bit when modelling - most of the time, you probably only want to deliberately select close-facing verts, but sometimes when reshaping a great chunk of stuff, you want to box-select all in that region both front and back to avoid jagged/botched up geometry - which I tried to map to something close to the addictive ZKEY solid/wireframe toggle)
All of these though were just buttons on the headers, and thus the shortcuts could only be shown in the tooltips. However, it turns out that even when the properties are added to menus, we can also get them to show the appropriate hotkeys as per usual:

"Show Seconds" is an example of a property which does just this - the hotkey is now shown alongside the property, just like in the early 2.5 days (before all such operators for setting these on a case-by-case basis were replaced with the generic operators + properties only in the menus).

In order to keep this from bogging down property views, I've restricted this to only working on Editor and ToolSetting properties so far. That's because only those ones can be easily automatically traced back to an appropriate data path (relative to the "context" object). Also, it only works with a limited set of WM_OT_context_* operators (i.e. basically only the default ones included with Blender), which means it won't work if you introduce your own little ones for special purposes...


The one limitation is one really annoying case (which motivated this whole exercise) which is sadly still not solved yet by this fix. That is the Pivot Point menu.

This Thing!

Argh! It's such a nuissance, since it is really the menu that needs it most, with each and every item in this list having a different and distinct hotkey (which is some combination of Shift/Ctrl/Alt/Non-Modifiers and either '.' or ','). Admittedly, I don't think I ever got around to learning which ones were which, though that doesn't mean I'm not interested in picking up the hotkeys for the few I end up toggling between rapidly when the time comes...

I'm not exactly sure what's going on here. The problem here is the way that popups like this work is nowadays buried quite deem in the multiple layers of UI widget wrappers we've got: layout engine property -> full-blown layout engine property -> auto button/special auto button/special special auto button/rather plain RNA property button/rather plain RNA property button with text and\or icon attached/etc. -> (lower-level pair of label + actual widget (in some cases)) -> the actual button used -> ... -> something which spawns the dropdown menu -> ... -> actual menu items (with RNA ptr/prop info probably still intact, but little else) -> ...

(If you thought that was bad, just wait till you try to debug why exactly some even you'd intended to be handled by your widget after text entry now zips in and out of different states, and perhaps goes back into the editing state all over again... now that's about one of the nastiest labryinths out there! Even the hell-hole of PyGtk+Py Threads + GTK threading may have a hot contender on its heels, though at least this one has deterministic behaviour across machines with different numbers of cores! :P)

Surprisingly, these internals have actually held up for so long without worse bugs creeping in. It's a bit of a miracle really :)

Other Roadblocks
This fix ended up taking me a lot longer than initially intended, and all because of a little one-line bug! For several hours, I spent a lot of time instrumenting and tracing through the internals of the code used to figure out what hotkeys are assigned for an operator in the current context.

However, in the end, it turned out to be simply a case of sing the wrong invocation context - WM_OP_INVOKE_DEFAULT vs WM_OP_INVOKE_REGION_WIN - to search for hotkeys in. I'm guessing now that what happened was that when using INVOKE_DEFAULT, it was assuming that we were only interested in hotkeys relevant to the header (i.e. there are hardly any!), so it wasn't finding any matches!

1 comment:

  1. For the pivot menu have a look at pie menus - new addon in contrib - it adds a pie menu to the '.' key that lets you select the pivot point. I believe this is aiming to be a standard part soon so your searching may end up to be for removing the hotkeys there?