#![deny(
warnings,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_import_braces,
unused_qualifications,
missing_docs
)]
use std::time::Duration;
#[cfg(feature = "ease_handle")]
use rand::Rng;
use bevy::prelude::*;
pub use interpolation::EaseFunction;
pub use interpolation::Lerp;
mod plugin;
pub use plugin::{custom_ease_system, EasingsPlugin};
mod implemented;
#[derive(Debug)]
pub struct EaseValue<T>(pub T);
#[derive(Clone, Copy)]
pub enum EasingType {
Once {
duration: Duration,
},
Loop {
duration: Duration,
pause: Duration,
},
PingPong {
duration: Duration,
pause: Duration,
},
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum EasingState {
Play,
Paused,
}
impl std::ops::Not for EasingState {
type Output = EasingState;
fn not(self) -> Self::Output {
match self {
EasingState::Paused => EasingState::Play,
EasingState::Play => EasingState::Paused,
}
}
}
pub struct EasingComponent<T> {
start: Option<EaseValue<T>>,
end: EaseValue<T>,
ease_function: EaseFunction,
timer: Timer,
pub state: EasingState,
paused: bool,
easing_type: EasingType,
#[cfg(feature = "ease_handle")]
id: i128,
direction: i16,
}
impl<T: Default> EasingComponent<T> {
pub fn ease_to(
self,
end: T,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingChainComponent<T> {
#[cfg(feature = "ease_handle")]
let mut rng = rand::thread_rng();
let next = EasingComponent {
start: None,
end: EaseValue(end),
ease_function,
timer: match easing_type {
EasingType::Once { duration } => Timer::new(duration, false),
EasingType::Loop { duration, .. } => Timer::new(duration, false),
EasingType::PingPong { duration, .. } => Timer::new(duration, false),
},
state: EasingState::Play,
paused: false,
easing_type,
#[cfg(feature = "ease_handle")]
id: rng.gen(),
direction: 1,
};
EasingChainComponent(vec![next, self])
}
}
pub struct EasingChainComponent<T>(Vec<EasingComponent<T>>);
impl<T: Default> EasingChainComponent<T> {
pub fn ease_to(
mut self,
end: T,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingChainComponent<T> {
#[cfg(feature = "ease_handle")]
let mut rng = rand::thread_rng();
let next = EasingComponent {
start: None,
end: EaseValue(end),
ease_function,
timer: match easing_type {
EasingType::Once { duration } => Timer::new(duration, false),
EasingType::Loop { duration, .. } => Timer::new(duration, false),
EasingType::PingPong { duration, .. } => Timer::new(duration, false),
},
state: EasingState::Play,
paused: false,
easing_type,
#[cfg(feature = "ease_handle")]
id: rng.gen(),
direction: 1,
};
self.0.insert(0, next);
self
}
}
pub trait Ease: Sized {
fn ease(
start: Option<Self>,
end: Self,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingComponent<Self> {
#[cfg(feature = "ease_handle")]
let mut rng = rand::thread_rng();
EasingComponent {
start: start.map(EaseValue),
end: EaseValue(end),
ease_function,
timer: match easing_type {
EasingType::Once { duration } => Timer::new(duration, false),
EasingType::Loop { duration, .. } => Timer::new(duration, false),
EasingType::PingPong { duration, .. } => Timer::new(duration, false),
},
state: EasingState::Play,
paused: false,
easing_type,
#[cfg(feature = "ease_handle")]
id: rng.gen(),
direction: 1,
}
}
fn ease_to(
self,
target: Self,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingComponent<Self> {
Self::ease(Some(self), target, ease_function, easing_type)
}
}
impl<T> Ease for EaseValue<T> where T: Lerp<Scalar = f32> {}
impl<T> Ease for Handle<T> where EaseValue<T>: Lerp<Scalar = f32> {}
impl<T> Ease for T where EaseValue<T>: Lerp<Scalar = f32> {}
impl<T> Default for EaseValue<T>
where
T: Default,
{
fn default() -> Self {
EaseValue(T::default())
}
}
trait IntermediateLerp: Sized {
fn lerp(start: &EaseValue<&Self>, end: &EaseValue<&Self>, scalar: &f32) -> Self;
}
pub trait CustomComponentEase: Sized {
fn ease(
start: Option<Self>,
end: Self,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingComponent<Self> {
#[cfg(feature = "ease_handle")]
let mut rng = rand::thread_rng();
EasingComponent {
start: start.map(EaseValue),
end: EaseValue(end),
ease_function,
timer: match easing_type {
EasingType::Once { duration } => Timer::new(duration, false),
EasingType::Loop { duration, .. } => Timer::new(duration, false),
EasingType::PingPong { duration, .. } => Timer::new(duration, false),
},
state: EasingState::Play,
paused: false,
easing_type,
#[cfg(feature = "ease_handle")]
id: rng.gen(),
direction: 1,
}
}
fn ease_to(
self,
target: Self,
ease_function: EaseFunction,
easing_type: EasingType,
) -> EasingComponent<Self> {
Self::ease(Some(self), target, ease_function, easing_type)
}
}
impl<T> CustomComponentEase for T where T: Lerp<Scalar = f32> {}