use crate::core::animation::base::{Animation, AudioEvent};
use crate::core::animation::AnyAnimation;
use std::time::Duration;
const INFINITE_DURATION_CAP: Duration = Duration::from_secs(3600);
pub struct LoopAnim {
pub(crate) factory: Box<dyn Fn() -> AnyAnimation + Send + Sync>,
pub(crate) current: Box<AnyAnimation>,
pub(crate) repeat_count: Option<usize>,
pub(crate) finished_count: usize,
}
impl LoopAnim {
pub fn new(factory: Box<dyn Fn() -> AnyAnimation + Send + Sync>, count: Option<usize>) -> Self {
let current = Box::new(factory());
Self {
factory,
current,
repeat_count: count,
finished_count: 0,
}
}
}
impl Animation for LoopAnim {
fn update(&mut self, mut dt: Duration) -> (bool, Duration) {
loop {
let (finished, leftover) = self.current.update(dt);
if !finished {
return (false, Duration::ZERO);
}
self.finished_count += 1;
if let Some(max) = self.repeat_count {
if self.finished_count >= max {
return (true, leftover);
}
}
self.current = Box::new((self.factory)());
dt = leftover;
if dt == Duration::ZERO {
return (false, Duration::ZERO);
}
}
}
fn duration(&self) -> Duration {
match self.repeat_count {
Some(count) => self.current.duration() * count as u32,
None => INFINITE_DURATION_CAP,
}
}
fn collect_audio_events(&mut self, current_time: Duration, events: &mut Vec<AudioEvent>) {
let loop_offset = self.current.duration() * self.finished_count as u32;
self.current
.collect_audio_events(current_time + loop_offset, events);
}
fn reset(&mut self) {
self.current = Box::new((self.factory)());
self.finished_count = 0;
}
}
pub fn loop_anim<F>(factory: F, count: Option<usize>) -> AnyAnimation
where
F: Fn() -> AnyAnimation + Send + Sync + 'static,
{
AnyAnimation::Loop(LoopAnim::new(Box::new(factory), count))
}