Start work on car rainbow
This commit is contained in:
parent
4781506ff9
commit
e4e69f4d51
@ -1,6 +1,7 @@
|
|||||||
use crate::color::Rgb;
|
use crate::color::Rgb;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub mod car_rainbow;
|
||||||
pub mod collide;
|
pub mod collide;
|
||||||
pub mod fade;
|
pub mod fade;
|
||||||
pub mod flashing;
|
pub mod flashing;
|
||||||
@ -10,6 +11,7 @@ pub mod orb;
|
|||||||
pub mod slide;
|
pub mod slide;
|
||||||
pub mod solid;
|
pub mod solid;
|
||||||
pub mod visualizer;
|
pub mod visualizer;
|
||||||
|
pub use car_rainbow::{CarRainbow, CarRainbowParams};
|
||||||
pub use collide::{Collide, CollideParams};
|
pub use collide::{Collide, CollideParams};
|
||||||
pub use fade::{Fade, FadeParams};
|
pub use fade::{Fade, FadeParams};
|
||||||
pub use flashing::{Flashing, FlashingParams};
|
pub use flashing::{Flashing, FlashingParams};
|
||||||
@ -124,6 +126,7 @@ pub enum Parameters {
|
|||||||
Fade(FadeParams),
|
Fade(FadeParams),
|
||||||
MovingPixel(MovingPixelParams),
|
MovingPixel(MovingPixelParams),
|
||||||
MovingRainbow(MovingRainbowParams),
|
MovingRainbow(MovingRainbowParams),
|
||||||
|
CarRainbow(CarRainbowParams),
|
||||||
Orb(OrbParams),
|
Orb(OrbParams),
|
||||||
Solid(SolidParams),
|
Solid(SolidParams),
|
||||||
Visualizer(VisualizerParams),
|
Visualizer(VisualizerParams),
|
||||||
@ -144,6 +147,7 @@ impl FormRender for Parameters {
|
|||||||
Self::Fade(ref p) => p.render(),
|
Self::Fade(ref p) => p.render(),
|
||||||
Self::MovingPixel(ref p) => p.render(),
|
Self::MovingPixel(ref p) => p.render(),
|
||||||
Self::MovingRainbow(ref p) => p.render(),
|
Self::MovingRainbow(ref p) => p.render(),
|
||||||
|
Self::CarRainbow(ref p) => p.render(),
|
||||||
Self::Orb(ref p) => p.render(),
|
Self::Orb(ref p) => p.render(),
|
||||||
Self::Solid(ref p) => p.render(),
|
Self::Solid(ref p) => p.render(),
|
||||||
Self::Visualizer(ref p) => p.render(),
|
Self::Visualizer(ref p) => p.render(),
|
||||||
@ -162,6 +166,7 @@ impl Parameters {
|
|||||||
"Fade",
|
"Fade",
|
||||||
"MovingPixel",
|
"MovingPixel",
|
||||||
"MovingRainbow",
|
"MovingRainbow",
|
||||||
|
"CarRainbow",
|
||||||
"Orb",
|
"Orb",
|
||||||
"Flashing",
|
"Flashing",
|
||||||
]
|
]
|
||||||
@ -174,6 +179,7 @@ impl Parameters {
|
|||||||
Self::Fade(ref p) => Box::new(Fade::new(p)),
|
Self::Fade(ref p) => Box::new(Fade::new(p)),
|
||||||
Self::MovingPixel(ref p) => Box::new(MovingPixel::new(p)),
|
Self::MovingPixel(ref p) => Box::new(MovingPixel::new(p)),
|
||||||
Self::MovingRainbow(ref p) => Box::new(MovingRainbow::new(p)),
|
Self::MovingRainbow(ref p) => Box::new(MovingRainbow::new(p)),
|
||||||
|
Self::CarRainbow(ref p) => Box::new(CarRainbow::new(p)),
|
||||||
Self::Orb(ref p) => Box::new(Orb::new(p)),
|
Self::Orb(ref p) => Box::new(Orb::new(p)),
|
||||||
Self::Solid(ref p) => Box::new(Solid::new(p)),
|
Self::Solid(ref p) => Box::new(Solid::new(p)),
|
||||||
Self::Visualizer(ref p) => Box::new(Visualizer::new(p)),
|
Self::Visualizer(ref p) => Box::new(Visualizer::new(p)),
|
||||||
|
99
common/src/pattern/car_rainbow.rs
Normal file
99
common/src/pattern/car_rainbow.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
use super::{ColorIterator, FormRender, InputRender, Pattern, PatternError, PatternResult};
|
||||||
|
use crate::color::{self, Rgb, RAINBOW};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{collections::VecDeque, convert::TryFrom, iter};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct CarRainbowParams {
|
||||||
|
pub width: u8,
|
||||||
|
pub skip: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CarRainbowParams {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { width: 8, skip: 4 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormRender for CarRainbowParams {
|
||||||
|
fn render(&self) -> String {
|
||||||
|
[
|
||||||
|
self.width.render("width", None),
|
||||||
|
self.skip.render("skip", None),
|
||||||
|
]
|
||||||
|
.concat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CarRainbow {
|
||||||
|
lights_buf: VecDeque<Rgb>,
|
||||||
|
/// The index to split, if Rainbow from the inside out
|
||||||
|
split_index: usize,
|
||||||
|
skip: u8,
|
||||||
|
width: u8,
|
||||||
|
}
|
||||||
|
impl Default for CarRainbow {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(&CarRainbowParams::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CarRainbow {
|
||||||
|
pub fn new(params: &CarRainbowParams) -> Self {
|
||||||
|
Self {
|
||||||
|
lights_buf: VecDeque::new(),
|
||||||
|
skip: params.skip,
|
||||||
|
width: params.width,
|
||||||
|
split_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Pattern for CarRainbow {
|
||||||
|
fn step(&mut self) -> PatternResult<bool> {
|
||||||
|
self.lights_buf.rotate_left(1);
|
||||||
|
// TODO: Not sure if we should go forward or backwards
|
||||||
|
// if self.forward {
|
||||||
|
// self.lights_buf.rotate_left(1);
|
||||||
|
// } else {
|
||||||
|
// self.lights_buf.rotate_right(1);
|
||||||
|
// }
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
fn init(&mut self, num_lights: u16) -> PatternResult<()> {
|
||||||
|
if !(1..=255).contains(&num_lights) {
|
||||||
|
return Err(PatternError::LightCount);
|
||||||
|
}
|
||||||
|
if self.width < 1 {
|
||||||
|
return Err(PatternError::LightCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (width + skip) * RAINBOW.len()
|
||||||
|
let length_factor = u16::from(self.width)
|
||||||
|
.checked_add(self.skip.into())
|
||||||
|
.ok_or(PatternError::ArithmeticError)?
|
||||||
|
.saturating_mul(u16::try_from(RAINBOW.len()).or(Err(PatternError::ArithmeticError))?);
|
||||||
|
// The length of the buffer
|
||||||
|
// Always a factor of length_factor
|
||||||
|
let buf_length = color::min_with_factor(num_lights, length_factor)?;
|
||||||
|
|
||||||
|
self.split_index = (num_lights / 2_u16) as usize;
|
||||||
|
|
||||||
|
self.lights_buf = RAINBOW
|
||||||
|
.iter()
|
||||||
|
.flat_map(|&x| {
|
||||||
|
iter::repeat(x)
|
||||||
|
.take(self.width.into())
|
||||||
|
.chain(iter::repeat(color::BLACK).take(self.skip.into()))
|
||||||
|
})
|
||||||
|
.cycle()
|
||||||
|
.take(buf_length.into())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn get_strip(&self) -> ColorIterator {
|
||||||
|
let forward_lights = self.lights_buf.iter().take(self.split_index);
|
||||||
|
let backward_lights = self.lights_buf.iter().take(self.split_index).rev();
|
||||||
|
Box::new(forward_lights.chain(backward_lights))
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@ use common::{
|
|||||||
pattern::{self, Pattern},
|
pattern::{self, Pattern},
|
||||||
strip::Message,
|
strip::Message,
|
||||||
};
|
};
|
||||||
use tracing::{error, info};
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
ops::Add,
|
ops::Add,
|
||||||
@ -14,6 +13,7 @@ use std::{
|
|||||||
thread,
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
use tracing::{error, info};
|
||||||
use ws2818_rgb_led_spi_driver::{adapter_gen::Ws28xxAdapter, adapter_spi::Ws28xxSpiAdapter};
|
use ws2818_rgb_led_spi_driver::{adapter_gen::Ws28xxAdapter, adapter_spi::Ws28xxSpiAdapter};
|
||||||
|
|
||||||
/// Maximum number of lights allowed
|
/// Maximum number of lights allowed
|
||||||
|
@ -3,8 +3,8 @@ use actix_web::HttpResponse;
|
|||||||
use actix_web_actors::ws;
|
use actix_web_actors::ws;
|
||||||
use common::{error, pattern, strip};
|
use common::{error, pattern, strip};
|
||||||
use live_view::{LiveView, StateSocket, Template};
|
use live_view::{LiveView, StateSocket, Template};
|
||||||
use template::{AppTemplate, ControlTemplate};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use template::{AppTemplate, ControlTemplate};
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
error::{ErrorInternalServerError, JsonPayloadError, UrlencodedError},
|
error::{ErrorInternalServerError, JsonPayloadError, UrlencodedError},
|
||||||
|
Loading…
Reference in New Issue
Block a user