rust_lum/src/patterns/rainbow.rs
2022-03-12 20:52:37 +01:00

96 lines
2.2 KiB
Rust

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<const N: usize> {
#[serde(default)]
pub(crate) current_iteration: usize,
pub(crate) max_iteration: Option<usize>,
pub(crate) step: Option<usize>,
}
impl<const N: usize> Pattern for Rainbow<N> {
type Strip = Strip<N>;
fn init(&mut self) -> Option<Self::Strip> {
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<const N: usize> Iterator for Rainbow<N> {
type Item = Strip<N>;
fn next(&mut self) -> Option<Self::Item> {
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,
}
}
}
}