use super::*;
impl<T: Interpolable + Copy> Tween<T> {
pub fn create(from: T, to: T, duration: f64) -> Tween<T> {
Tween {
from,
to,
duration: duration.max(0.0),
easing: Easing::Linear,
delay: 0.0,
elapsed: 0.0,
state: TweenState::Running,
mode: AnimationMode::Once,
direction: TWEEN_DIRECTION_FORWARD,
on_complete: None,
}
}
pub fn with_easing(mut self, easing: Easing) -> Tween<T> {
self.easing = easing;
self
}
pub fn with_delay(mut self, delay: f64) -> Tween<T> {
self.delay = delay.max(0.0);
if self.delay > 0.0 && self.state == TweenState::Running && self.elapsed == 0.0 {
self.state = TweenState::Delayed;
}
self
}
pub fn with_mode(mut self, mode: AnimationMode) -> Tween<T> {
self.mode = mode;
self
}
pub fn with_on_complete(mut self, on_complete: Rc<dyn Fn()>) -> Tween<T> {
self.on_complete = Some(on_complete);
self
}
pub fn update(&mut self, delta_time: f64) -> T {
if self.state == TweenState::Paused || self.state == TweenState::Finished {
return self.value();
}
self.elapsed += delta_time.max(0.0);
if self.state == TweenState::Delayed {
if self.elapsed < self.delay {
return self.from;
}
self.state = TweenState::Running;
}
let active_elapsed: f64 = self.elapsed - self.delay;
if self.duration <= 0.0 || active_elapsed >= self.duration {
self.complete_cycle(active_elapsed);
}
self.value()
}
pub fn value(&self) -> T {
let progress: f64 = self.eased_progress();
if self.direction == TWEEN_DIRECTION_BACKWARD {
return self.from.lerp(self.to, 1.0 - progress);
}
self.from.lerp(self.to, progress)
}
pub fn eased_progress(&self) -> f64 {
if self.duration <= 0.0 {
return 1.0;
}
let active_elapsed: f64 = (self.elapsed - self.delay).max(0.0);
let raw: f64 = (active_elapsed / self.duration).min(1.0);
self.easing.evaluate(raw)
}
pub fn raw_progress(&self) -> f64 {
if self.duration <= 0.0 {
return 1.0;
}
((self.elapsed - self.delay).max(0.0) / self.duration).min(1.0)
}
pub fn pause(&mut self) {
if self.state == TweenState::Running || self.state == TweenState::Delayed {
self.state = TweenState::Paused;
}
}
pub fn resume(&mut self) {
if self.state == TweenState::Paused {
if self.elapsed < self.delay {
self.state = TweenState::Delayed;
} else {
self.state = TweenState::Running;
}
}
}
pub fn reset(&mut self) {
self.elapsed = 0.0;
self.direction = TWEEN_DIRECTION_FORWARD;
self.state = if self.delay > 0.0 {
TweenState::Delayed
} else {
TweenState::Running
};
}
pub fn is_finished(&self) -> bool {
self.state == TweenState::Finished
}
pub fn get_state(&self) -> TweenState {
self.state
}
pub fn get_duration(&self) -> f64 {
self.duration
}
fn complete_cycle(&mut self, active_elapsed: f64) {
let overflow: f64 = if self.duration > 0.0 {
active_elapsed % self.duration
} else {
0.0
};
match self.mode {
AnimationMode::Once => {
self.elapsed = self.delay + self.duration;
self.state = TweenState::Finished;
}
AnimationMode::Loop => {
self.elapsed = self.delay + overflow;
}
AnimationMode::PingPong => {
self.elapsed = self.delay + overflow;
self.direction = -self.direction;
}
}
if let Some(on_complete) = &self.on_complete {
on_complete();
}
}
}
impl<T: Interpolable + Copy> Updatable for Tween<T> {
fn update(&mut self, delta_time: f64) {
let _: T = Tween::update(self, delta_time);
}
}