use crate::{Animate, Once, TweenAnim, Tween, FRAME_TIME, IS_ANIMATING};
use std::sync::atomic::Ordering;
impl<T, E, I> Animate for Tween<T, E, I, Once>
where
T: TweenAnim + PartialEq + Default,
E: Fn(f64) -> f64,
I: Fn(&T, &T, f64) -> T,
{
type Value = T;
fn update(&mut self) {
if self.state.pending {
self.state.start = std::mem::take(&mut self.state.current);
self.state.pending = false;
}
if let Some(start_t) = self.state.started_at {
let now = FRAME_TIME.load(Ordering::Relaxed);
let elapsed = now.saturating_sub(start_t) as f64;
let t = (elapsed / self.state.duration).clamp(0.0, 1.0);
self.state.current =
(self.state.interp)(&self.state.start, &self.state.target, (self.state.easing)(t));
if t >= 1.0 {
self.state.started_at = None;
} else {
IS_ANIMATING.store(true, Ordering::Relaxed);
}
}
}
fn get(&self) -> &T {
&self.state.current
}
fn set(&mut self, target: T) {
let now = FRAME_TIME.load(Ordering::Relaxed);
self.state.target = target;
self.state.started_at = Some(now);
self.state.pending = true;
}
fn target(&self) -> &T {
if self.state.started_at.is_none() {
&self.state.current
} else {
&self.state.target
}
}
}