Derive Macro mina::Animate

source ·
#[derive(Animate)]
{
    // Attributes available to this derive:
    #[animate]
}
Expand description

Sets up a type for animation.

Animatable types gain two functions:

  • timeline() creates a TimelineBuilder that can be used to build a single animation Timeline. Timelines provide the interpolates values of the animatable type at any arbitrary point in time.
  • keyframe() creates a KeyframeBuilder which is used to provide Keyframe instances to the timeline builder. Keyframes specify the exact values at a specific point in the timeline.

In addition, a specific timeline type is generated with a Timeline suffix; for example, if the name of the type is Style, then the generated timeline type will be StyleTimeline. This type will have the same visibility as the animatable type, and can be used directly to store the timeline, or an animator based on the timeline, without boxing.

Making a type animatable also allows it to be used with the animator macro.

The following requirements apply to any type decorated with #[derive(Animate}]:

  1. Must be a struct. Tuple and enum types are not supported.
  2. Must implement the Clone and Default traits.
  3. All animated fields must implement Lerp.
    • A blanket implementation is provided for all primitive numeric types.
    • Other types may need explicit implementations and/or a newtype for unowned types.
    • To exclude fields from animation, either because it is not Lerpable or simply because it is intended to be constant, add the #[animate] helper attribute to all fields which should be animated; any remaining fields not decorated will be ignored.
  4. Nested structures, Option fields, etc. are allowed, but will be treated as black-box, which means the actual type of the field (e.g. the entire struct) must meet the Lerp requirement above. This can be the desired behavior for a limited number of complex types such as vectors or colors, but usually flat structs are more appropriate.
  5. Generic types are not supported (for now) at the struct level, although the individual fields can be generic.

Example

use mina::prelude::*;

#[derive(Animate, Clone, Debug, Default, PartialEq)]
struct Style {
    alpha: f32,
    size: u16,
}

let timeline = Style::timeline()
    .duration_seconds(5.0)
    .delay_seconds(1.0)
    .keyframe(Style::keyframe(1.0).alpha(1.0).size(25))
    .build();

let mut values = Style::default();
timeline.update(&mut values, 3.0);
assert_eq!(values, Style { alpha: 0.4, size: 10 });