1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum Repeat {
8 #[default]
10 None,
11 Count(u32),
14 Infinite,
16}
17
18impl Repeat {
19 pub fn is_repeating(&self) -> bool {
21 !matches!(self, Self::None)
22 }
23
24 pub fn is_infinite(&self) -> bool {
26 matches!(self, Self::Infinite)
27 }
28
29 pub fn count(&self) -> Option<u32> {
31 match self {
32 Self::None => Some(0),
33 Self::Count(n) => Some(*n),
34 Self::Infinite => None,
35 }
36 }
37
38 pub fn can_repeat(&self, current_iteration: u32) -> bool {
40 match self {
41 Self::None => false,
42 Self::Count(n) => current_iteration < *n,
43 Self::Infinite => true,
44 }
45 }
46}
47
48impl From<u32> for Repeat {
49 fn from(count: u32) -> Self {
50 if count == 0 {
51 Self::None
52 } else {
53 Self::Count(count)
54 }
55 }
56}
57
58impl From<i32> for Repeat {
59 fn from(count: i32) -> Self {
60 if count < 0 {
61 Self::Infinite
62 } else if count == 0 {
63 Self::None
64 } else {
65 Self::Count(count as u32)
66 }
67 }
68}
69
70#[derive(Debug, Clone, Copy, Default)]
72pub struct RepeatConfig {
73 pub repeat: Repeat,
75 pub yoyo: bool,
77 pub delay: f32,
79}
80
81impl RepeatConfig {
82 pub fn none() -> Self {
84 Self::default()
85 }
86
87 pub fn count(n: u32) -> Self {
89 Self {
90 repeat: Repeat::Count(n),
91 yoyo: false,
92 delay: 0.0,
93 }
94 }
95
96 pub fn infinite() -> Self {
98 Self {
99 repeat: Repeat::Infinite,
100 yoyo: false,
101 delay: 0.0,
102 }
103 }
104
105 pub fn with_yoyo(mut self, yoyo: bool) -> Self {
107 self.yoyo = yoyo;
108 self
109 }
110
111 pub fn with_delay(mut self, delay: f32) -> Self {
113 self.delay = delay;
114 self
115 }
116
117 pub fn is_repeating(&self) -> bool {
119 self.repeat.is_repeating()
120 }
121
122 pub fn should_reverse(&self, iteration: u32) -> bool {
126 self.yoyo && iteration % 2 == 1
127 }
128
129 pub fn total_duration(&self, single_duration: f32) -> Option<f32> {
133 match self.repeat {
134 Repeat::None => Some(single_duration),
135 Repeat::Count(n) => {
136 let repeat_duration = single_duration + self.delay;
137
138 Some(single_duration + repeat_duration * n as f32)
139 }
140 Repeat::Infinite => None,
141 }
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_repeat_can_repeat() {
151 assert!(!Repeat::None.can_repeat(0));
152 assert!(Repeat::Count(3).can_repeat(0));
153 assert!(Repeat::Count(3).can_repeat(2));
154 assert!(!Repeat::Count(3).can_repeat(3));
155 assert!(Repeat::Infinite.can_repeat(1000));
156 }
157
158 #[test]
159 fn test_repeat_from_i32() {
160 assert_eq!(Repeat::from(-1), Repeat::Infinite);
161 assert_eq!(Repeat::from(0), Repeat::None);
162 assert_eq!(Repeat::from(5), Repeat::Count(5));
163 }
164
165 #[test]
166 fn test_yoyo_direction() {
167 let config = RepeatConfig::count(3).with_yoyo(true);
168
169 assert!(!config.should_reverse(0)); assert!(config.should_reverse(1)); assert!(!config.should_reverse(2)); assert!(config.should_reverse(3)); }
174
175 #[test]
176 fn test_total_duration() {
177 let config = RepeatConfig::count(2).with_delay(0.5);
178
179 assert_eq!(config.total_duration(1.0), Some(4.0));
181 }
182
183 #[test]
184 fn test_infinite_duration() {
185 let config = RepeatConfig::infinite();
186
187 assert_eq!(config.total_duration(1.0), None);
188 }
189}