smart_led_effects 0.1.8

A collection of effects for LED strips
Documentation
use crate::strip::EffectIterator;
use palette::{FromColor, Hsv, Srgb};
use rand::{thread_rng, Rng};

use crate::utils::hsv_to_srgb;

pub struct Twinkle {
    frequency: u8,
    probability: f32,
    fade: f32,
    colour: Option<Hsv>,
    current: Vec<Hsv>,
}

impl Twinkle {
    const DEFAULT_FREQUENCY: u8 = 0x04;
    const DEFAULT_PROBABILITY: f32 = 0.1;
    const DEFAULT_FADE: f32 = 0.02;
    pub fn new(
        count: usize,
        colour: Option<Srgb<u8>>,
        sparkle: Option<u8>,
        probability: Option<f32>,
        fade: Option<f32>,
    ) -> Self {
        Twinkle {
            frequency: sparkle.unwrap_or(Twinkle::DEFAULT_FREQUENCY),
            fade: fade.unwrap_or(Twinkle::DEFAULT_FADE),
            probability: probability.unwrap_or(Twinkle::DEFAULT_PROBABILITY),
            current: vec![Hsv::new(0.0, 1.0, 0.0); count],
            colour: colour.map(|colour| Hsv::from_color(colour.into_format())),
        }
    }

    pub fn sparkle(count: usize, colour: Option<Srgb<u8>>) -> Self {
        let colour = match colour {
            Some(colour) => Some(colour),
            None => Some(Srgb::<u8>::new(255, 255, 255)),
        };
        Twinkle::new(count, colour, Some(20), Some(0.4), Some(1.0))
    }
}

impl Twinkle {
    fn generate_sparkle(&mut self) {
        let mut rng = thread_rng();
        let index = rng.gen_range(0..self.current.len());

        let mut sparkle = match self.colour {
            Some(colour) => colour,
            None => Hsv::new(rng.gen_range(0.0..360.0), 1.0, 0.0),
        };

        sparkle.value = rng.gen_range(0.5..1.0);

        let chance = rng.gen_range(0.0..1.0);
        if chance < self.probability {
            self.current[index] = sparkle;
        }
    }

    fn fade_sparkles(&mut self) {
        for pixel in self.current.iter_mut() {
            pixel.value = if pixel.value > self.fade {
                pixel.value - self.fade
            } else {
                0.0
            };
        }
    }
}

impl EffectIterator for Twinkle {
    fn name(&self) -> &'static str {
        "Twinkle"
    }

    fn next(&mut self) -> Option<Vec<Srgb<u8>>> {
        self.fade_sparkles();

        let chances = thread_rng().gen_range(0..self.frequency);
        for _ in 0..chances {
            self.generate_sparkle();
        }

        Some(hsv_to_srgb(self.current.clone()))
    }
}