This continues the exploration of better support for append & link after #4.
The biggest issue is the lack of handlers for append and link. There are a couple of annoyances that could be solved with handlers:
Linked/appended object and it's blocks might have the same Keymesh ID as something else in the scene. If objects are the same type this breaks things and appends blocks from both objects to each other. Handler would be able to detect such cases by checking IDs on objects and offset ID on appended object if it finds a match.
Append and link operators have the 'Instance Object Data' property enabled by default. That creates new objects for each referenced object data that is without an object (e.i. everything Keymesh imports). If user leaves it on they need to delete those objects afterwards. Handler would override this property and always set it to disabled before completing the import.
Appending removes Fake User from IDs, add them back to Keymesh blocks.
Before the current frame changes it displays the last block instead of the one it should on the current frame. Handler could either register update_keymesh() function or simply offset the current frame by +-1
Even though simple append and link works there needs to be a check for copy-pasting and asset browser.
Library override system is working nicely in #8 and makes for a good first release, but some things can be improved for future updates:
Editing individual blocks on overridden objects is probably still possible (but opens up whole new workflow issues, so postponed for now). Will require batch operators, tests and fallbacks.
Removing blocks in object file messes with animation. While it's not broken, it can be improved by removing keyframes in scene file (maybe with handler).
I don't know how practical they can be, since frames are already tightly controlled in this animation workflow, but it's easy to do and I can just copy code from Bake Shape Keys.
When deleting duplicates, currently operator only reports about frames on which duplicates were keyframes on. For example, if block was keyframes on 9th and 23rd frames it reports 9 and 23. But it ignores hold keyframes. Without that information user might be misled about the animation, and didn't realize exactly how many times block was used.
If the block was keyframed on 9th frame, but held the value till 14th, operator should report that block was used on 9-14 keyframes
If the block was keyframed once but was hold it reports that a duplicate was used 1 time. It should report the hold duration
Report the number of keyframes (currently showing) separately from the total number of frames on which the block was visible
Some sculpt mode properties like remesh resolution are stored on mesh, and not object. This is annoying when working on Keymesh, as you have to adjust them for each block. There are multiple ways this can be fixed:
Create temporary properties on object, store values there and transfer between blocks on update.
Transfer can happen either when doing timeline jump with PageUp and PageDown (which would be inconsistent and unreliable), or on frame handler update (which might be tiny bit costly)
This is quite a difficult task that needs good design and many corner cases to test. Besides some general things, data transfer should be specific to object types and each of them might need separate operator. Feature can be implemented separately for them too.
There are many transfer/copy/link operators in Blender that can be hooked by add-on operators by pretending two blocks are two objects.
At first operators will copy properties to all blocks, but in future some sort of selection will be needed (currently no way of having it)
Copy Materials
(should be able to replace material slots entirely for all blocks, or only active one by index; might be good to also have option that adds material as a new slot)
Copy Properties
(mostly useful for other types besides mesh. Operator in which you can pass property id_name as string, like in attributes, and copy that property from active to all blocks; option for copying all properties might be useful too, but hard to define what is "all")
Transfer Attribute
(by using geometry nodes modifier that uses surface sampling to nearest vertex it can be done, but won't be easy to set up, will require temporary copy of object that can act as modifier target)
Transfer Shape Keys
(operator exists in Blender, but has to be tested how good it works, and in which cases; I think it's doable and can be useful if cases where mesh doesn't change too much between blocks)
This task is keeping to-dos & designs for when/if event handlers are added for duplicating and deleting objects.
duplicate_handler:
Currently, when duplicating without linking [Shift-D] only the active Keymesh block gets duplicated, the rest are shared between two objects. Instead, every Keymesh block should get duplicated and assigned to new objects registry.
New duplicated Keymesh blocks should get fake_user, which is now not added when duplicating with [Shift-D]
delete_handler:
Since Keymesh blocks are assigned fake_user it makes it impossible to purge them (except manually) after the object is deleted. When object is deleted, remove fake_user from all its Keymesh blocks.
Currently there is single button in UI and property "Keyframe on Selection", while I like this a lot, I think maybe it can be improved if previewing and keyframing were two different buttons. Problem with current workflow is that if you want to quickly preview something you have to disable the property, and when you find the object you want to keyframe then enable property again and click the button.
Using either PointerProperty or CollectionProperty (can't remember which is correct) every object data block with the same Keymesh ID as an object can be registered on object itself. It will be empty reference, but potentially it can mean that appending object from one scene to another will also bring Keymesh data-blocks with it. It needs more testing to see if/how well this will work (copy/paste, asset browser, linking, etc.)
For this change it will be good to create general Keymesh CollectionProperty and store data-blocks there. Keymesh ID and Keymesh Data properties can be moved there as well. We'll lose visibility (maybe restored somewhere else), but on the other hand users will not accidentally mess up properties that are vital for Keymesh to function.