ff_filter/animation/
keyframe.rs1use std::cmp::Ordering;
2use std::time::Duration;
3
4use super::{Easing, Lerp};
5
6#[derive(Debug, Clone)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[cfg_attr(
21 feature = "serde",
22 serde(bound(
23 serialize = "T: serde::Serialize",
24 deserialize = "T: serde::Deserialize<'de>",
25 ))
26)]
27pub struct Keyframe<T: Lerp> {
28 pub timestamp: Duration,
30 pub value: T,
32 pub easing: Easing,
34}
35
36impl<T: Lerp> Keyframe<T> {
37 pub fn new(timestamp: Duration, value: T, easing: Easing) -> Self {
39 Self {
40 timestamp,
41 value,
42 easing,
43 }
44 }
45}
46
47impl<T: Lerp> PartialEq for Keyframe<T> {
50 fn eq(&self, other: &Self) -> bool {
51 self.timestamp == other.timestamp
52 }
53}
54
55impl<T: Lerp> Eq for Keyframe<T> {}
56
57impl<T: Lerp> PartialOrd for Keyframe<T> {
58 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63impl<T: Lerp> Ord for Keyframe<T> {
64 fn cmp(&self, other: &Self) -> Ordering {
65 self.timestamp.cmp(&other.timestamp)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[derive(Clone, Debug)]
76 struct TestVal(f64);
77
78 impl Lerp for TestVal {
79 fn lerp(a: &Self, b: &Self, t: f64) -> Self {
80 TestVal(a.0 + (b.0 - a.0) * t)
81 }
82 }
83
84 fn kf(ms: u64, v: f64) -> Keyframe<TestVal> {
85 Keyframe::new(Duration::from_millis(ms), TestVal(v), Easing::Linear)
86 }
87
88 #[test]
89 fn keyframe_new_should_store_all_fields() {
90 let ts = Duration::from_millis(500);
91 let kf = Keyframe::new(ts, TestVal(1.0), Easing::EaseInOut);
92 assert_eq!(kf.timestamp, ts);
93 assert!((kf.value.0 - 1.0).abs() < f64::EPSILON);
94 assert!(matches!(kf.easing, Easing::EaseInOut));
95 }
96
97 #[test]
98 fn keyframe_should_order_by_timestamp() {
99 let a = kf(100, 0.0);
100 let b = kf(200, 0.5);
101 let c = kf(300, 1.0);
102
103 assert!(a < b);
104 assert!(b < c);
105 assert!(a < c);
106
107 let mut frames = vec![c, a, b];
108 frames.sort();
109 assert_eq!(frames[0].timestamp, Duration::from_millis(100));
110 assert_eq!(frames[1].timestamp, Duration::from_millis(200));
111 assert_eq!(frames[2].timestamp, Duration::from_millis(300));
112 }
113
114 #[test]
115 fn keyframe_should_compare_equal_by_timestamp_only() {
116 let a = Keyframe::new(Duration::from_millis(100), TestVal(0.0), Easing::Linear);
117 let b = Keyframe::new(Duration::from_millis(100), TestVal(99.0), Easing::Hold);
118 assert_eq!(a, b);
120 assert_eq!(a.cmp(&b), Ordering::Equal);
121 }
122
123 #[test]
124 fn keyframe_should_be_less_than_later_keyframe() {
125 let early = kf(0, 0.0);
126 let late = kf(1000, 1.0);
127 assert!(early < late);
128 assert!(late > early);
129 }
130}