animato_timeline/
group.rs1use crate::{At, Sequence, Timeline};
4use alloc::format;
5use alloc::vec::Vec;
6use animato_core::{Playable, Update};
7use animato_tween::StaggerPattern;
8use core::fmt;
9
10pub struct AnimationGroup {
12 inner: Timeline,
13}
14
15impl fmt::Debug for AnimationGroup {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 f.debug_struct("AnimationGroup")
18 .field("inner", &self.inner)
19 .finish()
20 }
21}
22
23impl AnimationGroup {
24 pub fn from_timeline(timeline: Timeline) -> Self {
26 Self { inner: timeline }
27 }
28
29 pub fn parallel<A>(animations: Vec<A>) -> Self
31 where
32 A: Playable + Send + 'static,
33 {
34 let mut timeline = Timeline::new();
35 for (index, animation) in animations.into_iter().enumerate() {
36 timeline = timeline.add(format!("item_{index}"), animation, At::Start);
37 }
38 Self::from_timeline(timeline)
39 }
40
41 pub fn sequence<A>(animations: Vec<A>) -> Self
43 where
44 A: Playable + Send + 'static,
45 {
46 let mut sequence = Sequence::new();
47 for (index, animation) in animations.into_iter().enumerate() {
48 sequence = sequence.then(format!("item_{index}"), animation);
49 }
50 Self::from_timeline(sequence.build())
51 }
52
53 pub fn stagger<A>(animations: Vec<A>, pattern: StaggerPattern) -> Self
55 where
56 A: Playable + Send + 'static,
57 {
58 let total = animations.len();
59 let mut timeline = Timeline::new();
60 for (index, animation) in animations.into_iter().enumerate() {
61 timeline = timeline.add(
62 format!("item_{index}"),
63 animation,
64 At::Absolute(pattern.delay(index, total)),
65 );
66 }
67 Self::from_timeline(timeline)
68 }
69
70 pub fn timeline(&self) -> &Timeline {
72 &self.inner
73 }
74
75 pub fn timeline_mut(&mut self) -> &mut Timeline {
77 &mut self.inner
78 }
79
80 pub fn play(&mut self) {
82 self.inner.play();
83 }
84
85 pub fn pause(&mut self) {
87 self.inner.pause();
88 }
89
90 pub fn resume(&mut self) {
92 self.inner.resume();
93 }
94
95 pub fn reset(&mut self) {
97 self.inner.reset();
98 }
99
100 pub fn seek(&mut self, progress: f32) {
102 self.inner.seek(progress);
103 }
104
105 pub fn reverse(&mut self) {
107 let progress = self.inner.progress();
108 self.inner.seek(1.0 - progress);
109 }
110
111 pub fn set_time_scale(&mut self, scale: f32) {
113 self.inner.set_time_scale(scale);
114 }
115
116 pub fn duration(&self) -> f32 {
118 self.inner.duration()
119 }
120
121 pub fn progress(&self) -> f32 {
123 self.inner.progress()
124 }
125
126 pub fn is_complete(&self) -> bool {
128 self.inner.is_complete()
129 }
130
131 #[cfg(feature = "std")]
133 pub fn on_complete(mut self, f: impl FnMut() + Send + 'static) -> Self {
134 self.inner = self.inner.on_complete(f);
135 self
136 }
137}
138
139impl Update for AnimationGroup {
140 fn update(&mut self, dt: f32) -> bool {
141 self.inner.update(dt)
142 }
143}
144
145impl Playable for AnimationGroup {
146 fn duration(&self) -> f32 {
147 self.inner.duration()
148 }
149
150 fn reset(&mut self) {
151 AnimationGroup::reset(self);
152 }
153
154 fn seek_to(&mut self, progress: f32) {
155 self.seek(progress);
156 }
157
158 fn is_complete(&self) -> bool {
159 AnimationGroup::is_complete(self)
160 }
161
162 fn as_any(&self) -> &dyn core::any::Any {
163 self
164 }
165
166 fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
167 self
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use animato_tween::Tween;
175
176 #[test]
177 fn parallel_completes_when_last_child_finishes() {
178 let mut group = AnimationGroup::parallel(alloc::vec![
179 Tween::new(0.0_f32, 1.0).duration(0.5).build(),
180 Tween::new(0.0_f32, 1.0).duration(1.0).build(),
181 ]);
182 group.play();
183 assert!(group.update(0.75));
184 assert!(!group.update(0.25));
185 }
186
187 #[test]
188 fn sequence_orders_children() {
189 let mut group = AnimationGroup::sequence(alloc::vec![
190 Tween::new(0.0_f32, 10.0).duration(1.0).build(),
191 Tween::new(0.0_f32, 20.0).duration(1.0).build(),
192 ]);
193 group.play();
194 group.update(1.5);
195 assert_eq!(
196 group
197 .timeline()
198 .get::<Tween<f32>>("item_0")
199 .expect("first")
200 .value(),
201 10.0
202 );
203 assert_eq!(
204 group
205 .timeline()
206 .get::<Tween<f32>>("item_1")
207 .expect("second")
208 .value(),
209 10.0
210 );
211 }
212}