#[derive(Clone, Copy, Default)]
pub enum Easing {
#[default]
Linear,
EaseIn,
EaseOut,
EaseInOut,
}
impl Easing {
fn apply(&self, t: f32) -> f32 {
match self {
Easing::Linear => t,
Easing::EaseIn => t * t,
Easing::EaseOut => 1.0 - (1.0 - t) * (1.0 - t),
Easing::EaseInOut => {
if t < 0.5 {
2.0 * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
}
}
}
}
}
pub struct Tween {
current: f32,
target: f32,
speed: f32,
easing: Easing,
progress: f32,
start_value: f32,
}
impl Tween {
pub fn new(initial: f32, speed: f32) -> Self {
Self {
current: initial,
target: initial,
speed,
easing: Easing::Linear,
progress: 1.0,
start_value: initial,
}
}
pub fn with_easing(mut self, easing: Easing) -> Self {
self.easing = easing;
self
}
pub fn set_target(&mut self, target: f32) {
if (target - self.target).abs() > f32::EPSILON {
self.target = target;
self.start_value = self.current;
self.progress = 0.0;
}
}
pub fn update(&mut self) {
if self.progress >= 1.0 {
self.current = self.target;
return;
}
self.progress = (self.progress + self.speed).min(1.0);
let eased = self.easing.apply(self.progress);
self.current = self.start_value + (self.target - self.start_value) * eased;
}
pub fn value(&self) -> f32 {
self.current
}
pub fn done(&self) -> bool {
self.progress >= 1.0
}
pub fn snap(&mut self) {
self.current = self.target;
self.progress = 1.0;
}
}