tween/tweener/
looper.rs

1use crate::{Tween, TweenValue};
2
3/// A [Looper] is a wrapper around a [Tween], which makes it so that
4/// every time the tweener *would* fuse (end), it loops from the start.
5#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
6#[repr(transparent)]
7pub struct Looper<T: ?Sized>(pub T);
8
9impl<T> Looper<T> {
10    /// Creates a new Looper around a [Tween].
11    pub fn new(tween: T) -> Self {
12        Self(tween)
13    }
14}
15
16impl<Value, T> Tween<Value> for Looper<T>
17where
18    Value: TweenValue,
19    T: Tween<Value>,
20{
21    #[inline(always)]
22    fn tween(&mut self, value_delta: Value, mut percent: f32) -> Value {
23        if percent == 0.0 {
24            return self.0.tween(value_delta, percent);
25        }
26
27        percent %= 1.0;
28        if percent == 0.0 {
29            percent = 1.0
30        }
31
32        // pass through to the underlying tween
33        self.0.tween(value_delta, percent)
34    }
35
36    fn is_finite(&self) -> bool {
37        false
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use crate::{FixedTweener, Linear, Tweener};
44
45    use super::*;
46
47    #[test]
48    fn tweener_loop() {
49        let mut looper = Tweener::new(0, 2, 2, Looper::new(Linear));
50
51        assert_eq!(looper.move_to(0), 0);
52        assert_eq!(looper.move_to(1), 1);
53        assert_eq!(looper.move_to(2), 2);
54        assert_eq!(looper.move_to(3), 1);
55        assert_eq!(looper.move_to(4), 2);
56        assert_eq!(looper.move_to(5), 1);
57        assert_eq!(looper.move_to(6), 2);
58    }
59
60    #[test]
61    fn delta_tweener_loop() {
62        let mut looper = Tweener::new(0, 2, 2, Looper::new(Linear));
63
64        assert_eq!(looper.move_by(1), 1);
65        assert_eq!(looper.move_by(1), 2);
66        assert_eq!(looper.move_by(1), 1);
67        assert_eq!(looper.move_by(1), 2);
68        assert_eq!(looper.move_by(1), 1);
69        assert_eq!(looper.move_by(1), 2);
70    }
71
72    #[test]
73    fn fixed_delta_tweener_loop() {
74        let mut looper = FixedTweener::new(0, 2, 2, Looper::new(Linear), 1);
75
76        assert_eq!(looper.next().unwrap(), 1);
77        assert_eq!(looper.next().unwrap(), 2);
78        assert_eq!(looper.next().unwrap(), 1);
79        assert_eq!(looper.next().unwrap(), 2);
80        assert_eq!(looper.next().unwrap(), 1);
81        assert_eq!(looper.next().unwrap(), 2);
82    }
83
84    #[test]
85    fn tweener_loop_frac() {
86        let mut looper = Tweener::new(0, 2, 0.5, Looper::new(Linear));
87
88        assert_eq!(looper.move_by(0.25), 1);
89        assert_eq!(looper.move_by(0.25), 2);
90        assert_eq!(looper.move_by(0.25), 1);
91        assert_eq!(looper.move_by(0.25), 2);
92        assert_eq!(looper.move_by(0.25), 1);
93    }
94
95    #[test]
96    fn tweener_big_loop() {
97        let mut looper = Tweener::new(0, 2, 2, Looper::new(Linear));
98
99        assert_eq!(looper.move_by(3), 1);
100        assert_eq!(looper.move_by(4), 1);
101        assert_eq!(looper.move_by(4), 1);
102        assert_eq!(looper.move_by(5), 2);
103    }
104
105    #[test]
106    fn type_test() {
107        let mut _looper: FixedTweener<i32, i32, Looper<Linear>> = FixedTweener::new(0, 2, 2, Looper::new(Linear), 2);
108    }
109}