aura_anim_core/keyframes/
keyframe.rs1use lilt::Easing;
2
3use crate::traits::Animatable;
4
5#[derive(Debug, Clone)]
7pub struct Keyframe<T: Animatable> {
8 time: f64,
9 value: T,
10 easing: Easing,
11}
12
13impl<T: Animatable> Keyframe<T> {
14 #[must_use]
16 pub fn new(time: f64, value: T) -> Self {
17 let time = if time.is_finite() { time } else { 0.0 };
18
19 Self {
20 time,
21 value,
22 easing: Easing::default(),
23 }
24 }
25
26 #[must_use]
28 pub fn time(&self) -> f64 {
29 self.time
30 }
31
32 #[must_use]
34 pub fn value(&self) -> &T {
35 &self.value
36 }
37
38 #[must_use]
40 pub fn easing(&self) -> Easing {
41 self.easing
42 }
43
44 #[must_use]
46 pub fn with_easing(mut self, easing: Easing) -> Self {
47 self.easing = easing;
48 self
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::Keyframe;
55 use float_cmp::assert_approx_eq;
56 use lilt::Easing;
57
58 #[test]
59 fn invalid_time_is_replaced_with_zero() {
60 assert_approx_eq!(f64, Keyframe::new(f64::NAN, 1.0_f32).time(), 0.0);
61 assert_approx_eq!(f64, Keyframe::new(f64::INFINITY, 1.0_f32).time(), 0.0);
62 }
63
64 #[test]
65 fn accessors_return_stored_values() {
66 let frame = Keyframe::new(25.0, 3_i32).with_easing(Easing::EaseIn);
67
68 assert_approx_eq!(f64, frame.time(), 25.0);
69 assert_eq!(*frame.value(), 3);
70 assert_eq!(frame.easing(), Easing::EaseIn);
71 }
72}