Start work on car rainbow
This commit is contained in:
parent
4781506ff9
commit
e4e69f4d51
@ -1,6 +1,7 @@
|
||||
use crate::color::Rgb;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod car_rainbow;
|
||||
pub mod collide;
|
||||
pub mod fade;
|
||||
pub mod flashing;
|
||||
@ -10,6 +11,7 @@ pub mod orb;
|
||||
pub mod slide;
|
||||
pub mod solid;
|
||||
pub mod visualizer;
|
||||
pub use car_rainbow::{CarRainbow, CarRainbowParams};
|
||||
pub use collide::{Collide, CollideParams};
|
||||
pub use fade::{Fade, FadeParams};
|
||||
pub use flashing::{Flashing, FlashingParams};
|
||||
@ -124,6 +126,7 @@ pub enum Parameters {
|
||||
Fade(FadeParams),
|
||||
MovingPixel(MovingPixelParams),
|
||||
MovingRainbow(MovingRainbowParams),
|
||||
CarRainbow(CarRainbowParams),
|
||||
Orb(OrbParams),
|
||||
Solid(SolidParams),
|
||||
Visualizer(VisualizerParams),
|
||||
@ -144,6 +147,7 @@ impl FormRender for Parameters {
|
||||
Self::Fade(ref p) => p.render(),
|
||||
Self::MovingPixel(ref p) => p.render(),
|
||||
Self::MovingRainbow(ref p) => p.render(),
|
||||
Self::CarRainbow(ref p) => p.render(),
|
||||
Self::Orb(ref p) => p.render(),
|
||||
Self::Solid(ref p) => p.render(),
|
||||
Self::Visualizer(ref p) => p.render(),
|
||||
@ -162,6 +166,7 @@ impl Parameters {
|
||||
"Fade",
|
||||
"MovingPixel",
|
||||
"MovingRainbow",
|
||||
"CarRainbow",
|
||||
"Orb",
|
||||
"Flashing",
|
||||
]
|
||||
@ -174,6 +179,7 @@ impl Parameters {
|
||||
Self::Fade(ref p) => Box::new(Fade::new(p)),
|
||||
Self::MovingPixel(ref p) => Box::new(MovingPixel::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::Solid(ref p) => Box::new(Solid::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},
|
||||
strip::Message,
|
||||
};
|
||||
use tracing::{error, info};
|
||||
use std::{
|
||||
cmp,
|
||||
ops::Add,
|
||||
@ -14,6 +13,7 @@ use std::{
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use tracing::{error, info};
|
||||
use ws2818_rgb_led_spi_driver::{adapter_gen::Ws28xxAdapter, adapter_spi::Ws28xxSpiAdapter};
|
||||
|
||||
/// Maximum number of lights allowed
|
||||
|
@ -3,8 +3,8 @@ use actix_web::HttpResponse;
|
||||
use actix_web_actors::ws;
|
||||
use common::{error, pattern, strip};
|
||||
use live_view::{LiveView, StateSocket, Template};
|
||||
use template::{AppTemplate, ControlTemplate};
|
||||
use std::str::FromStr;
|
||||
use template::{AppTemplate, ControlTemplate};
|
||||
|
||||
use actix_web::{
|
||||
error::{ErrorInternalServerError, JsonPayloadError, UrlencodedError},
|
||||
|
Loading…
Reference in New Issue
Block a user