Skip to main content

ashlar_motion/
lanes.rs

1//! Values that animate: anything that maps to up to four f32 lanes.
2
3/// The most lanes a value can have.
4pub const MAX_LANES: usize = 4;
5
6/// The lanes of a value; lanes past `Animatable::LANES` are unused (0).
7pub type Lanes = [f32; MAX_LANES];
8
9/// A value that animates lane by lane. Each lane moves independently along the same curve.
10pub trait Animatable: Copy {
11    /// How many lanes the value uses (at most [`MAX_LANES`]; more are ignored).
12    const LANES: usize;
13    /// The value as lanes.
14    fn to_lanes(self) -> Lanes;
15    /// The value from lanes.
16    fn from_lanes(lanes: Lanes) -> Self;
17}
18
19impl Animatable for f32 {
20    const LANES: usize = 1;
21    fn to_lanes(self) -> Lanes {
22        [self, 0.0, 0.0, 0.0]
23    }
24    fn from_lanes([x, ..]: Lanes) -> Self {
25        x
26    }
27}
28
29impl Animatable for [f32; 2] {
30    const LANES: usize = 2;
31    fn to_lanes(self) -> Lanes {
32        let [x, y] = self;
33        [x, y, 0.0, 0.0]
34    }
35    fn from_lanes([x, y, ..]: Lanes) -> Self {
36        [x, y]
37    }
38}
39
40impl Animatable for [f32; 3] {
41    const LANES: usize = 3;
42    fn to_lanes(self) -> Lanes {
43        let [x, y, z] = self;
44        [x, y, z, 0.0]
45    }
46    fn from_lanes([x, y, z, _]: Lanes) -> Self {
47        [x, y, z]
48    }
49}
50
51impl Animatable for [f32; 4] {
52    const LANES: usize = 4;
53    fn to_lanes(self) -> Lanes {
54        self
55    }
56    fn from_lanes(lanes: Lanes) -> Self {
57        lanes
58    }
59}
60
61/// A rectangle by its four edges, in points. Animating by edges keeps an edge that does not
62/// move still, where animating by position and size would wobble it.
63#[derive(Clone, Copy, Debug, PartialEq, Default)]
64pub struct Edges {
65    /// Left edge (min x).
66    pub left: f32,
67    /// Top edge (min y).
68    pub top: f32,
69    /// Right edge (max x).
70    pub right: f32,
71    /// Bottom edge (max y).
72    pub bottom: f32,
73}
74
75impl Edges {
76    /// Edges from left, top, right, bottom.
77    pub const fn new(left: f32, top: f32, right: f32, bottom: f32) -> Edges {
78        Edges { left, top, right, bottom }
79    }
80}
81
82impl Animatable for Edges {
83    const LANES: usize = 4;
84    fn to_lanes(self) -> Lanes {
85        [self.left, self.top, self.right, self.bottom]
86    }
87    fn from_lanes([left, top, right, bottom]: Lanes) -> Self {
88        Edges { left, top, right, bottom }
89    }
90}
91
92/// The lane count of `T`, at most [`MAX_LANES`].
93pub(crate) const fn lane_count<T: Animatable>() -> usize {
94    if T::LANES < MAX_LANES { T::LANES } else { MAX_LANES }
95}