diff --git a/src/color.rs b/src/color.rs index ed3c415..23e7965 100644 --- a/src/color.rs +++ b/src/color.rs @@ -8,6 +8,9 @@ impl Rgb { pub const fn to_tuple(self) -> (u8, u8, u8) { (self.0, self.1, self.2) } + pub fn to_float_tuple(self) -> (f32, f32, f32) { + (f32::from(self.0), f32::from(self.1), f32::from(self.2)) + } // pub fn to_gamma_corrected_tuple(&self) -> (u8, u8, u8) { // ( // GAMMA_CORRECT[self.0 as usize], @@ -77,6 +80,37 @@ pub const RAINBOW: [Rgb; 7] = [ Rgb(148, 0, 211), // V ]; +/// Merges a color by some factor +pub fn merge_colors(from_color: Rgb, to_color: Rgb, factor: f32) -> Rgb { + let (from_r, from_g, from_b) = from_color.to_float_tuple(); + let (to_r, to_g, to_b) = to_color.to_float_tuple(); + + // TODO: Do not use as u8 + let r = ((to_r - from_r) * factor + from_r) as u8; + let g = ((to_g - from_g) * factor + from_g) as u8; + let b = ((to_b - from_b) * factor + from_b) as u8; + + Rgb(r, g, b) +} + +/// Builds a color ramp of length `length` of the (exclusive) bounds of `from_color` to `to_color` +pub fn build_ramp(from_color: Rgb, to_color: Rgb, length: usize) -> Vec { + //let diff = i16::from(to_color) - i16::from(from_color); + let mut ret: Vec = vec![]; + // for i in 1..=length { + // () + // } + + // ret + // let (r_step,g_step,b_step) = ( + // (to_color.r - from_color.r).div_euclid(length), + // (to_color.g - from_color.g).div_euclid(length), + // (to_color.b - from_color.b).div_euclid(length), + // ); + // step = 255 + ret +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/pattern.rs b/src/pattern.rs index 8dbf662..e95cf6f 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -4,11 +4,13 @@ pub mod collide; pub mod fade; pub mod moving_pixel; pub mod moving_rainbow; +pub mod orb; pub mod solid; pub use collide::Collide; pub use fade::Fade; pub use moving_pixel::MovingPixel; pub use moving_rainbow::MovingRainbow; +pub use orb::Orb; pub use solid::Solid; pub trait Pattern: std::fmt::Debug { diff --git a/src/pattern/moving_rainbow.rs b/src/pattern/moving_rainbow.rs index c8f3399..7da0ef2 100644 --- a/src/pattern/moving_rainbow.rs +++ b/src/pattern/moving_rainbow.rs @@ -2,23 +2,31 @@ use super::Pattern; use crate::color::{Rgb, RAINBOW}; use std::convert::TryFrom; use std::iter; +//use std::collections::VecDeque; +//TODO Use a VecDeque #[derive(Clone, Debug)] pub struct MovingRainbow { lights_buf: Vec, width: u8, + forward: bool, } impl MovingRainbow { - pub const fn new(width: u8) -> Self { + pub const fn new(width: u8, forward: bool) -> Self { Self { lights_buf: vec![], width, + forward, } } } impl Pattern for MovingRainbow { fn step(&mut self) -> Result { - self.lights_buf.rotate_right(1); + 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) -> Result<(), ()> { diff --git a/src/pattern/orb.rs b/src/pattern/orb.rs new file mode 100644 index 0000000..585f7b4 --- /dev/null +++ b/src/pattern/orb.rs @@ -0,0 +1,49 @@ +use super::Pattern; +use crate::color::Rgb; + +#[derive(Clone, Debug)] +pub struct Orb { + lights_buf: Vec, + color: Rgb, + center_width: u8, + backoff_width: u8, + total_width: u8, + bounces: bool, +} +impl Orb { + pub const fn new(color: Rgb, center_width: u8, backoff_width: u8) -> Self { + Self { + lights_buf: vec![], + color, + center_width, + backoff_width, + total_width: center_width + backoff_width * 2, + bounces: false, + } + } +} +impl Pattern for Orb { + fn step(&mut self) -> Result { + self.lights_buf.rotate_right(1); + Ok(true) + } + fn init(&mut self, num_lights: u16) -> Result<(), ()> { + // if num_lights < 1 || num_lights > 255 { + // return Err(()); + // } + + // self.lights_buf = + + // self.lights_buf = RAINBOW + // .iter() + // .flat_map(|&x| iter::repeat(x).take(self.width.into())) + // .cycle() + // .take(buf_length.into()) + // .collect(); + + Ok(()) + } + fn get_strip(&self) -> &[Rgb] { + &self.lights_buf + } +} diff --git a/src/ui.rs b/src/ui.rs index 4c3da52..78e8375 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -65,10 +65,14 @@ fn parse_cmd(tx: &Sender, s: &str) -> Result<(), String> { let color = parse_color(c, c, c)?; change_pattern(tx, Box::new(pattern::Solid::new(color))) }, - ["r"] =>change_pattern(tx, Box::new(pattern::MovingRainbow::new(4))), + ["r"] =>change_pattern(tx, Box::new(pattern::MovingRainbow::new(4, true))), ["r", w] => { let width = w.parse::().map_err(|_| String::from("Width could not be parsed"))?; - change_pattern(tx, Box::new(pattern::MovingRainbow::new(width))) + change_pattern(tx, Box::new(pattern::MovingRainbow::new(width, true))) + }, + ["r", w, f] => { + let width = w.parse::().map_err(|_| String::from("Width could not be parsed"))?; + change_pattern(tx, Box::new(pattern::MovingRainbow::new(width, ["t", "T"].contains(f)))) }, ["b", r1, g1, b1, r2, g2, b2, r3, g3, b3] => { let left = parse_color(r1, g1, b1)?;