1use std::any::Any;
2
3use crate::{
4 Extract,
5 animation::{AnimationCell, CoreItemAnimation, Eval, Static},
6 core_item::{AnyExtractCoreItem, CoreItem, DynItem},
7};
8
9#[derive(Default)]
12pub struct Timeline {
13 anims: Vec<Box<dyn CoreItemAnimation>>,
14 cur_sec: f64,
16 planning_static_start_sec: Option<f64>,
19}
20impl Timeline {
23 pub fn new() -> Self {
25 Self::default()
26 }
27 pub fn show(&mut self) -> &mut Self {
31 if self.planning_static_start_sec.is_none() {
32 self.planning_static_start_sec = Some(self.cur_sec)
33 }
34 self
35 }
36 pub fn hide(&mut self) -> &mut Self {
40 self._submit_planning_static_anim();
42 self
43 }
44 pub fn forward(&mut self, secs: f64) -> &mut Self {
46 self.cur_sec += secs;
47 self
48 }
49 pub fn forward_to(&mut self, target_sec: f64) -> &mut Self {
51 if target_sec > self.cur_sec {
52 self.forward(target_sec - self.cur_sec);
53 }
54 self
55 }
56 fn _submit_planning_static_anim(&mut self) -> bool {
57 if let (Some(start), Some(last_anim)) =
59 (self.planning_static_start_sec.take(), self.anims.last())
60 {
61 let state = last_anim.eval_alpha_dyn(1.0);
62 self.anims.push(Box::new(
63 Static(state)
64 .into_animation_cell()
65 .at(start)
66 .with_duration(self.cur_sec - start)
67 .with_enabled(last_anim.anim_info().enabled),
68 ));
69 return true;
70 }
71 false
72 }
73 pub fn play<T: AnyExtractCoreItem>(&mut self, anim: AnimationCell<T>) -> &mut Self {
79 self._submit_planning_static_anim();
80 let duration = anim.info.duration_secs;
82 self.anims
83 .push(Box::new(anim.at(self.cur_sec).with_duration(duration)));
84 self.cur_sec += duration;
85 self.show();
87 self
88 }
89 pub fn eval_at_alpha(&self, alpha: f64) -> Option<(usize, DynItem)> {
91 let (Some(start), Some(end)) = (self.start_sec(), self.end_sec()) else {
92 return None;
93 };
94 self.eval_at_sec(alpha * (end - start) + start)
95 }
96 pub fn eval_at_sec(&self, target_sec: f64) -> Option<(usize, DynItem)> {
98 let (Some(start), Some(end)) = (self.start_sec(), self.end_sec()) else {
99 return None;
100 };
101
102 if !(start..=end).contains(&target_sec) {
103 return None;
104 }
105
106 self.anims
107 .iter()
108 .enumerate()
109 .filter(|(_, a)| a.anim_info().enabled)
110 .find_map(|(idx, anim)| {
111 let range = anim.anim_info().range();
113 if range.contains(&target_sec)
115 || (idx == self.anims.len() - 1 && target_sec == range.end)
116 {
117 anim.eval_global_sec_dyn(target_sec)
118 .map(|dyn_item| (idx, dyn_item))
119 } else {
120 None
121 }
122 })
123 }
124}
125
126impl TimelineFunc for Timeline {
127 fn start_sec(&self) -> Option<f64> {
128 self.anims.first().map(|a| a.anim_info().range().start)
129 }
130 fn end_sec(&self) -> Option<f64> {
131 self.anims.last().map(|a| a.anim_info().range().end)
132 }
133 fn seal(&mut self) {
134 self._submit_planning_static_anim();
135 }
136 fn cur_sec(&self) -> f64 {
137 self.cur_sec
138 }
139 fn forward(&mut self, duration_secs: f64) {
140 self.cur_sec += duration_secs;
141 }
142 fn show(&mut self) {
143 self.show();
144 }
145 fn hide(&mut self) {
146 self.hide();
147 }
148 fn get_animation_infos(&self) -> Vec<AnimationInfo> {
149 self.anims
150 .iter()
151 .map(|a| AnimationInfo {
152 anim_name: a.anim_name().to_string(),
153 range: a.anim_info().range(),
154 })
155 .collect()
156 }
157 fn type_name(&self) -> &str {
158 ""
159 }
161 fn eval_primitives_at_sec(&self, target_sec: f64) -> Option<(usize, Vec<CoreItem>)> {
162 self.eval_at_sec(target_sec).map(|(idx, dyn_item)| {
163 let mut items = Vec::new();
164 dyn_item.extract_into(&mut items);
165 (idx, items)
166 })
167 }
168}
169
170pub trait TimelineFunc: Any {
173 fn start_sec(&self) -> Option<f64>;
175 fn end_sec(&self) -> Option<f64>;
177 fn range_sec(&self) -> Option<std::ops::Range<f64>> {
179 let (Some(start), Some(end)) = (self.start_sec(), self.end_sec()) else {
180 return None;
181 };
182 Some(start..end)
183 }
184 fn seal(&mut self);
186 fn cur_sec(&self) -> f64;
188 fn forward(&mut self, secs: f64);
190 fn forward_to(&mut self, target_sec: f64) {
192 let duration = target_sec - self.cur_sec();
193 if duration > 0.0 {
194 self.forward(duration);
195 }
196 }
197 fn show(&mut self);
199 fn hide(&mut self);
201 fn get_animation_infos(&self) -> Vec<AnimationInfo>;
203 fn type_name(&self) -> &str;
205
206 fn eval_primitives_at_sec(&self, target_sec: f64) -> Option<(usize, Vec<CoreItem>)>;
209}
210
211pub trait TimelinesFunc {
214 fn seal(&mut self);
216 fn max_total_secs(&self) -> f64;
218 fn sync(&mut self);
220 fn forward(&mut self, secs: f64);
222 fn forward_to(&mut self, target_sec: f64);
224}
225
226impl<I: ?Sized, T: TimelineFunc> TimelinesFunc for I
227where
228 for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
229 for<'a> &'a I: IntoIterator<Item = &'a T>,
230{
231 fn seal(&mut self) {
232 self.into_iter().for_each(|timeline: &mut T| {
233 timeline.seal();
234 });
235 }
236 fn max_total_secs(&self) -> f64 {
237 self.into_iter()
238 .map(|timeline: &T| timeline.cur_sec())
239 .max_by(|a, b| a.partial_cmp(b).unwrap())
240 .unwrap()
241 }
242 fn sync(&mut self) {
243 let max_elapsed_secs = self.max_total_secs();
244 self.into_iter().for_each(|timeline: &mut T| {
245 timeline.forward_to(max_elapsed_secs);
246 });
247 }
248 fn forward(&mut self, secs: f64) {
249 self.into_iter()
250 .for_each(|timeline: &mut T| timeline.forward(secs));
251 }
252 fn forward_to(&mut self, target_sec: f64) {
253 self.into_iter().for_each(|timeline: &mut T| {
254 timeline.forward_to(target_sec);
255 });
256 }
257}
258
259pub struct AnimationInfo {
261 pub anim_name: String,
263 pub range: std::ops::Range<f64>,
265}