photonic-effects 0.1.0

Dynamic light controller and animator
Documentation
use std::fmt::Debug;
use std::time::Duration;

use num_traits::Float;

#[derive(Debug)]
pub struct Easing<F: Float> {
    pub func: fn(F) -> F,
    pub speed: Duration,
}

impl<F: Float> Easing<F> {
    pub fn new(func: fn(F) -> F) -> Self {
        return Self {
            func,
            speed: Duration::from_secs(1),
        };
    }

    pub fn with_speed(mut self, speed: Duration) -> Self {
        self.speed = speed;
        return self;
    }
}

impl<F: Float> From<fn(F) -> F> for Easing<F> {
    fn from(func: fn(F) -> F) -> Self {
        return Self::new(func);
    }
}

#[derive(Debug)]
#[cfg_attr(feature = "dynamic", derive(photonic_dynamic::serde::Deserialize))]
#[cfg_attr(feature = "dynamic", serde(rename_all = "snake_case"))]
pub enum EasingDirection {
    In,
    Out,
    InOut,
}

#[derive(Debug)]
#[cfg_attr(feature = "dynamic", derive(photonic_dynamic::serde::Deserialize))]
#[cfg_attr(feature = "dynamic", serde(rename_all = "snake_case"))]
pub enum Easings {
    Instant,
    Linear,
    Quadratic(EasingDirection),
    Cubic(EasingDirection),
    Quartic(EasingDirection),
    Quintic(EasingDirection),
    Sine(EasingDirection),
    Circular(EasingDirection),
    Exponential(EasingDirection),
    Elastic(EasingDirection),
    Back(EasingDirection),
    Bounce(EasingDirection),
}

impl Easings {
    pub fn with_speed<F: Float>(self, speed: Duration) -> Easing<F> {
        return Easing::from(self).with_speed(speed);
    }
}

impl<F: Float> From<Easings> for Easing<F> {
    fn from(value: Easings) -> Self {
        use ezing::*;
        return match value {
            Easings::Instant => |_| F::one(),
            Easings::Linear => linear,
            Easings::Quadratic(EasingDirection::In) => quad_in,
            Easings::Quadratic(EasingDirection::Out) => quad_out,
            Easings::Quadratic(EasingDirection::InOut) => quad_inout,
            Easings::Cubic(EasingDirection::In) => cubic_in,
            Easings::Cubic(EasingDirection::Out) => cubic_out,
            Easings::Cubic(EasingDirection::InOut) => cubic_inout,
            Easings::Quartic(EasingDirection::In) => quart_in,
            Easings::Quartic(EasingDirection::Out) => quart_out,
            Easings::Quartic(EasingDirection::InOut) => quad_inout,
            Easings::Quintic(EasingDirection::In) => quint_in,
            Easings::Quintic(EasingDirection::Out) => quint_out,
            Easings::Quintic(EasingDirection::InOut) => quint_inout,
            Easings::Sine(EasingDirection::In) => sine_in,
            Easings::Sine(EasingDirection::Out) => sine_out,
            Easings::Sine(EasingDirection::InOut) => sine_inout,
            Easings::Circular(EasingDirection::In) => circ_in,
            Easings::Circular(EasingDirection::Out) => circ_out,
            Easings::Circular(EasingDirection::InOut) => circ_inout,
            Easings::Exponential(EasingDirection::In) => expo_in,
            Easings::Exponential(EasingDirection::Out) => expo_out,
            Easings::Exponential(EasingDirection::InOut) => expo_inout,
            Easings::Elastic(EasingDirection::In) => elastic_in,
            Easings::Elastic(EasingDirection::Out) => elastic_out,
            Easings::Elastic(EasingDirection::InOut) => elastic_inout,
            Easings::Back(EasingDirection::In) => back_in,
            Easings::Back(EasingDirection::Out) => back_out,
            Easings::Back(EasingDirection::InOut) => back_inout,
            Easings::Bounce(EasingDirection::In) => bounce_in,
            Easings::Bounce(EasingDirection::Out) => bounce_out,
            Easings::Bounce(EasingDirection::InOut) => bounce_inout,
        }
        .into();
    }
}

#[cfg(feature = "dynamic")]
impl<'de, F: Float> serde::Deserialize<'de> for Easing<F> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where D: serde::Deserializer<'de> {
        #[derive(Debug, serde::Deserialize)]
        struct S {
            func: Easings,

            #[serde(with = "humantime_serde")]
            speed: Duration,
        }

        let s = S::deserialize(deserializer)?;

        return Ok(s.func.with_speed(s.speed));
    }
}