See KeyframeStrip::keyframe_insert()
. That function can fail for a few reasons:
BKE_fcurve_is_keyframable()
).INSERTKEY_REPLACE
flag is set and there is no existing key to replace (see insert_vert_fcurve()
).As a generalisation of this question, there is:
KeyframeStrip::keyframe_insert()
specifies an output, and the RNA path of the property to key. The caller may have an interest in both the FCurve *
that was used (or even created), as well as the index of the key (to do further modifications).
Information about failure of key insertion could also be returned as a 3rd return value, so the eventual return type could be something like tuple<FCurve *, int, eKeyInsertionFailureReason>
.
How to do deal with animation layers?
Answer: use the same logic as where new keys go.
Can be very useful for driving shapekeys, for lip syncing (using markers to place phonemes on the timeline). Should be slotted, so that it's clear which markers are for which animated data-block.
M×N
relationship, with M
markers defined over time, animating N
things (like multiple shape-key blend weights).Creating a new layer no longer automatically creates a new strip. The Py should be updated for this.
Instead of just writing the evaluated FCurve value directly to the property, it should be stored in a structure. Those can then be mixed between strips and layers, and finally written to the props.
Current when you add a strip, it's automatically going to be infinite. This means that it's trivially easy to add overlapping strips, and thus an invalid datamodel. Or not, if we define the right blend operations for overlaps.
It should be well-defined how boundaries of strips behave.
Done: 335a160365c: Anim: when evaluating animation layer, add special case for strip overlap (Sybren A. Stüvel) (2024-01-26)
What happens outside a finite strip? IIRC the NLA currently respects the extrapolation rules of the last Action strip. Do we copy that, or do we simply expect a (half) infinite strip in that case?
For now it's simple: no strip extrapolation. If you want the strip to be effective, make it longer (up to, but not beyond, infinity).
It should be possible to cut a strip in two, including the infinite strip. This means that we should be able to have two strips (-∞, t₁]
and [t₂, ∞)
.
Can be done with Python now. No dedicated function for it.
Somewhat done, the colors in the UI are shown now, but some extra research is needed to ensure all calls to the modified code work well.
There are TODO
markers about this in the code.
Animation
: from stable index to Output *
KeyframeStrip
: from output stable index to ChannelsForOutput *
.Library linking should work as expected:
Removing of layers, strips, and outputs should be implemented.
Implemented for layers and strips, but not yet for outputs.
❓ Removing outputs: Should this also remove all the animation data for that output?
The existing notifiers (ND_KEYFRAME
, ND_ANIMCHAN
and friends) may not be sufficient to nicely handle layer / strip events.
We may need a depsgraph node per output, instead of one for the entire Animation data-block. That way keyframe updates don't need to trigger re-evaluation of the world.
Necessary to properly fix #135750: Anim: Inserting keyframes (or undoing them) doesn't update animation for IDs that share action slot
Currently key-insertion code uses ID_RECALC_ANIMATION_NO_FLUSH
to tag the Action. This means that other users of the same Action do not get their properties updated with the new animation.
The current behaviour is for when you have the loc/rot/scale animated, then go to another frame and translate/rotate/scale the cube. Then you want to be able to key loc/rot/scale in sequence. If we were to use ID_RECALC_ANIMATION
, keying the location would directly snap back the rotation & scale to the animated values.
A possible solution could be to only flush to not-manually-changed properties. But that means we have to know what was manually changed since the last time the animation was evaluated. Currently it's impossible to tell "needs updating because the animation data changed" from "should be skipped because the property value was manually changed".