use crate::patterns::{Pattern, PixelColor}; use crate::Strip; use serde::{Deserialize, Serialize}; /// # Rainbow pattern /// /// every pattern implement the iterator trait /// /// This pattern display a moving rainbow over the strip /// /// ### Note /// /// If max iteration is let to None, it's an infinite pattern. /// #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] pub struct Rainbow { #[serde(default)] pub(crate) current_iteration: usize, pub(crate) max_iteration: Option, pub(crate) step: Option, } impl Pattern for Rainbow { type Strip = Strip; fn init(&mut self) -> Option { None } fn is_last_iteration(&self) -> bool { match self.max_iteration { None => false, Some(max_iter) => { if self.current_iteration >= max_iter { true } else { false } } } } } impl Iterator for Rainbow { type Item = Strip; fn next(&mut self) -> Option { if self.is_last_iteration() { return None; } let mut strip = Strip::default(); let step = self.step.unwrap_or(255 / N); for i in 0..N { let pos = (i * step + self.current_iteration) as u8; strip[i] = Some(wheel(pos)) } self.current_iteration += 1; Some(strip) } } /// compute **rgb** pixel color according to the **hsv** wheel /// /// # Arguments /// /// * `index`: position in the hsv wheel /// /// returns: PixelColor /// fn wheel(index: u8) -> PixelColor { let pos = 255 - index; match pos { 0..=85 => PixelColor { red: 255 - (pos * 3), green: 0, blue: pos * 3, }, 86..=170 => { let pos = pos - 85; PixelColor { red: 0, green: pos * 3, blue: 255 - (pos * 3), } } _ => { let pos = pos - 170; PixelColor { red: pos * 3, green: 255 - (pos * 3), blue: 0, } } } }