cogs_gamedev/
ease.rs

1//! A collection of easing functions.
2
3use num_traits::{Float, FloatConst};
4
5/// Trait for things that can interpolate values.
6///
7/// See [this handy cheatsheet](https://easings.net).
8pub trait Interpolator<Value>: Float + FloatConst {
9    /// Get a value self% between start and end.
10    /// `self` being 0 should mean all the way at `start`; `self` being 1 means all the way at `end`.
11    /// The implementation must accept values outside of 0 and 1, however,
12    /// for easing functions like `elastic_in`.
13    ///
14    /// All the easing functions are defined in terms of this function.
15    /// An equation is run on `self` to get a modified value, and the modified
16    /// value has `lerp` called on it.
17    fn lerp(self, start: Value, end: Value) -> Value;
18
19    fn sine_in(self, start: Value, end: Value) -> Value {
20        let it = Self::one() - ((self * Self::PI()) / Self::from(2).unwrap()).cos();
21        it.lerp(start, end)
22    }
23    fn sine_out(self, start: Value, end: Value) -> Value {
24        let it = ((self * Self::PI()) / Self::from(2).unwrap()).sin();
25        it.lerp(start, end)
26    }
27    fn sine_in_out(self, start: Value, end: Value) -> Value {
28        let it = -((self * Self::PI()).cos() - Self::one()) / Self::from(2).unwrap();
29        it.lerp(start, end)
30    }
31
32    fn quad_in(self, start: Value, end: Value) -> Value {
33        let it = self * self;
34        it.lerp(start, end)
35    }
36    fn quad_out(self, start: Value, end: Value) -> Value {
37        let it = Self::one() - (Self::one() - self) * (Self::one() - self);
38        it.lerp(start, end)
39    }
40    fn quad_in_out(self, start: Value, end: Value) -> Value {
41        let two = Self::from(2).unwrap();
42        let it = if self < Self::from(0.5).unwrap() {
43            two * self * self
44        } else {
45            Self::one() - (-two * self + two).powi(2) / two
46        };
47        it.lerp(start, end)
48    }
49
50    // impl the rest later
51}
52
53impl<F> Interpolator<F> for F
54where
55    F: Float + FloatConst,
56{
57    fn lerp(self, start: F, end: F) -> F {
58        start * (Self::one() - self) + end * self
59    }
60}
61
62impl<F, const N: usize> Interpolator<[F; N]> for F
63where
64    F: Float + FloatConst + Copy,
65{
66    fn lerp(self, start: [F; N], end: [F; N]) -> [F; N] {
67        let mut out = [Self::zero(); N];
68        for i in 0..N {
69            out[i] = self.lerp(start[i], end[i]);
70        }
71        out
72    }
73}