Click or drag to resize
DigitalRuneControlling Animations

This topic explains some general concepts and contains information about starting, stopping and controlling animations.

This topic contains the following sections:

Animation service

The interface IAnimationService (implemented by the AnimationManager) exposes all methods required to start new animations (see method StartAnimation and its overloads) and stop running animations (see method StopAnimation and its overloads).

IsAnimated is a method that allows to query whether an object or property is currently being animated.

When a new animation is started the animated properties do not change immediately. Animation values are only updated and applied when the methods Update and ApplyAnimations of the animation manager are called. But in certain cases the animated properties should change immediately. In this case the method UpdateAndApplyAnimation (or one of its overloads) can be called. This method instantly evaluates all animations that affect the specified objects or properties and applies the new animation values.

Timelines, animations and animation instances

The animation system differentiates between timelines, animations and animation instances. (Note: These are no official terms - they are only used by DigitalRune Animation. The term animation is used very loosely throughout this documentation and can usually mean any of the above.)

Timelines

A timeline defines when an animation starts and how long it is active. It is defined by the interface ITimeline. Anything that implements ITimeline can be played back by the animation system. The most important types that implement this interface are TimelineClip and TimelineGroup. These types of animations do not compute an animation value themselves. Instead they only arrange other animations.

Animations

Animation instances

When animations are started AnimationInstances are created. An animation instance maintains the runtime state (such as the current animation time) of the animations. See AnimationInstance for more information.

Each animation controller has a property AnimationInstance which points to its root animation instance.

Animation controller

Every time a new animation is started an AnimationController is returned. The animation controller is a lightweight handle (struct) that allows to interactively control the associated animation instances.

An animation controller can also be created explicitly by calling the method CreateController of the animation service. In this case the animations are assigned to the specified objects and properties, but the animations do not start immediately.

The animation controller allows to start (see method Start) and stop (see method Stop) animations, pause (see method Pause) and resume (see method Resume) the animation timing, change the playback speed (see property Speed), query the state (see property State) of an animation, adjust the animation time (see property Time), and more.

UpdateAndApply can be called to immediately evaluate and apply the animations associated with the given animation controller.

Animation state

Timelines have a FillBehavior. The fill behavior determines what happens when the duration of the animation is exceeded. When it is set to Hold then the animation holds its last animation value. This animation value is returned until the animation is stopped manually. When the fill behavior is Stop then the animation system automatically removes the animation once the duration is exceeded.

Each animation instance stores its current state (see property State). The possible animation states are:

Animation timing

Each animation instance stores the current animation time (see property Time). Note that the animation state, described above, does not indicate whether the animation timing is active or not. I.e. whether the animation time is progressing or not. The animation timing can be paused and resumed by calling Pause and Resume. Pausing an animation won't affect the State. Use the property IsPaused to check whether the animation timing is paused or not.

The speed at which the animation time advances can be manipulated by changing the speed ratio (see property Speed). Setting the speed ratio to 0 also effectively pauses the animation, but this does not set IsPaused to true.

Resource pooling and auto-recycling

Animation instances are pooled objects: They are stored in an internal resource pool and reused whenever possible in order to avoid unnecessary memory allocations at runtime. There are two ways to recycle animation instances: manual recycling and auto-recycling.

Manual Recycling: When an animation controller is no longer needed the associated animation instance can be recycled by explicitly calling the method Recycle. When this method is called the animation controller becomes invalid and can no longer be used.

Auto-Recycling: Animations are automatically removed from the animation system when they stop. The animation system can be instructed to automatically recycle animation instances when they are removed. This is done by calling AutoRecycle or by setting the property AutoRecycleEnabled. For example:

C#
// Play an animation. Automatically recycle the associated animation
// instances once the animation stops.
var controller = animationService.StartAnimation(animation, property);
controller.AutoRecycle();

// Or, the short version:
animationService.StartAnimation(animation, property).AutoRecycle()

Note that the AnimationController itself is only a light-weight handle that does not allocate memory on the managed heap.

Animation transitions

When starting a new animation, either with IAnimationServiceStartAnimation(ITimeline, IAnimatableProperty, AnimationTransition) or with AnimationControllerStart(AnimationTransition), an AnimationTransition can be specified. Animation transitions control how new animations interact with already existing animations. This is relevant if multiple animations are applied to the same objects or properties. In this case the animation system needs to know whether to replace existing animations or whether to combine new animations with already existing animations. The class AnimationTransitions is a collection of predefined animation transitions.

The default behavior is SnapshotAndReplace: The animation system takes a snapshot of any currently running animations and then replaces the existing animations with the new animation. The snapshot of the animation value is then passed to the new animation as an input parameter. (Some animations - not all - make use of this input parameter. A FromToByAnimationT, for example, can be configured to animate from the snapshot value to another value.)

C#
// Start a new animation using Snapshot-And-Replace.
animationService.StartAnimation(animation, property, AnimationTransitions.SnapshotAndReplace());

The Replace transitions can be used to replace all previously running animations or to replace one particular animation.

C#
// Start a new animation and replace all existing animations that affect
// the specified property.
animationService.StartAnimation(animation, property, AnimationTransitions.Replace());

Some transitions (such as Replace) allow to specify a transition time: In this case the new animations slowly fade in over the specified duration. The result is a "fade-in" or a "cross-fade" between existing animations and the new animations.

C#
// Start a new animation using a cross-fade of 0.5 seconds.
TimeSpan crossFadeDuration = TimeSpan.FromSeconds(0.5);
animationService.StartAnimation(animation, property, AnimationTransitions.Replace(crossFadeDuration));

The transition Compose combines new animations with existing animations by building so called "animation composition chains".

C#
// Start a new animation adding them to the animation composition chain
// of the specified property.
animationService.StartAnimation(animation, property, AnimationTransitions.Compose());
Animation composition chains and animation weights

When animations are started using Compose the animations are combined using animation composition chains. The animation system manages an animation composition chain for every property that is being animated.

An animation composition chain stores all animation instances that affect a certain property. All animation instances are evaluated in the order in which they were added to the composition chain. The first animation instance receives the property's base value as its input. Every animation instance combines its output with the output of the previous stage in the animation composition chain. Additive animations, for example, can add their animation value to the output of the previous stage.

All animation instances have an animation weight (see property Weight). The animation weight is basically a factor that defines the intensity of the animation. An animation applies the animation weight when it combines its output with the output of the previous stage. (If the animation is the first or only animation of a composition chain it combines its value with the base value of the property that is being animated.)

The default value of the animation weights is 1 which means that 100% of the animation is applied, usually overriding any previous stage in an animation composition chain. A value of 0.75 means that result is a weighted combination of the previous stage (25%) and the output of the current animation (75%). A value of 0 basically disables the output of the current animation.

Note that the animation weights themselves are animatable properties! That means animation weights can be animated. This can be useful to manually fade animations in or out. (The animation system internally also animates the animation weights when it fades animations in or out.)