use super::*;
impl<T: Interpolable + Copy> Tween<T> {
pub fn get_from(&self) -> T {
self.from
}
pub fn get_to(&self) -> T {
self.to
}
pub fn get_easing(&self) -> Easing {
self.easing
}
pub fn get_delay(&self) -> f64 {
self.delay
}
pub fn get_elapsed(&self) -> f64 {
self.elapsed
}
pub fn get_elapsed_mut(&mut self) -> &mut f64 {
&mut self.elapsed
}
pub fn get_mode(&self) -> AnimationMode {
self.mode
}
pub fn get_direction(&self) -> f64 {
self.direction
}
pub fn try_get_on_complete(&self) -> &Option<Rc<dyn Fn()>> {
&self.on_complete
}
pub fn set_easing(&mut self, easing: Easing) {
self.easing = easing;
}
pub fn set_delay(&mut self, delay: f64) {
self.delay = delay;
}
pub fn set_elapsed(&mut self, elapsed: f64) {
self.elapsed = elapsed;
}
pub fn set_state(&mut self, state: TweenState) {
self.state = state;
}
pub fn set_mode(&mut self, mode: AnimationMode) {
self.mode = mode;
}
pub fn set_direction(&mut self, direction: f64) {
self.direction = direction;
}
pub fn set_on_complete(&mut self, on_complete: Option<Rc<dyn Fn()>>) {
self.on_complete = on_complete;
}
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.set_easing(easing);
self
}
pub fn with_delay(mut self, delay: f64) -> Tween<T> {
self.set_delay(delay.max(0.0));
if self.get_delay() > 0.0
&& self.get_state() == TweenState::Running
&& self.get_elapsed() == 0.0
{
self.set_state(TweenState::Delayed);
}
self
}
pub fn with_mode(mut self, mode: AnimationMode) -> Tween<T> {
self.set_mode(mode);
self
}
pub fn with_on_complete(mut self, on_complete: Rc<dyn Fn()>) -> Tween<T> {
self.set_on_complete(Some(on_complete));
self
}
pub fn update(&mut self, delta_time: f64) -> T {
if self.get_state() == TweenState::Paused || self.get_state() == TweenState::Finished {
return self.value();
}
*self.get_elapsed_mut() += delta_time.max(0.0);
if self.get_state() == TweenState::Delayed {
if self.get_elapsed() < self.get_delay() {
return self.get_from();
}
self.set_state(TweenState::Running);
}
let active_elapsed: f64 = self.get_elapsed() - self.get_delay();
if self.get_duration() <= 0.0 || active_elapsed >= self.get_duration() {
self.complete_cycle(active_elapsed);
}
self.value()
}
pub fn value(&self) -> T {
let progress: f64 = self.eased_progress();
if self.get_direction() == TWEEN_DIRECTION_BACKWARD {
return self.get_from().lerp(self.get_to(), 1.0 - progress);
}
self.get_from().lerp(self.get_to(), progress)
}
pub fn eased_progress(&self) -> f64 {
if self.get_duration() <= 0.0 {
return 1.0;
}
let active_elapsed: f64 = (self.get_elapsed() - self.get_delay()).max(0.0);
let raw: f64 = (active_elapsed / self.get_duration()).min(1.0);
self.get_easing().evaluate(raw)
}
pub fn raw_progress(&self) -> f64 {
if self.get_duration() <= 0.0 {
return 1.0;
}
((self.get_elapsed() - self.get_delay()).max(0.0) / self.get_duration()).min(1.0)
}
pub fn pause(&mut self) {
if self.get_state() == TweenState::Running || self.get_state() == TweenState::Delayed {
self.set_state(TweenState::Paused);
}
}
pub fn resume(&mut self) {
if self.get_state() == TweenState::Paused {
if self.get_elapsed() < self.get_delay() {
self.set_state(TweenState::Delayed);
} else {
self.set_state(TweenState::Running);
}
}
}
pub fn reset(&mut self) {
self.set_elapsed(0.0);
self.set_direction(TWEEN_DIRECTION_FORWARD);
self.set_state(if self.get_delay() > 0.0 {
TweenState::Delayed
} else {
TweenState::Running
});
}
pub fn is_finished(&self) -> bool {
self.get_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.get_duration() > 0.0 {
active_elapsed % self.get_duration()
} else {
0.0
};
match self.get_mode() {
AnimationMode::Once => {
self.set_elapsed(self.get_delay() + self.get_duration());
self.set_state(TweenState::Finished);
}
AnimationMode::Loop => {
self.set_elapsed(self.get_delay() + overflow);
}
AnimationMode::PingPong => {
self.set_elapsed(self.get_delay() + overflow);
self.set_direction(-self.get_direction());
}
}
if let Some(on_complete) = self.try_get_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);
}
}
impl<T: Interpolable + Copy> Clone for Tween<T> {
fn clone(&self) -> Tween<T> {
Tween {
from: self.get_from(),
to: self.get_to(),
duration: self.get_duration(),
easing: self.get_easing(),
delay: self.get_delay(),
elapsed: self.get_elapsed(),
state: self.get_state(),
mode: self.get_mode(),
direction: self.get_direction(),
on_complete: self.try_get_on_complete().clone(),
}
}
}
impl<T: Interpolable + Copy + Debug> Debug for Tween<T> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("Tween")
.field("from", &self.from)
.field("to", &self.to)
.field("duration", &self.duration)
.field("easing", &self.easing)
.field("delay", &self.delay)
.field("elapsed", &self.elapsed)
.field("state", &self.state)
.field("mode", &self.mode)
.field("direction", &self.direction)
.finish_non_exhaustive()
}
}