diff --git a/src/animations.rs b/src/animations.rs index 2c454e7..01a2811 100644 --- a/src/animations.rs +++ b/src/animations.rs @@ -301,7 +301,7 @@ pub fn get_animation(name: &str, db: &State) -> Result struct AnimationId { animation: Animation, id: u8 - }; + } let next = stmt.query_map([name], |row| { Ok(AnimationId { @@ -370,7 +370,7 @@ pub fn get_animation(name: &str, db: &State) -> Result * */ #[get("/delete/")] -pub async fn delete(name: &str, start_sender: &State>, db: &State) -> String { +pub async fn delete(name: &str, db: &State) -> String { let animation = remove_animation(name, db); diff --git a/src/render.rs b/src/render.rs index 4aacf86..f5de026 100644 --- a/src/render.rs +++ b/src/render.rs @@ -3,7 +3,7 @@ use ws281x_rpi::Ws2812Rpi; use crate::{DBPool, animations::Animation}; use std::error::Error; -use smart_leds::{RGB8, SmartLedsWrite}; +use smart_leds::{RGB8, SmartLedsWrite, RGB}; use std::time::{SystemTime, UNIX_EPOCH}; #[derive(Clone, Debug)] @@ -23,7 +23,7 @@ pub struct LigthSetting { #[derive(Clone)] pub struct KeyFrame { - duration: u64, + duration: u128, settings: Vec } @@ -34,16 +34,18 @@ pub struct RenderAnimation { name: String, current_frame: usize, - start_time: u64, + start_time: u128, reset: bool, } pub struct Render { conn: DBPool, num_leds: u32, + + last_render: u128, ws: Option, - last: Vec, + last: Vec>, animations: Vec, @@ -65,6 +67,7 @@ impl Render { let mut render = Render { conn, num_leds: 0, + last_render: 0, ws: None, animations: vec![], local_led_config: vec![], @@ -173,7 +176,7 @@ impl Render { }); } - key_frames.push(KeyFrame { duration: frame.get_duration().into(), settings: light_settings }) + key_frames.push(KeyFrame { duration: (frame.get_duration() as u128) * (1000 as u128), settings: light_settings }) } let new_animation = RenderAnimation { @@ -198,10 +201,14 @@ impl Render { self.animations = self.animations.clone().into_iter().filter(|ani| !ani.name.eq(&animation_name)).collect::>(); } - pub fn proccess_settings (&mut self, data: &mut Vec, settings: &Vec) { - fn load_led_into_light (data: &mut Vec, color: RGB8, start: usize, end: usize) { + pub fn proccess_settings (&mut self, data: &mut Vec>, settings: &Vec) { + fn load_led_into_light (data: &mut Vec>, color: RGB8, start: usize, end: usize) { for i in start..=end { - data[i] = color; + data[i] = RGB::new( + color.r as f64, + color.g as f64, + color.b as f64 + ); } } @@ -227,9 +234,17 @@ impl Render { if self.ws.is_none() { return; } - let mut data = vec![RGB8::default(); self.num_leds.try_into().unwrap()]; + let mut data: Vec> = vec![RGB::default(); self.num_leds.try_into().unwrap()]; - let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs(); + let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis(); + + if self.last_render == 0 { + self.last_render = time; + } + + let delta = time - self.last_render; + + self.last_render = time; let mut to_clean: Vec = Vec::new(); @@ -276,15 +291,66 @@ impl Render { to_clean.iter().for_each(|i| self.remove_animation(i.to_string())); if self.last.is_empty() || !self.last.clone().iter().eq(data.clone().iter()) { - let err = self.ws.as_mut().unwrap().write(data.clone().into_iter()); + + if self.last.len() == 0 { + self.last = data.clone(); + } + + + let lerp_data: Vec> = data.iter().zip(&self.last).map(|(d, l)| l.lerp(d, delta as f64)).collect(); + + //println!("d:{:?}\n l:{:?}", data, lerp_data); + + let to_set_data: Vec> = rgbs_f64_to_u8(&lerp_data); + + let err = self.ws.as_mut().unwrap().write(to_set_data.into_iter()); if err.is_err() || err.ok().is_none() { println!("Failed to write data"); } - self.last = data; + self.last = lerp_data; } } } +pub fn rgbs_f64_to_u8(data: &Vec>) -> Vec>{ + data.clone().iter().map(|a| { + RGB::new( + a.r as u8, + a.g as u8, + a.b as u8 + ) + }).collect() +} + +pub trait Lerp { + fn lerp(self, other: &Self, diff: f64) -> Self; +} + +impl Lerp for f64 { + fn lerp(self, other: &Self, diff: f64) -> Self { + let delta = diff / 1000.0; + + let change = (*other - self) * 0.8 * delta; + + let lerped = self + change; + + if *other != self && diff != 0.0 { + println!("c: {} target:{} lerp: {} move: {}", self, other, lerped, change); + } + + if (*other - self).abs() < 2.0 && diff != 0.0 { + return *other; + } + + lerped + } +} + +impl Lerp for RGB { + fn lerp(self, other: &Self, diff: f64) -> Self { + RGB::new(self.r.lerp(&other.r, diff), self.g.lerp(&other.g, diff), self.b.lerp(&other.b, diff)) + } +} diff --git a/src/utils.rs b/src/utils.rs index 1901568..ef736c9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use rocket::{serde::{Deserialize, Serialize}, Responder, http::{ContentType, Header}}; +use rocket::{serde::{Deserialize, Serialize}, Responder}; #[derive(Deserialize, Serialize)] #[serde(crate="rocket::serde")]