1use crate::{MessageData, Scalar, messenger::MessageSender, widget::WidgetId};
11use serde::{Deserialize, Serialize};
12use std::{collections::HashMap, sync::mpsc::Sender};
13
14pub enum AnimationError {
16 CouldNotReadData,
18 CouldNotWriteData,
20}
21
22#[derive(Clone)]
25pub(crate) struct AnimationUpdate(Sender<(String, Option<Animation>)>);
26
27impl AnimationUpdate {
28 pub fn new(sender: Sender<(String, Option<Animation>)>) -> Self {
29 Self(sender)
30 }
31
32 pub fn change(&self, name: &str, data: Option<Animation>) -> Result<(), AnimationError> {
33 if self.0.send((name.to_owned(), data)).is_err() {
34 Err(AnimationError::CouldNotWriteData)
35 } else {
36 Ok(())
37 }
38 }
39}
40
41pub struct Animator<'a> {
54 states: &'a AnimatorStates,
55 update: AnimationUpdate,
56}
57
58impl<'a> Animator<'a> {
59 #[inline]
61 pub(crate) fn new(states: &'a AnimatorStates, update: AnimationUpdate) -> Self {
62 Self { states, update }
63 }
64
65 #[inline]
67 pub fn has(&self, anim_id: &str) -> bool {
68 self.states.has(anim_id)
69 }
70
71 #[inline]
73 pub fn change(
74 &self,
75 anim_id: &str,
76 animation: Option<Animation>,
77 ) -> Result<(), AnimationError> {
78 self.update.change(anim_id, animation)
79 }
80
81 #[inline]
85 pub fn value_progress(&self, anim_id: &str, value_name: &str) -> Option<AnimatedValueProgress> {
86 self.states.value_progress(anim_id, value_name)
87 }
88
89 #[inline]
96 pub fn value_progress_factor(&self, anim_id: &str, value_name: &str) -> Option<Scalar> {
97 self.states
98 .value_progress(anim_id, value_name)
99 .map(|x| x.progress_factor)
100 }
101
102 #[inline]
104 pub fn value_progress_factor_or(
105 &self,
106 anim_id: &str,
107 value_name: &str,
108 default: Scalar,
109 ) -> Scalar {
110 self.value_progress_factor(anim_id, value_name)
111 .unwrap_or(default)
112 }
113
114 #[inline]
116 pub fn value_progress_factor_or_zero(&self, anim_id: &str, value_name: &str) -> Scalar {
117 self.value_progress_factor(anim_id, value_name)
118 .unwrap_or(0.)
119 }
120}
121
122#[derive(Debug, Default, Clone, Copy)]
124pub struct AnimatedValueProgress {
125 pub progress_factor: Scalar,
127 pub time: Scalar,
129 pub duration: Scalar,
131}
132
133#[derive(Debug, Default, Clone, Serialize, Deserialize)]
146pub struct AnimatorStates(
147 #[serde(default)]
148 #[serde(skip_serializing_if = "HashMap::is_empty")]
149 pub HashMap<String, AnimatorState>,
150);
151
152impl AnimatorStates {
153 pub(crate) fn new(anim_id: String, animation: Animation) -> Self {
155 let mut result = HashMap::with_capacity(1);
156 result.insert(anim_id, AnimatorState::new(animation));
157 Self(result)
158 }
159
160 pub fn in_progress(&self) -> bool {
162 self.0.values().any(|s| s.in_progress())
163 }
164
165 #[inline]
167 pub fn is_done(&self) -> bool {
168 !self.in_progress()
169 }
170
171 #[inline]
173 pub fn has(&self, anim_id: &str) -> bool {
174 self.0.contains_key(anim_id)
175 }
176
177 #[inline]
181 pub fn value_progress(&self, anim_id: &str, value_name: &str) -> Option<AnimatedValueProgress> {
182 if let Some(state) = self.0.get(anim_id) {
183 state.value_progress(value_name)
184 } else {
185 None
186 }
187 }
188
189 #[inline]
196 pub fn value_progress_factor(&self, anim_id: &str, value_name: &str) -> Option<Scalar> {
197 if let Some(state) = self.0.get(anim_id) {
198 state.value_progress_factor(value_name)
199 } else {
200 None
201 }
202 }
203
204 #[inline]
206 pub fn value_progress_factor_or(
207 &self,
208 anim_id: &str,
209 value_name: &str,
210 default: Scalar,
211 ) -> Scalar {
212 self.value_progress_factor(anim_id, value_name)
213 .unwrap_or(default)
214 }
215
216 #[inline]
218 pub fn value_progress_factor_or_zero(&self, anim_id: &str, value_name: &str) -> Scalar {
219 self.value_progress_factor(anim_id, value_name)
220 .unwrap_or(0.)
221 }
222
223 pub fn change(&mut self, anim_id: String, animation: Option<Animation>) {
227 if let Some(animation) = animation {
228 self.0.insert(anim_id, AnimatorState::new(animation));
229 } else {
230 self.0.remove(&anim_id);
231 }
232 }
233
234 pub(crate) fn process(
236 &mut self,
237 delta_time: Scalar,
238 owner: &WidgetId,
239 message_sender: &MessageSender,
240 ) {
241 for state in self.0.values_mut() {
242 state.process(delta_time, owner, message_sender);
243 }
244 }
245}
246
247#[derive(Debug, Default, Clone, Serialize, Deserialize)]
253pub struct AnimatorState {
254 #[serde(default)]
255 #[serde(skip_serializing_if = "HashMap::is_empty")]
256 sheet: HashMap<String, AnimationPhase>,
257 #[serde(default)]
258 #[serde(skip_serializing_if = "Vec::is_empty")]
259 messages: Vec<(Scalar, String)>,
260 #[serde(default)]
261 time: Scalar,
262 #[serde(default)]
263 duration: Scalar,
264 #[serde(default)]
265 looped: bool,
266}
267
268impl AnimatorState {
269 pub(crate) fn new(animation: Animation) -> Self {
271 let mut sheet = HashMap::new();
272 let mut messages = vec![];
273 let (time, looped) = Self::include_animation(animation, &mut sheet, &mut messages, 0.0);
274 Self {
275 sheet,
276 messages,
277 time: 0.0,
278 duration: time,
279 looped,
280 }
281 }
282
283 #[inline]
285 pub fn in_progress(&self) -> bool {
286 self.looped || (self.time <= self.duration && !self.sheet.is_empty())
287 }
288
289 #[inline]
291 pub fn is_done(&self) -> bool {
292 !self.in_progress()
293 }
294
295 #[inline]
299 pub fn value_progress(&self, name: &str) -> Option<AnimatedValueProgress> {
300 self.sheet.get(name).map(|p| AnimatedValueProgress {
301 progress_factor: p.cached_progress,
302 time: p.cached_time,
303 duration: p.duration,
304 })
305 }
306
307 #[inline]
314 pub fn value_progress_factor(&self, name: &str) -> Option<Scalar> {
315 self.sheet.get(name).map(|p| p.cached_progress)
316 }
317
318 #[inline]
320 pub fn value_progress_factor_or(&self, name: &str, default: Scalar) -> Scalar {
321 self.value_progress_factor(name).unwrap_or(default)
322 }
323
324 #[inline]
326 pub fn value_progress_factor_or_zero(&self, name: &str) -> Scalar {
327 self.value_progress_factor(name).unwrap_or(0.)
328 }
329
330 pub(crate) fn process(
332 &mut self,
333 delta_time: Scalar,
334 owner: &WidgetId,
335 message_sender: &MessageSender,
336 ) {
337 if delta_time > 0.0 {
338 if self.looped && self.time > self.duration {
339 self.time = 0.0;
340 }
341 let old_time = self.time;
342 self.time += delta_time;
343 for phase in self.sheet.values_mut() {
344 phase.cached_time = (self.time - phase.start).min(phase.duration).max(0.0);
345 phase.cached_progress = if phase.duration > 0.0 {
346 phase.cached_time / phase.duration
347 } else {
348 0.0
349 };
350 }
351 for (time, message) in &self.messages {
352 if *time >= old_time && *time < self.time {
353 message_sender.write(owner.to_owned(), AnimationMessage(message.to_owned()));
354 }
355 }
356 }
357 }
358
359 fn include_animation(
361 animation: Animation,
362 sheet: &mut HashMap<String, AnimationPhase>,
363 messages: &mut Vec<(Scalar, String)>,
364 mut time: Scalar,
365 ) -> (Scalar, bool) {
366 match animation {
367 Animation::Value(value) => {
368 let duration = value.duration.max(0.0);
369 let phase = AnimationPhase {
370 start: time,
371 duration,
372 cached_time: 0.0,
373 cached_progress: 0.0,
374 };
375 sheet.insert(value.name, phase);
376 (time + duration, false)
377 }
378 Animation::Sequence(anims) => {
379 for anim in anims {
380 time = Self::include_animation(anim, sheet, messages, time).0;
381 }
382 (time, false)
383 }
384 Animation::Parallel(anims) => {
385 let mut result = time;
386 for anim in anims {
387 result = Self::include_animation(anim, sheet, messages, time)
388 .0
389 .max(result);
390 }
391 (result, false)
392 }
393 Animation::Looped(anim) => {
394 let looped = sheet.is_empty();
395 time = Self::include_animation(*anim, sheet, messages, time).0;
396 (time, looped)
397 }
398 Animation::TimeShift(v) => ((time - v).max(0.0), false),
399 Animation::Message(message) => {
400 messages.push((time, message));
401 (time, false)
402 }
403 }
404 }
405}
406
407#[derive(Debug, Default, Clone, Serialize, Deserialize)]
408struct AnimationPhase {
409 #[serde(default)]
410 pub start: Scalar,
411 #[serde(default)]
412 pub duration: Scalar,
413 #[serde(default)]
414 pub cached_time: Scalar,
415 #[serde(default)]
416 pub cached_progress: Scalar,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
428pub enum Animation {
429 Value(AnimatedValue),
431 Sequence(Vec<Animation>),
433 Parallel(Vec<Animation>),
435 Looped(Box<Animation>),
437 TimeShift(Scalar),
439 Message(String),
441}
442
443impl Default for Animation {
444 fn default() -> Self {
445 Self::TimeShift(0.0)
446 }
447}
448
449#[derive(Debug, Default, Clone, Serialize, Deserialize)]
451pub struct AnimatedValue {
452 #[serde(default)]
457 pub name: String,
458 #[serde(default)]
460 pub duration: Scalar,
461}
462
463#[derive(MessageData, Debug, Default, Clone)]
466#[message_data(crate::messenger::MessageData)]
467pub struct AnimationMessage(pub String);
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472 use std::{str::FromStr, sync::mpsc::channel};
473
474 #[test]
475 fn test_animator() {
476 let animation = Animation::Sequence(vec![
477 Animation::Value(AnimatedValue {
478 name: "fade-in".to_owned(),
479 duration: 0.2,
480 }),
481 Animation::Value(AnimatedValue {
482 name: "delay".to_owned(),
483 duration: 0.6,
484 }),
485 Animation::Value(AnimatedValue {
486 name: "fade-out".to_owned(),
487 duration: 0.2,
488 }),
489 Animation::Message("next".to_owned()),
490 ]);
491 println!("Animation: {animation:#?}");
492 let mut states = AnimatorStates::new("".to_owned(), animation);
493 println!("States 0: {states:#?}");
494 let id = WidgetId::from_str("type:/widget").unwrap();
495 let (sender, receiver) = channel();
496 let sender = MessageSender::new(sender);
497 states.process(0.5, &id, &sender);
498 println!("States 1: {states:#?}");
499 states.process(0.6, &id, &sender);
500 println!("States 2: {states:#?}");
501 println!(
502 "Message: {:#?}",
503 receiver
504 .try_recv()
505 .unwrap()
506 .1
507 .as_any()
508 .downcast_ref::<AnimationMessage>()
509 .unwrap()
510 );
511 }
512}