use crate::{
color::{Hsv, HsvHueRainbow},
layout::{Layout1d, Layout2d, Layout3d},
markers::{Dim1d, Dim2d, Dim3d},
pattern::Pattern,
};
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RainbowParams {
pub time_scalar: f32,
pub position_scalar: f32,
}
impl Default for RainbowParams {
fn default() -> Self {
const MILLISECONDS_PER_SECOND: f32 = 1e3;
Self {
time_scalar: 0.3 / MILLISECONDS_PER_SECOND,
position_scalar: 1.,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Rainbow {
params: RainbowParams,
}
impl<Layout> Pattern<Dim1d, Layout> for Rainbow
where
Layout: Layout1d,
{
type Params = RainbowParams;
type Color = Hsv<HsvHueRainbow>;
fn new(params: Self::Params) -> Self {
Self { params }
}
fn tick(&self, time_in_ms: u64) -> impl Iterator<Item = Self::Color> {
let Self { params } = self;
let RainbowParams {
time_scalar,
position_scalar,
} = params;
let time = time_in_ms as f32 * time_scalar;
let step = 0.5 * position_scalar;
Layout::points().map(move |x| {
let hue = x * step + time;
let saturation = 1.;
let value = 1.;
Self::Color::new(hue, saturation, value)
})
}
}
impl<Layout> Pattern<Dim2d, Layout> for Rainbow
where
Layout: Layout2d,
{
type Params = RainbowParams;
type Color = Hsv<HsvHueRainbow>;
fn new(params: Self::Params) -> Self {
Self { params }
}
fn tick(&self, time_in_ms: u64) -> impl Iterator<Item = Self::Color> {
let Self { params } = self;
let RainbowParams {
time_scalar,
position_scalar,
} = params;
let time = time_in_ms as f32 * time_scalar;
let step = 0.5 * position_scalar;
Layout::points().map(move |point| {
let hue = (point.x + point.y) * step + time;
let saturation = 1.;
let value = 1.;
Self::Color::new(hue, saturation, value)
})
}
}
impl<Layout> Pattern<Dim3d, Layout> for Rainbow
where
Layout: Layout3d,
{
type Params = RainbowParams;
type Color = Hsv<HsvHueRainbow>;
fn new(params: Self::Params) -> Self {
Self { params }
}
fn tick(&self, time_in_ms: u64) -> impl Iterator<Item = Self::Color> {
let Self { params } = self;
let RainbowParams {
time_scalar,
position_scalar,
} = params;
let time = time_in_ms as f32 * time_scalar;
let step = 0.5 * position_scalar;
Layout::points().map(move |point| {
let hue = (point.x + point.y + point.z) * step + time;
let saturation = 1.;
let value = 1.;
Self::Color::new(hue, saturation, value)
})
}
}