use super::{Animation, BaseAnimation};
use crate::core::DURATION_ZERO;
use std::time::Duration;
#[derive(Clone, Copy)]
pub enum SeekFrom {
Begin(Duration),
End(Duration),
Percent(f32),
}
#[derive(Debug, Clone)]
pub struct Seek<T: Animation> {
src: T,
progress: Duration,
}
impl<T: Animation> Seek<T> {
pub(super) fn new(src: T, seek: SeekFrom) -> Self {
let progress = match seek {
SeekFrom::Begin(progress) => progress,
SeekFrom::End(progress) => {
if let Some(duration) = src.duration() {
if duration > progress {
duration - progress
} else {
DURATION_ZERO
}
} else {
panic!("cannot seek from end for infinite animation");
}
}
SeekFrom::Percent(percent) => {
assert!((-1.0..=1.0).contains(&percent));
if let Some(duration) = src.duration() {
if percent < 0.0 {
duration.mul_f32(1.0 + percent)
} else {
duration.mul_f32(percent)
}
} else {
panic!("cannot seek by percent for infinite animation");
}
}
};
Self { src, progress }
}
}
impl<T: Animation> BaseAnimation for Seek<T> {
type Item = T::Item;
#[inline]
fn duration(&self) -> Option<Duration> {
self.src.duration().map(|d| {
if d > self.progress {
d - self.progress
} else {
DURATION_ZERO
}
})
}
#[inline]
fn animate(&self, elapsed: Duration) -> Self::Item {
let elapsed = self.progress + elapsed;
self.src.animate(elapsed)
}
}