freya_animation/
anim_color.rs

1use std::time::Duration;
2
3use freya_core::prelude::Color;
4
5use crate::{
6    easing::{
7        Function,
8        apply_value,
9    },
10    hook::{
11        AnimDirection,
12        AnimatedValue,
13        Ease,
14        ReadAnimatedValue,
15    },
16};
17
18/// Animate a color.
19#[derive(Clone, PartialEq, Default)]
20pub struct AnimColor {
21    origin: Color,
22    destination: Color,
23    time: Duration,
24    ease: Ease,
25    function: Function,
26
27    value: Color,
28}
29
30impl AnimColor {
31    pub fn new(origin: impl Into<Color>, destination: impl Into<Color>) -> Self {
32        let origin = origin.into();
33        Self {
34            origin,
35            destination: destination.into(),
36            time: Duration::default(),
37            ease: Ease::default(),
38            function: Function::default(),
39
40            value: origin,
41        }
42    }
43
44    /// Set the animation duration using milliseconds. Use `Self::duration` if you want to specify the duration in another form.
45    pub fn time(mut self, time: u64) -> Self {
46        self.time = Duration::from_millis(time);
47        self
48    }
49
50    /// Set the animation duration using milliseconds.
51    pub fn duration(mut self, duration: Duration) -> Self {
52        self.time = duration;
53        self
54    }
55
56    /// Set the easing type. See `Ease` for all the types.
57    pub fn ease(mut self, ease: Ease) -> Self {
58        self.ease = ease;
59        self
60    }
61
62    /// Set the easing function. See `Function` for all the types.
63    pub fn function(mut self, function: Function) -> Self {
64        self.function = function;
65        self
66    }
67
68    /// Read the value of the [AnimColor] as a String.
69    pub fn value(&self) -> Color {
70        self.value
71    }
72}
73
74impl From<&AnimColor> for Color {
75    fn from(value: &AnimColor) -> Self {
76        value.value()
77    }
78}
79
80impl AnimatedValue for AnimColor {
81    fn prepare(&mut self, direction: AnimDirection) {
82        match direction {
83            AnimDirection::Forward => self.value = self.origin,
84            AnimDirection::Reverse => {
85                self.value = self.destination;
86            }
87        }
88    }
89
90    fn is_finished(&self, index: u128, direction: AnimDirection) -> bool {
91        match direction {
92            AnimDirection::Forward => {
93                index >= self.time.as_millis()
94                    && self.value.r() == self.destination.r()
95                    && self.value.g() == self.destination.g()
96                    && self.value.b() == self.destination.b()
97                    && self.value.a() == self.destination.a()
98            }
99            AnimDirection::Reverse => {
100                index >= self.time.as_millis()
101                    && self.value.r() == self.origin.r()
102                    && self.value.g() == self.origin.g()
103                    && self.value.b() == self.origin.b()
104                    && self.value.a() == self.origin.a()
105            }
106        }
107    }
108
109    fn advance(&mut self, index: u128, direction: AnimDirection) {
110        let (origin, destination) = match direction {
111            AnimDirection::Forward => (self.origin, self.destination),
112            AnimDirection::Reverse => (self.destination, self.origin),
113        };
114        let r = apply_value(
115            origin.r() as f32,
116            destination.r() as f32,
117            index.min(self.time.as_millis()),
118            self.time,
119            self.ease,
120            self.function,
121        );
122        let g = apply_value(
123            origin.g() as f32,
124            destination.g() as f32,
125            index.min(self.time.as_millis()),
126            self.time,
127            self.ease,
128            self.function,
129        );
130        let b = apply_value(
131            origin.b() as f32,
132            destination.b() as f32,
133            index.min(self.time.as_millis()),
134            self.time,
135            self.ease,
136            self.function,
137        );
138        let a = apply_value(
139            origin.a() as f32,
140            destination.a() as f32,
141            index.min(self.time.as_millis()),
142            self.time,
143            self.ease,
144            self.function,
145        );
146        self.value = Color::from_argb(a as u8, r as u8, g as u8, b as u8);
147    }
148
149    fn finish(&mut self, direction: AnimDirection) {
150        self.advance(self.time.as_millis(), direction);
151    }
152
153    /// Reverses the `origin` and the `destination` of the [AnimColor].
154    fn into_reversed(self) -> Self {
155        Self {
156            origin: self.destination,
157            destination: self.origin,
158            ..self
159        }
160    }
161}
162
163impl ReadAnimatedValue for AnimColor {
164    type Output = Color;
165    fn value(&self) -> Self::Output {
166        self.value()
167    }
168}