photonic 0.1.1

Dynamic light controller and animator
Documentation
use num_traits::Float;
use palette::rgb::Rgb;
use palette::{Hsl, Hsv, Lch, Mix};

pub trait Lerp {
    fn lerp(a: Self, b: Self, i: f32) -> Self;
}

impl Lerp for f64 {
    fn lerp(f1: Self, f2: Self, i: f32) -> Self {
        assert!((0.0..=1.0).contains(&i));

        if i <= 0.0 {
            return f1;
        }

        if i >= 1.0 {
            return f2;
        }

        return f1 + (f2 - f1) * i as f64;
    }
}

impl Lerp for f32 {
    fn lerp(f1: Self, f2: Self, i: f32) -> Self {
        assert!((0.0..=1.0).contains(&i));

        if i <= 0.0 {
            return f1;
        }

        if i >= 1.0 {
            return f2;
        }

        return f1 + (f2 - f1) * i;
    }
}

impl Lerp for Hsl {
    fn lerp(a: Self, b: Self, i: f32) -> Self {
        return Hsl::mix(a, b, i);
    }
}

impl Lerp for Hsv {
    fn lerp(a: Self, b: Self, i: f32) -> Self {
        return Hsv::mix(a, b, i);
    }
}

impl Lerp for Lch {
    fn lerp(a: Self, b: Self, i: f32) -> Self {
        return Lch::mix(a, b, i);
    }
}

impl Lerp for Rgb {
    fn lerp(a: Self, b: Self, i: f32) -> Self {
        return Rgb::mix(a, b, i);
    }
}

pub fn minmax<F>(a: F, b: F) -> (F, F)
where F: PartialOrd {
    return if a < b { (a, b) } else { (b, a) };
}

pub fn clamp<F>(f: F, r: (F, F)) -> F
where F: PartialOrd {
    if f <= r.0 {
        return r.0;
    }

    if f >= r.1 {
        return r.1;
    }

    return f;
}

pub fn clamp_opt<F>(f: F, r: (Option<F>, Option<F>)) -> F
where F: PartialOrd {
    if let Some(r) = r.0 {
        if f <= r {
            return r;
        }
    }

    if let Some(r) = r.1 {
        if f >= r {
            return r;
        }
    }

    return f;
}

pub fn wrap<F>(f: F, s: usize) -> F
where F: Float {
    let s = F::from(s).expect("Can not convert");
    return (s + (f % s)) % s;
}

pub fn remap<F>(v: F, s: (F, F), t: (F, F)) -> F
where F: Float {
    return (v - s.0) / (s.1 - s.0) * (t.1 - t.0) + t.0;
}