1use crate::{
8 easing::{Easing, EasingFunction},
9 interpolation::Lerp,
10 timeline::Keyframe,
11};
12use std::fmt::Debug;
13
14#[derive(Clone, Debug)]
37pub struct SubTimeline<Value: Clone> {
38 frames: Vec<SplitKeyframe<Value>>,
39 frame_index_map: Vec<usize>,
40 start_frame_override: Option<SplitKeyframe<Value>>,
41}
42
43impl<Value: Clone + Lerp> SubTimeline<Value> {
44 pub fn from_keyframes<'a, Data: 'a + Clone + Debug, ValueFn>(
59 keyframes: impl IntoIterator<Item = &'a Keyframe<Data>>,
60 default_value: Value,
61 get_value: ValueFn,
62 default_easing: Easing,
63 ) -> Self
64 where
65 ValueFn: Fn(&Data) -> Option<Value>,
66 {
67 let mut converted_frames = Vec::new();
68 let mut frame_index_map = Vec::new();
69 let mut current_easing = default_easing;
70 let mut has_frame_data = false;
71 for keyframe in keyframes.into_iter() {
72 if converted_frames.is_empty() && keyframe.normalized_time > 0.0 {
75 converted_frames.push(SplitKeyframe::new(
76 0.0,
77 default_value.clone(),
78 current_easing.clone(),
79 ));
80 }
81 if let Some(data) = get_value(&keyframe.data) {
82 has_frame_data = true;
83 if let Some(easing) = &keyframe.easing {
84 current_easing = easing.clone();
85 }
86 converted_frames.push(SplitKeyframe::new(
87 keyframe.normalized_time,
88 data,
89 current_easing.clone(),
90 ));
91 }
92 frame_index_map.push(converted_frames.len().max(1) - 1);
93 }
94 if !has_frame_data {
95 return Self::empty();
96 }
97 let trailing_frame = match converted_frames.last() {
98 Some(frame) if frame.normalized_time < 1.0 =>
99 {
102 Some(frame.with_time(1.0))
103 }
104 _ => None,
105 };
106 if let Some(trailing_frame) = trailing_frame {
107 converted_frames.push(trailing_frame);
108 }
109 Self {
110 frames: converted_frames,
111 frame_index_map,
112 start_frame_override: None,
113 }
114 }
115
116 pub fn override_start_value(&mut self, value: Value) {
129 if let Some(first_frame) = self.frames.first() {
130 self.start_frame_override = Some(first_frame.with_value(value));
131 }
132 }
133
134 pub fn value_at(
150 &self,
151 normalized_time: f32,
152 index_hint: usize,
153 enable_start_override: bool,
154 ) -> Option<Value> {
155 if self.frame_index_map.is_empty() {
156 return None;
157 }
158 let normalized_time = normalized_time.clamp(0.0, 1.0);
159 let bounding_frames =
160 self.get_bounding_frames(normalized_time, index_hint, enable_start_override)?;
161 Some(interpolate_value(&bounding_frames, normalized_time))
162 }
163
164 fn empty() -> Self {
165 Self {
166 frame_index_map: vec![],
167 frames: vec![],
168 start_frame_override: None,
169 }
170 }
171
172 fn get_bounding_frames(
173 &self,
174 normalized_time: f32,
175 index_hint: usize,
176 enable_start_override: bool,
177 ) -> Option<[&SplitKeyframe<Value>; 2]> {
178 let index_at = *self.frame_index_map.get(index_hint)?;
179 let frame_at = self.get_frame(index_at, enable_start_override)?;
180 if normalized_time < frame_at.normalized_time {
181 if index_at > 0 {
182 Some([
183 self.get_frame(index_at - 1, enable_start_override)?,
184 frame_at,
185 ])
186 } else {
187 None
188 }
189 } else if index_at == self.frames.len() - 1 {
190 Some([frame_at, frame_at])
191 } else {
192 self.frames
193 .get(index_at + 1)
194 .map(|next_frame| [frame_at, next_frame])
195 }
196 }
197
198 fn get_frame(
199 &self,
200 index: usize,
201 enable_start_override: bool,
202 ) -> Option<&SplitKeyframe<Value>> {
203 if enable_start_override && index == 0 {
204 if let Some(ref override_frame) = self.start_frame_override {
205 Some(override_frame)
206 } else {
207 self.frames.get(0)
208 }
209 } else {
210 self.frames.get(index)
211 }
212 }
213}
214
215#[derive(Clone, Debug)]
230struct SplitKeyframe<Value: Clone> {
231 easing: Easing,
232 normalized_time: f32,
233 value: Value,
234}
235
236impl<Value: Clone> SplitKeyframe<Value> {
237 fn new(normalized_time: f32, value: Value, easing: Easing) -> Self {
238 Self {
239 normalized_time,
240 value,
241 easing,
242 }
243 }
244
245 fn with_time(&self, normalized_time: f32) -> Self {
246 SplitKeyframe::new(normalized_time, self.value.clone(), self.easing.clone())
247 }
248
249 fn with_value(&self, value: Value) -> Self {
250 SplitKeyframe::new(self.normalized_time, value, self.easing.clone())
251 }
252}
253
254fn interpolate_value<Value: Clone + Lerp>(
255 bounding_frames: &[&SplitKeyframe<Value>; 2],
256 time: f32,
257) -> Value {
258 let [start_frame, end_frame] = bounding_frames;
259 let duration = end_frame.normalized_time - start_frame.normalized_time;
260 if duration == 0.0 {
261 return start_frame.value.clone();
262 }
263 let easing = &start_frame.easing;
267 let x = (time - start_frame.normalized_time) / duration;
268 let y = easing.calc(x);
269 start_frame.value.lerp(&end_frame.value, y)
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275 use crate::timeline::Timeline;
276
277 #[derive(Clone, Debug, Default, PartialEq)]
278 struct TestValues {
279 foo: u8,
280 bar: f32,
281 }
282
283 impl TestValues {
284 pub fn new(foo: u8, bar: f32) -> Self {
285 Self { foo, bar }
286 }
287
288 pub fn round(&self) -> Self {
291 Self {
292 foo: self.foo,
293 bar: self.bar.round(),
294 }
295 }
296 }
297
298 #[derive(Clone, Debug)]
299 struct TestKeyframeData {
300 foo: Option<u8>,
301 bar: Option<f32>,
302 }
303
304 impl TestKeyframeData {
305 fn new(foo: Option<u8>, bar: Option<f32>) -> Self {
306 Self { foo, bar }
307 }
308
309 fn full(foo: u8, bar: f32) -> Self {
310 Self {
311 foo: Some(foo),
312 bar: Some(bar),
313 }
314 }
315 }
316
317 #[derive(Debug)]
318 struct TestTimeline {
319 boundary_times: Vec<f32>,
320 foo: SubTimeline<u8>,
321 bar: SubTimeline<f32>,
322 }
323
324 impl TestTimeline {
325 fn new(keyframes: Vec<Keyframe<TestKeyframeData>>, default_easing: Easing) -> Self {
326 let defaults = TestValues::default();
327 Self {
328 foo: SubTimeline::from_keyframes(
329 &keyframes,
330 defaults.foo,
331 |k| k.foo,
332 default_easing.clone(),
333 ),
334 bar: SubTimeline::from_keyframes(
335 &keyframes,
336 defaults.bar,
337 |k| k.bar,
338 default_easing,
339 ),
340 boundary_times: keyframes.iter().map(|k| k.normalized_time).collect(),
341 }
342 }
343
344 fn update_with_override(
351 &self,
352 target: &mut TestValues,
353 time: f32,
354 enable_start_override: bool,
355 ) {
356 if self.boundary_times.is_empty() {
357 return;
358 }
359 let frame_index = match self.boundary_times.binary_search_by(|t| t.total_cmp(&time)) {
360 Ok(index) => index,
361 Err(next_index) => next_index.max(1) - 1,
362 };
363 if let Some(foo) = self.foo.value_at(time, frame_index, enable_start_override) {
364 target.foo = foo;
365 }
366 if let Some(bar) = self.bar.value_at(time, frame_index, enable_start_override) {
367 target.bar = bar;
368 }
369 }
370
371 fn values_at(&self, time: f32) -> TestValues {
372 let mut target = TestValues::default();
373 self.update(&mut target, time);
374 target
375 }
376
377 fn non_overridden_values_at(&self, time: f32) -> TestValues {
378 let mut target = TestValues::default();
379 self.update_with_override(&mut target, time, false);
380 target
381 }
382
383 fn updated_values_at<'a>(&self, values: &TestValues, time: f32) -> TestValues {
384 let mut updated_values = values.clone();
385 self.update(&mut updated_values, time);
386 updated_values
387 }
388 }
389
390 impl Timeline for TestTimeline {
391 type Target = TestValues;
392
393 fn start_with(&mut self, values: &Self::Target) {
394 self.foo.override_start_value(values.foo);
395 self.bar.override_start_value(values.bar);
396 }
397
398 fn update(&self, target: &mut Self::Target, time: f32) {
399 self.update_with_override(target, time, true);
400 }
401 }
402
403 #[test]
404 fn when_empty_then_does_not_modify() {
405 let timeline = TestTimeline::new(vec![], Easing::default());
406
407 let initial_values = TestValues::new(123, 583.122);
408 assert_eq!(
409 timeline.updated_values_at(&initial_values, 0.0),
410 initial_values
411 );
412 assert_eq!(
413 timeline.updated_values_at(&initial_values, 0.5),
414 initial_values
415 );
416 assert_eq!(
417 timeline.updated_values_at(&initial_values, 1.0),
418 initial_values
419 );
420 }
421
422 #[test]
423 fn when_property_not_used_then_does_not_modify_property() {
424 let keyframes = vec![
425 Keyframe::new(0.4, TestKeyframeData::new(Some(40), None), None),
426 Keyframe::new(0.6, TestKeyframeData::new(Some(50), None), None),
427 Keyframe::new(0.6, TestKeyframeData::new(Some(80), None), None),
428 ];
429 let timeline = TestTimeline::new(keyframes, Easing::default());
430
431 let initial_values = TestValues::new(100, 0.123);
432 assert_eq!(
433 timeline.updated_values_at(&initial_values, 0.0),
434 TestValues::new(0, 0.123)
435 );
436 assert_eq!(
437 timeline.updated_values_at(&initial_values, 0.5),
438 TestValues::new(45, 0.123)
439 );
440 assert_eq!(
441 timeline.updated_values_at(&initial_values, 1.0),
442 TestValues::new(80, 0.123)
443 );
444 }
445
446 #[test]
447 fn when_no_keyframe_at_zero_then_interpolates_from_defaults() {
448 let keyframes = vec![
449 Keyframe::new(0.25, TestKeyframeData::new(None, Some(50.0)), None),
450 Keyframe::new(0.5, TestKeyframeData::new(Some(80), Some(200.0)), None),
451 ];
452 let timeline = TestTimeline::new(keyframes, Easing::default());
453
454 assert_eq!(timeline.values_at(0.0), TestValues::default());
455 assert_eq!(timeline.values_at(0.1), TestValues::new(16, 20.0));
456 assert_eq!(timeline.values_at(0.25), TestValues::new(40, 50.0));
457 }
458
459 #[test]
460 fn when_full_keyframe_at_zero_then_interpolates_from_first_keyframe() {
461 let keyframes = vec![
462 Keyframe::new(0.0, TestKeyframeData::full(10, 20.0), None),
463 Keyframe::new(0.4, TestKeyframeData::full(50, 200.0), None),
464 ];
465 let timeline = TestTimeline::new(keyframes, Easing::default());
466
467 assert_eq!(timeline.values_at(0.0), TestValues::new(10, 20.0));
468 assert_eq!(timeline.values_at(0.2), TestValues::new(30, 110.0));
469 assert_eq!(timeline.values_at(0.4), TestValues::new(50, 200.0));
470 }
471
472 #[test]
473 fn when_partial_keyframe_at_zero_then_interpolates_from_defaults_and_first_keyframe() {
474 let keyframes = vec![
475 Keyframe::new(0.0, TestKeyframeData::new(Some(10), None), None),
476 Keyframe::new(0.4, TestKeyframeData::full(50, 200.0), None),
477 ];
478 let timeline = TestTimeline::new(keyframes, Easing::default());
479
480 assert_eq!(timeline.values_at(0.0), TestValues::new(10, 0.0));
481 assert_eq!(timeline.values_at(0.2), TestValues::new(30, 100.0));
482 assert_eq!(timeline.values_at(0.4), TestValues::new(50, 200.0));
483 }
484
485 #[test]
486 fn when_no_keyframe_at_end_then_stays_at_last_keyframe() {
487 let keyframes = vec![
488 Keyframe::new(0.5, TestKeyframeData::new(Some(30), None), None),
489 Keyframe::new(0.75, TestKeyframeData::new(Some(50), Some(1000.0)), None),
490 ];
491 let timeline = TestTimeline::new(keyframes, Easing::default());
492
493 assert_eq!(timeline.values_at(0.75), TestValues::new(50, 1000.0));
494 assert_eq!(timeline.values_at(0.85), TestValues::new(50, 1000.0));
495 assert_eq!(timeline.values_at(1.0), TestValues::new(50, 1000.0));
496 }
497
498 #[test]
499 fn when_keyframe_at_end_then_interpolates_to_last_keyframe() {
500 let keyframes = vec![
501 Keyframe::new(0.25, TestKeyframeData::full(40, 250.0), None),
502 Keyframe::new(0.5, TestKeyframeData::full(20, 0.0), None),
503 Keyframe::new(1.0, TestKeyframeData::full(60, 1000.0), None),
504 ];
505 let timeline = TestTimeline::new(keyframes, Easing::default());
506
507 assert_eq!(timeline.values_at(0.5), TestValues::new(20, 0.0));
508 assert_eq!(timeline.values_at(0.75), TestValues::new(40, 500.0));
509 assert_eq!(timeline.values_at(1.0), TestValues::new(60, 1000.0));
510 }
511
512 #[test]
513 fn when_easing_not_overridden_then_interpolates_with_default_easing() {
514 let keyframes = vec![
515 Keyframe::new(0.0, TestKeyframeData::full(0, 0.0), None),
516 Keyframe::new(1.0, TestKeyframeData::full(40, 100.0), None),
517 ];
518 let timeline = TestTimeline::new(keyframes, Easing::OutQuad);
519
520 assert_eq!(timeline.values_at(0.0).round(), TestValues::new(0, 0.0));
521 assert_eq!(timeline.values_at(0.2).round(), TestValues::new(20, 49.0));
522 assert_eq!(timeline.values_at(0.4).round(), TestValues::new(31, 78.0));
523 assert_eq!(timeline.values_at(0.6).round(), TestValues::new(37, 94.0));
524 assert_eq!(timeline.values_at(0.8).round(), TestValues::new(40, 99.0));
525 assert_eq!(timeline.values_at(1.0).round(), TestValues::new(40, 100.0));
526 }
527
528 #[test]
529 fn when_easing_overridden_then_uses_new_easing() {
530 let keyframes = vec![
531 Keyframe::new(0.0, TestKeyframeData::full(0, 0.0), None),
532 Keyframe::new(0.2, TestKeyframeData::full(50, 100.0), None),
533 Keyframe::new(
534 0.4,
535 TestKeyframeData::full(100, 400.0),
536 Some(Easing::OutCirc),
537 ),
538 Keyframe::new(0.6, TestKeyframeData::full(150, 1000.0), None),
539 Keyframe::new(
540 0.8,
541 TestKeyframeData::full(200, 5000.0),
542 Some(Easing::InSine),
543 ),
544 Keyframe::new(1.0, TestKeyframeData::full(250, 10000.0), None),
545 ];
546 let timeline = TestTimeline::new(keyframes, Easing::default());
547
548 assert_eq!(timeline.values_at(0.0).round(), TestValues::new(0, 0.0));
549 assert_eq!(timeline.values_at(0.1).round(), TestValues::new(25, 50.0));
550 assert_eq!(timeline.values_at(0.2).round(), TestValues::new(50, 100.0));
551 assert_eq!(timeline.values_at(0.3).round(), TestValues::new(75, 250.0));
552 assert_eq!(timeline.values_at(0.4).round(), TestValues::new(100, 400.0));
553 assert_eq!(timeline.values_at(0.5).round(), TestValues::new(135, 824.0));
554 assert_eq!(
555 timeline.values_at(0.6).round(),
556 TestValues::new(150, 1000.0)
557 );
558 assert_eq!(
559 timeline.values_at(0.7).round(),
560 TestValues::new(185, 3825.0)
561 );
562 assert_eq!(
563 timeline.values_at(0.8).round(),
564 TestValues::new(200, 5000.0)
565 );
566 assert_eq!(
567 timeline.values_at(0.9).round(),
568 TestValues::new(206, 5625.0)
569 );
570 assert_eq!(
571 timeline.values_at(1.0).round(),
572 TestValues::new(250, 10000.0)
573 );
574 }
575
576 #[test]
577 fn when_start_value_overridden_then_updates_if_non_empty() {
578 let keyframes = vec![
579 Keyframe::new(0.0, TestKeyframeData::new(Some(10), None), None),
580 Keyframe::new(0.5, TestKeyframeData::new(Some(15), None), None),
581 Keyframe::new(1.0, TestKeyframeData::new(Some(50), None), None),
582 ];
583 let mut timeline = TestTimeline::new(keyframes, Easing::default());
584
585 timeline.start_with(&TestValues::new(5, 8.5));
586
587 assert_eq!(timeline.values_at(0.0), TestValues::new(5, 0.0));
588 assert_eq!(timeline.values_at(0.25), TestValues::new(10, 0.0));
589 assert_eq!(timeline.values_at(0.5), TestValues::new(15, 0.0));
590 assert_eq!(timeline.values_at(1.0), TestValues::new(50, 0.0));
591 }
592
593 #[test]
594 fn when_start_override_disabled_then_interpolates_with_original_keyframe() {
595 let keyframes = vec![
596 Keyframe::new(0.0, TestKeyframeData::new(Some(10), None), None),
597 Keyframe::new(0.5, TestKeyframeData::new(Some(15), None), None),
598 Keyframe::new(1.0, TestKeyframeData::new(Some(50), None), None),
599 ];
600 let mut timeline = TestTimeline::new(keyframes, Easing::default());
601
602 timeline.start_with(&TestValues::new(5, 8.5));
603
604 assert_eq!(
605 timeline.non_overridden_values_at(0.0),
606 TestValues::new(10, 0.0)
607 );
608 assert_eq!(
609 timeline.non_overridden_values_at(0.25),
610 TestValues::new(12, 0.0)
611 );
612 assert_eq!(
613 timeline.non_overridden_values_at(0.5),
614 TestValues::new(15, 0.0)
615 );
616 assert_eq!(
617 timeline.non_overridden_values_at(1.0),
618 TestValues::new(50, 0.0)
619 );
620 }
621}