Skip to main content

dinamika_core/signal/
tweenable.rs

1//! A type whose values can be linearly interpolated ([`Tweenable`]).
2
3use dinamika_cpu::{Color, Point};
4
5/// A type whose values can be linearly interpolated.
6///
7/// Implemented for `f32`, `f64`, [`Color`] and [`Point`]. Implement it for your
8/// own types to animate signals over them.
9pub trait Tweenable: Clone + 'static {
10    /// Linear interpolation from `a` to `b` by the parameter `t` (`0..=1`).
11    fn lerp(a: &Self, b: &Self, t: f32) -> Self;
12}
13
14impl Tweenable for f32 {
15    #[inline]
16    fn lerp(a: &Self, b: &Self, t: f32) -> Self {
17        a + (b - a) * t
18    }
19}
20
21impl Tweenable for f64 {
22    #[inline]
23    fn lerp(a: &Self, b: &Self, t: f32) -> Self {
24        a + (b - a) * t as f64
25    }
26}
27
28impl Tweenable for Color {
29    #[inline]
30    fn lerp(a: &Self, b: &Self, t: f32) -> Self {
31        Color::from_rgba(
32            a.red() + (b.red() - a.red()) * t,
33            a.green() + (b.green() - a.green()) * t,
34            a.blue() + (b.blue() - a.blue()) * t,
35            a.alpha() + (b.alpha() - a.alpha()) * t,
36        )
37    }
38}
39
40impl Tweenable for Point {
41    #[inline]
42    fn lerp(a: &Self, b: &Self, t: f32) -> Self {
43        Point::lerp(*a, *b, t)
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn color_lerp_midpoint() {
53        let c = Color::lerp(
54            &Color::from_rgba8(0, 0, 0, 255),
55            &Color::from_rgba8(255, 255, 255, 255),
56            0.5,
57        );
58        assert!((c.red() - 0.5).abs() < 0.01);
59    }
60}