1use ordered_float::OrderedFloat;
12
13use crate::interpolator::InterpolationFunction;
14
15pub type Time = OrderedFloat<f32>;
16
17pub trait Duration {
19 fn as_f32(&self) -> f32;
21}
22
23impl Duration for f32 {
24 fn as_f32(&self) -> f32 {
25 *self
26 }
27}
28
29impl Duration for () {
30 fn as_f32(&self) -> f32 {
31 0.
32 }
33}
34
35pub struct Keyframe<A, T, Dur: Duration> {
39 pub time: Time,
41 pub duration: Dur,
43 pub argument: A,
45 pub value: T,
47}
48
49impl<A, T, Dur: Duration> Keyframe<A, T, Dur> {
50 pub fn time(&self) -> &Time {
52 &self.time
53 }
54
55 pub fn duration(&self) -> f32 {
57 self.duration.as_f32()
58 }
59
60 pub fn value(&self) -> &T {
62 &self.value
63 }
64
65 pub fn argument(&self) -> &A {
67 &self.argument
68 }
69}
70
71impl<A, T, Dur: Duration> PartialEq for Keyframe<A, T, Dur> {
72 fn eq(&self, other: &Self) -> bool {
73 self.time.eq(&other.time)
74 }
75}
76
77impl<A, T, Dur: Duration> Eq for Keyframe<A, T, Dur> {}
78
79impl<A, T, Dur: Duration> PartialOrd for Keyframe<A, T, Dur> {
80 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
81 Some(self.cmp(other))
82 }
83}
84
85impl<A, T, Dur: Duration> Ord for Keyframe<A, T, Dur> {
86 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
87 self.time.cmp(&other.time)
88 }
89}
90
91impl<T> From<(Time, T)> for Keyframe<(), T, ()> {
92 fn from((time, value): (Time, T)) -> Self {
93 Self {
94 time,
95 duration: (),
96 argument: (),
97 value,
98 }
99 }
100}
101
102impl<T> From<(f32, T)> for Keyframe<(), T, ()> {
103 fn from((time, value): (f32, T)) -> Self {
104 Self::from((OrderedFloat::from(time), value))
105 }
106}
107
108impl<T, Dur: Duration> From<(Time, Dur, T)> for Keyframe<(), T, Dur> {
109 fn from((time, duration, value): (Time, Dur, T)) -> Self {
110 Self {
111 time,
112 duration,
113 value,
114 argument: (),
115 }
116 }
117}
118
119impl<T, Dur: Duration> From<(f32, Dur, T)> for Keyframe<(), T, Dur> {
120 fn from((time, duration, value): (f32, Dur, T)) -> Self {
121 Self::from((OrderedFloat::from(time), duration, value))
122 }
123}
124
125impl<A, T, Dur: Duration> From<(Time, Dur, A, T)> for Keyframe<A, T, Dur> {
126 fn from((time, duration, argument, value): (Time, Dur, A, T)) -> Self {
127 Self {
128 time,
129 duration,
130 value,
131 argument,
132 }
133 }
134}
135
136impl<A, T, Dur: Duration> From<(f32, Dur, A, T)> for Keyframe<A, T, Dur> {
137 fn from((time, duration, argument, value): (f32, Dur, A, T)) -> Self {
138 Self::from((OrderedFloat::from(time), duration, argument, value))
139 }
140}
141
142pub struct Timeline<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T>> {
144 keyframes: Vec<Keyframe<A, T, Dur>>,
147 default: T,
149 interpolation_function: I,
151}
152
153impl<A: Copy, T: Copy + Default, Dur: Duration, I: InterpolationFunction<A, T> + Default> Default
154 for Timeline<A, T, Dur, I>
155{
156 fn default() -> Self {
157 Self {
158 keyframes: Vec::new(),
159 default: T::default(),
160 interpolation_function: Default::default(),
161 }
162 }
163}
164
165impl<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T> + Default>
166 Timeline<A, T, Dur, I>
167{
168 pub fn new(default: T) -> Self {
171 Self {
172 keyframes: Vec::new(),
173 default,
174 interpolation_function: Default::default(),
175 }
176 }
177}
178
179impl<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T>> Timeline<A, T, Dur, I> {
180 pub fn new_with_interpolation(default: T, interpolation_function: I) -> Self {
183 Self {
184 keyframes: Vec::new(),
185 default,
186 interpolation_function,
187 }
188 }
189
190 fn search_time(&self, time: Time) -> Result<usize, usize> {
193 self.keyframes.binary_search_by_key(&&time, Keyframe::time)
194 }
195
196 fn get_idx(&self, time: Time) -> usize {
198 match self.search_time(time) {
199 Ok(idx) => idx,
200 Err(idx) => idx,
201 }
202 }
203
204 fn find_idx(&self, time: Time) -> Option<usize> {
209 match self.search_time(time) {
210 Ok(idx) => Some(idx),
211 Err(idx) => {
212 if idx > 0 {
213 Some(idx - 1)
214 } else {
215 None
216 }
217 }
218 }
219 }
220
221 pub fn get(&self, time: Time) -> T {
224 let idx = self.find_idx(time);
225 if let Some(idx) = idx {
226 let keyframe = &self.keyframes[idx];
227 let to = keyframe.value;
228 let from = idx
229 .checked_sub(1)
230 .map(|i| &self.keyframes[i])
231 .map(|k| I::ENDPOINT.get(self.default, k.value))
232 .unwrap_or(self.default);
233 let duration = keyframe.duration.as_f32().into();
234 let keyframe_relative_time = time - keyframe.time; if keyframe_relative_time >= duration {
236 return I::ENDPOINT.get(from, to);
238 }
239 let fraction = keyframe_relative_time / duration;
240 self.interpolation_function
241 .interpolate(fraction, keyframe.argument, from, to)
242 } else {
243 self.default
244 }
245 }
246
247 pub fn add(&mut self, keyframe: impl Into<Keyframe<A, T, Dur>>) -> &mut Self {
249 let keyframe = keyframe.into();
250 self.keyframes.insert(self.get_idx(keyframe.time), keyframe);
251 self
252 }
253
254 pub fn add_all(
256 &mut self,
257 keyframes: impl IntoIterator<Item = impl Into<Keyframe<A, T, Dur>>>,
258 ) -> &mut Self {
259 self.keyframes.extend(keyframes.into_iter().map(Into::into));
260 self.keyframes.sort();
261 self
262 }
263}