use super::BaseAnimation;
use crate::{
core::{Animatable, Options, RepeatBehavior},
DURATION_ZERO,
};
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct Primitive<T: Animatable> {
opt: Options<T>,
duration: Option<Duration>,
}
impl<T: Animatable> Primitive<T> {
#[inline]
pub(crate) fn new(opt: Options<T>) -> Self {
let duration = {
if opt.duration == DURATION_ZERO {
Some(DURATION_ZERO)
} else {
match opt.repeat {
RepeatBehavior::Count(count) => Some(if count > 0.0 {
opt.duration.mul_f32(count)
} else {
DURATION_ZERO
}),
RepeatBehavior::Forever => None,
}
}
};
Self { opt, duration }
}
}
impl<T: Animatable> BaseAnimation for Primitive<T> {
type Item = T;
#[inline]
fn duration(&self) -> Option<Duration> {
if let Some(mut duration) = self.duration {
if let Some(delay) = self.opt.delay {
duration += delay;
}
if let Some(skip) = self.opt.skip {
if duration > skip {
duration -= skip
} else {
duration = DURATION_ZERO;
}
}
Some(duration)
} else {
None
}
}
#[inline]
fn animate(&self, mut elapsed: Duration) -> Self::Item {
if let Some(skip) = self.opt.skip {
elapsed += skip;
}
if let Some(delay) = self.opt.delay {
if elapsed > delay {
elapsed -= delay;
} else {
elapsed = DURATION_ZERO;
}
}
if let Some(duration) = self.duration {
if duration == DURATION_ZERO {
return self.opt.from.clone();
}
if elapsed > duration {
elapsed = duration;
}
}
let time = elapsed.as_secs_f64() / self.opt.duration.as_secs_f64();
let count = time.floor();
let mut time = time - count;
if count > 0.0 && time == 0.0 {
time = 1.0;
}
time = self.opt.easing.ease(time);
if self.opt.auto_reverse {
if time > 0.5 {
self.opt.to.animate(&self.opt.from, time * 2.0 - 1.0)
} else {
self.opt.from.animate(&self.opt.to, time * 2.0)
}
} else {
self.opt.from.animate(&self.opt.to, time)
}
}
}