smart_led_effects 0.1.8

A collection of effects for LED strips
Documentation
use crate::strip::EffectIterator;
use palette::{Mix, Srgb};

pub struct ProgressBar {
    count: usize,
    start_colour: Srgb,
    end_colour: Srgb,
    gradient: bool,
    pixels_per_percent: f32,
    current_value: f32,
    last_value: f32,
    last_pixels: Option<Vec<Srgb<u8>>>,
}

impl ProgressBar {
    const DEFAULT_START_COLOUR: Srgb = Srgb::new(0.0, 0.0, 1.0);
    const DEFAULT_END_COLOUR: Srgb = Srgb::new(1.0, 0.0, 0.0);
    pub fn new(
        count: usize,
        start_colour: Option<Srgb>,
        end_colour: Option<Srgb>,
        gradient: Option<bool>,
    ) -> Self {
        ProgressBar {
            count,
            start_colour: start_colour.unwrap_or(Self::DEFAULT_START_COLOUR),
            end_colour: end_colour.unwrap_or(Self::DEFAULT_END_COLOUR),
            gradient: gradient.unwrap_or(false),
            pixels_per_percent: count as f32 / 100.0,
            current_value: 0.0,
            last_value: 0.0,
            last_pixels: None,
        }
    }

    pub fn set_percentage(&mut self, percentage: f32) {
        self.current_value = percentage;
    }

    pub fn get_output_for_value(&mut self, percentage: f32) -> Vec<Srgb<u8>> {
        let percentage = percentage.clamp(0.0, 100.0);
        let pixels = self.count - (self.pixels_per_percent * (100.0 - percentage)) as usize;
        let mut out = vec![Srgb::new(0.0, 0.0, 0.0).into_format(); self.count];

        if self.gradient {
            for (i, pixel) in out.iter_mut().take(pixels).enumerate() {
                *pixel = self
                    .start_colour
                    .mix(self.end_colour, i as f32 / self.count as f32)
                    .into_format();
            }
        } else {
            for pixel in out.iter_mut().take(pixels) {
                *pixel = self
                    .start_colour
                    .mix(self.end_colour, percentage / 100.0)
                    .into_format();
            }
        }

        out
    }
}

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

    fn next(&mut self) -> Option<Vec<Srgb<u8>>> {
        if self.current_value == self.last_value {
            if let Some(pixels) = self.last_pixels.take() {
                return Some(pixels);
            }
        }
        let out = self.get_output_for_value(self.current_value);
        self.last_value = self.current_value;
        self.last_pixels = Some(out.clone());
        Some(out)
    }
}