use lyon_geom::{CubicBezierSegment, QuadraticBezierSegment};
pub trait Easing {
fn easing(&self, time_rate: f32) -> f32;
}
#[derive(Clone)]
pub struct CubicBezierEasing(CubicBezierSegment<f32>);
#[derive(Clone, Debug, PartialEq)]
pub struct QuadraticBezierEasing(QuadraticBezierSegment<f32>);
#[derive(Clone)]
pub struct LinearEasing;
pub const EASE: CubicBezierEasing = CubicBezierEasing::new(0.25, 0.1, 0.25, 1.0);
pub const LINEAR: LinearEasing = LinearEasing;
pub const EASE_IN: QuadraticBezierEasing = QuadraticBezierEasing::new(0.42, 0.);
pub const EASE_OUT: QuadraticBezierEasing = QuadraticBezierEasing::new(0.58, 1.);
pub const EASE_IN_OUT: CubicBezierEasing = CubicBezierEasing::new(0.42, 0., 0.58, 1.);
impl CubicBezierEasing {
pub const fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
use lyon_geom::Point as LPoint;
Self(CubicBezierSegment {
from: LPoint::new(0., 0.),
ctrl1: LPoint::new(x1, y1),
ctrl2: LPoint::new(x2, y2),
to: LPoint::new(1., 1.),
})
}
}
impl QuadraticBezierEasing {
pub const fn new(x: f32, y: f32) -> Self {
use lyon_geom::Point as LPoint;
Self(QuadraticBezierSegment {
from: LPoint::new(0., 0.),
ctrl: LPoint::new(x, y),
to: LPoint::new(1., 1.),
})
}
}
impl Easing for LinearEasing {
#[inline]
fn easing(&self, time_rate: f32) -> f32 { time_rate }
}
impl Easing for QuadraticBezierEasing {
#[inline]
fn easing(&self, time_rate: f32) -> f32 { self.0.y(time_rate) }
}
impl Easing for CubicBezierEasing {
#[inline]
fn easing(&self, time_rate: f32) -> f32 {
assert!((0. ..=1.).contains(&time_rate));
self.0.y(time_rate)
}
}
pub enum StepsJump {
JumpStart,
JumpEnd,
JumpNone,
JumpBoth,
}
pub fn steps(step_cnt: u32, jump: StepsJump) -> Steps {
let time_step = 1. / step_cnt as f32;
match jump {
StepsJump::JumpStart => Steps { start: time_step, step: time_step, time_step },
StepsJump::JumpEnd => Steps { start: 0., step: time_step, time_step },
StepsJump::JumpBoth => {
Steps { start: 1. / (step_cnt + 1) as f32, step: 1. / (step_cnt + 1) as f32, time_step }
}
StepsJump::JumpNone => Steps { start: 0., step: 1. / (step_cnt - 1) as f32, time_step },
}
}
#[derive(Clone)]
pub struct Steps {
start: f32,
step: f32,
time_step: f32,
}
impl Easing for Steps {
#[inline]
fn easing(&self, time_rate: f32) -> f32 {
(self.start + (time_rate / self.time_step).floor() * self.step).min(1.)
}
}
#[derive(Clone)]
pub struct StepEnd(pub f32);
impl Easing for StepEnd {
#[inline]
fn easing(&self, time_rate: f32) -> f32 { ((time_rate / self.0).ceil() * self.0).min(1.) }
}