Skip to main content

freya_animation/
anim_color.rs

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