To be added to the [developer docs]( (just using hackmd as a nice markdown editor with mermaid diagram preview). ## High-level Overview Project Balava introduces a new `Animation` datablock, which is intended to eventually replace `Action`s and the NLA system. The `Animation` datablock is designed to hold animation data for multiple IDs at once, and also to accommodate layered animation and NLA workflows. At a high level, there are only a few key concepts in the new `Animation` datablock: - `Output`s - `Layer`s - `Strip`s ```mermaid classDiagram direction TB Animation --> Output Animation --> Layer Layer --> Strip class Animation { list~Output~ outputs list~Layer~ layers } class Output { string name int handle } class Layer { string name enum mix_mode float mix_influence list~Strip~ strips } class Strip { enum type float frame_start float frame_end float frame_offset ---- animation_data } ``` Let's discuss them in more detail, starting from the lowest-level component—the `Strip`—and building up from there. ### `Strip`s `Strip`s live on `Layer`s (discussed below), and conceptually are similar to clips in a video editor. They contain the actual animation data for an `Animation` datablock, and place that data on the timeline. `Strip`s have a start frame, end frame, and an offset: - The start/end frames determine a `Strip`'s *extent* on the timeline, but specifically do *not* affect how its animation data is mapped (i.e. what frame in the `Strip` maps to what frame on the timeline). You can think of a `Strip` as conceptually being infinite, with animation data anywhere within the strip's local timeline. The start and end frames simply determine where in the global timeline the `Strip`'s data is "visible", but do not affect how its local timeline is mapped to the global timeline. - The offset (also in frames) is what determines how the local timeline of the `Strip` is mapped to the global timeline. It simply offsets the strip's data in time, as suggested by the name. An offset of zero, for example, means that the local strip time and global time are aligned. Note that strips can have infinite extent, such that they occupy the entire timeline of the layer they are on. In the future there will be multiple `Strip` types, but currently there is only one type: the `KeyframeStrip`, which contains f-curves. (An example of another strip type we're considering for the future is the `ModifierStrip`, which modifies animation data rather than containing animation data itself.) Notably, `Strip`s can contain animation for more than one ID at a time. This is discussed in more detail in the `Output`s section further below. ### `Layer`s Animation `Layer`s are analogous to layers in something like Gimp or Photoshop, or tracks in a video editor: they stack on top of each other and mix together to create the final animation. Much like in a video editor or DAW, `Layer`s do not themselves directly contain animation data. Rather, `Layer`s contain `Strip`s which in turn contain animation data. Similar to image editing software, each `Layer` has a mix mode which determines how it is combined with the layer below it. We plan to have at least "replace" and "offset" mix modes. Also similar to image editing software, each layer has an influence (analogous to opacity) which determines how much of an effect the layer has. ### `Output`s One of the strong points of `Actions` (from the current non-Baklava system) is that they are *loosely coupled* with the IDs they animate. In other words: you can easily swap out the `Action` that animates a given ID, and `Actions` are not limited to animating a specific single ID. However, `Action`s can only contain a single ID's worth of animation data at a time. We wanted to lift that latter restriction with the new `Animation` datablock, allowing it to store animation data for more than one ID at a time, but still with the *loose coupling*. One approach to storing animation for multiple IDs would be to simply associate each f-curve with a specific ID. Then when an ID is connected with an `Animation` datablock, it uses the f-curves that are associated with it. However, that would *tightly couple* the animation data with the IDs, making it difficult to swap out one ID for another (e.g. swapping out a proxy rig for the final full-res rig). So instead we opted for what we're calling `Output`s. An `Output` is basically a place-holder for an ID. Every piece of animation data (e.g. an f-curve) in an `Animation` datablock is associated with an `Output`, and when an actual ID is connected to an `Animation` datablock it also specifies which `Output` it uses. This approach gives the `Animation` datablock the best of both worlds: it can contain animation data for more than one ID, while also keeping the coupling loose and allowing IDs to be easily connected with whichever animation data is desired. Each `Animation` datablock has a list of `Output`s at the top-level. Those `Output`s are then referenced within the `Strip`s of the `Animation` datablock to associate f-curves or other animation data with them. ## Lower-level Details ### Output Handles TODO ### Evaluation TODO