Dear fellow Blender developers,
TL;DR: syncing selection between editors is broken, and needs a redesign. Please help.
Intro to Selection Sync
Currently Blender responds to certain changes in selection, and updates the selection state of other things. For example:
- Select a Bone in pose mode → the corresponding Animation Channel Group is selected.
- Select an Animation Channel Group in the Dope Sheet → the corresponding Bone is selected.
- Select a Shader Node → its animation channels are selected.
In principle this is all fine, as it helps animators to quickly find relevant animation channels based on their selection in the 3D viewport, node editor, etc.
The current problem
Selection syncs are handled via the window manager notification system, and in my opinion in an unreliable and badly designed way. It causes reports like these:
- T48145 All bone drivers selected when reselecting bone
- T58718 Clicking on Dope Sheet deselects all bones
- T62463 Skeleton rig with keyframes prevents selection of Shader Nodetree channels in Dope Sheet and Graph Editor
- T71615 Select key in dopesheet deselect bone in the viewport
- T73215 Blender autokeying deselects objects channels but not Armatures.
As far as I’ve been able to figure out from the code, this is what’s happening. I’ve included my comments about what’s happening. I’ve marked the loss of contextual information with a .
What Happens | My interpretation |
---|---|
User selects a bone | This is fine |
A notification is sent to the window manager, indicating that bone selection changed |
This has no information about which Object changed |
This notification is received by the Action editor | ok |
Action editor sets a runtime flag that indicates “channels need syncing” | This looses information, from the specific “bone selection changed” to the generic “sync necessary” |
Action editor tags the area for refresh via the very generic ED_area_tag_refresh() function |
by now, all context is gone, and only that one flag is all that’s left |
The window manager handles the refresh tags, and calls the Action editor’s refresh function | ok |
Action editor’s refresh function looks at the flag, and when set, effectively deselects all FCurves, then selectes curves that refer to something (bone, shader node) that is selected | This is problematic, as it synces too much (shader node channel selection is synced too) |
Action editor’s refresh function clears the flag, and calls ED_area_tag_redraw() on itself |
This shouldn’t be necessary |
From a glance, things don’t look too bad:
- By using the notification system, the part of the code that changes the bone selection doesn’t need to know about the selection synchronisation. It just needs to send a generic Window Manager notification and the rest is taken care of automatically.
- By using the “tag for refresh” functionality, handling the notifications themselves is very cheap. This makes it possible send many notifications, while still causing only one “loop over all the visible animation channels and sync their selection” step.
However, from “My Interpretation” above, you can see that there are various issues with the current code (for example: the existence of pose animation channels causes node animation channels to become unselectable).
My proposal
My proposal to address the above issues is:
-
(A): Create functions for specific things for which we want to sync selections. These should take a pointer to whatever was changed (
Object*
,bNodeTree*
), and should be limited to the FCurves in that Object/Node Tree’s action, so that the selection state of unrelated animation data is unaffected. - (B): Code that wants to modify the selection state of bones/nodes, should call dedicated functions for this (instead of modifying the DNA directly).
- The (B) functions shouldn’t directly call the (A) functions, as selecting many bones in a for-loop should be kept efficient. They could set some runtime flag “flush selection state to animation” on the Object or Node Tree (or on the
ID
orAnimData
struct to keep it generic).
After all the selection changes are done, we need some way to call the relevant (A) functions. This could be done in response to window manager notifications similar to what’s done now. With the proposed tags, the current Action Editor refresh functions could be reused, looking at the owner of the animation data to see if they’re tagged.
Alternatively, the (B) functions could be made in such a way that they keep track of the objects that require syncing, and that list could at some point be used by the window manager notification system. This would remove the “refreshing also alters selection state in DNA” quirk that we have now, at the expense of having to find a place to do the relevant bookkeping.
What do other devs think about this?