Try   HackMD

Layered Animation Model: Open Questions & TODOs

Open Questions

How do we deal with low level errors?

See KeyframeStrip::keyframe_insert(). That function can fail for a few reasons:

  • The FCurve exists, but not able to receive new keys (see BKE_fcurve_is_keyframable()).
  • Inserting a key can fail, for example because the 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:

How do we deal with multiple return values?

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>.

Property background colors

How to do deal with animation layers?

  1. Which color for "animated by multiple layers"?
  2. Show animation of non-selected layers at all?
  3. How about "is on a key" color? One layer may have a key for the prop, the other may be interpolating the same prop.

Answer: use the same logic as where new keys go.

Markers

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.

  • Timeline Markers already have IDProperties, new system should also support that.
  • Markers could also have "blend weight curves", "activation curves", however we want to call them. Blender could then use those to produce a weighted combination of markers, and use that to animate things.
  • More generally, the markers could be seen as an M×N relationship, with M markers defined over time, animating N things (like multiple shape-key blend weights).
  • F-Curves vs. Markers are a bit like mesh (with explicit edge/face connections between points) and point clouds (where the system interprets the point properties in various ways).
  • The ID Chooser channel type might be implemented via this new system too.

TODOs

✅ Update Python example code

Creating a new layer no longer automatically creates a new strip. The Py should be updated for this.

✅ Anim Evaluation Result class

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.

✅ Create sensible API for adding more than one strip

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.

✅ Define strip boundaries.

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)

✅ Define strip extrapolation rules.

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).

✅ Add support for half-infinite strips

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.

Design replacement API for UI operations

  • GUI color queries:
    • Is this property animated?
    • Is there a key on this frame?
    • Is the current property value consistent with the animated value?
  • Animation Filtering is for later.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

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.

Create some hashmaps for faster lookups

There are TODO markers about this in the code.

  • on Animation: from stable index to Output *
  • on KeyframeStrip: from output stable index to ChannelsForOutput *.

Test library linking

Library linking should work as expected:

  • Linking an animated data-block should bring in its Animation, but when linking an Animation data-block it should not bring in everything that was animated by it.
  • Linking an Animation data-block should make it possible to connect local data-blocks to its output.
  • Linking in the animated data-blocks from the first step into yet another file should also work, and they should still be animated.

Add functions to remove stuff

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?

Create new set of notifiers

The existing notifiers (ND_KEYFRAME, ND_ANIMCHAN and friends) may not be sufficient to nicely handle layer / strip events.

For future: more granular depsgraph tagging

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.

Depsgraph tagging for animation, but skipping manually-changed properties

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".