smart_led_effects/strip/
snow_sparkle.rs

1use crate::strip::EffectIterator;
2use palette::{Hsv, Srgb};
3use rand::{thread_rng, Rng};
4
5use crate::utils::{hsv_to_srgb, srgbu8_to_hsv};
6
7pub struct SnowSparkle {
8    frequency: u8,
9    probability: f32,
10    fade: f32,
11    colour: Hsv,
12    current: Vec<Hsv>,
13}
14
15impl SnowSparkle {
16    const DEFAULT_FREQUENCY: u8 = 0x04;
17    const DEFAULT_PROBABILITY: f32 = 0.1;
18    const DEFAULT_FADE: f32 = 0.4;
19    const BASE_BRIGHTNESS: f32 = 0.2;
20    pub fn new(
21        count: usize,
22        colour: Option<Srgb<u8>>,
23        sparkle: Option<u8>,
24        probability: Option<f32>,
25        fade: Option<f32>,
26    ) -> Self {
27        let mut colour = match colour {
28            Some(colour) => srgbu8_to_hsv(colour),
29            None => Hsv::new(0.0, 0.0, 1.0),
30        };
31
32        colour.value = SnowSparkle::BASE_BRIGHTNESS;
33
34        SnowSparkle {
35            frequency: sparkle.unwrap_or(SnowSparkle::DEFAULT_FREQUENCY),
36            fade: fade.unwrap_or(SnowSparkle::DEFAULT_FADE),
37            probability: probability.unwrap_or(SnowSparkle::DEFAULT_PROBABILITY),
38            current: vec![colour; count],
39            colour,
40        }
41    }
42
43    pub fn sparkle(count: usize, colour: Option<Srgb<u8>>) -> Self {
44        let colour = match colour {
45            Some(colour) => Some(colour),
46            None => Some(Srgb::<u8>::new(255, 255, 255)),
47        };
48        SnowSparkle::new(count, colour, Some(20), Some(0.4), Some(1.0))
49    }
50}
51
52impl SnowSparkle {
53    fn generate_sparkle(&mut self) {
54        let mut rng = thread_rng();
55        let index = rng.gen_range(0..self.current.len());
56
57        let mut sparkle = self.colour;
58        sparkle.value = rng.gen_range(0.5..1.0);
59
60        let chance = rng.gen_range(0.0..1.0);
61        if chance < self.probability {
62            self.current[index] = sparkle;
63        }
64    }
65
66    fn fade_sparkles(&mut self) {
67        for pixel in self.current.iter_mut() {
68            pixel.value = (pixel.value - self.fade).max(Self::BASE_BRIGHTNESS);
69        }
70    }
71}
72
73impl EffectIterator for SnowSparkle {
74    fn name(&self) -> &'static str {
75        "SnowSparkle"
76    }
77
78    fn next(&mut self) -> Option<Vec<Srgb<u8>>> {
79        self.fade_sparkles();
80
81        let chances = thread_rng().gen_range(0..self.frequency);
82        for _ in 0..chances {
83            self.generate_sparkle();
84        }
85
86        Some(hsv_to_srgb(self.current.clone()))
87    }
88}