96 lines
2.2 KiB
Rust
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,
|
|
}
|
|
}
|
|
}
|
|
}
|