Update orb

This commit is contained in:
Austen Adler 2021-08-12 21:05:38 -04:00
parent 7987c1796c
commit 17b9f8ed66
4 changed files with 52 additions and 30 deletions

View File

@ -96,7 +96,7 @@ pub fn merge_colors(from_color: Rgb, to_color: Rgb, factor: f32) -> Rgb {
/// Builds a color ramp of length `length` of the (exclusive) bounds of `from_color` to `to_color` /// 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<Rgb> { pub fn build_ramp(from_color: Rgb, to_color: Rgb, length: usize) -> Vec<Rgb> {
let offset = 1.0f32 / (length as f32 + 1.0f32); let offset = 1.0_f32 / (length as f32 + 1.0_f32);
let mut ret: Vec<Rgb> = vec![]; let mut ret: Vec<Rgb> = vec![];
for step in 1..=length { for step in 1..=length {
ret.push(merge_colors(from_color, to_color, offset * step as f32)); ret.push(merge_colors(from_color, to_color, offset * step as f32));

View File

@ -56,13 +56,16 @@ fn main() -> Result<(), ProgramError> {
// I do not care if the console ui crashes // I do not care if the console ui crashes
let (g, h) = (tx.clone(), tx.clone()); let (g, h) = (tx.clone(), tx.clone());
let _console_ui_handle = let _console_ui_handle = thread::spawn(move || -> Result<(), ProgramError> {
thread::spawn(move || -> Result<(), ProgramError> { console_ui_loop(&g) }); let ret = console_ui_loop(&g);
println!("Console ui dead: {:?}", ret);
ret
});
// I do not care if the web ui crashes // I do not care if the web ui crashes
let _web_ui_handle = thread::spawn(move || -> Result<(), io::Error> { let _web_ui_handle = thread::spawn(move || -> Result<(), io::Error> {
let ret = webui::start(h); let ret = webui::start(h);
println!("Webui dead"); println!("Webui dead: {:?}", ret);
ret ret
// TODO: Do not join -- this is just because we are running on a computer with no spi env // TODO: Do not join -- this is just because we are running on a computer with no spi env
}) })

View File

@ -1,46 +1,64 @@
use super::Pattern; use super::Pattern;
use crate::color::{self, Rgb}; use crate::color::{self, Rgb};
use std::iter; use std::iter;
use std::collections::VecDeque;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Orb { pub struct Orb {
lights_buf: Vec<Rgb>, /// Buffer to manage the lights
lights_buf: VecDeque<Rgb>,
/// The color of the orb
color: Rgb, color: Rgb,
/// The width of the center of the orb
center_width: u8, center_width: u8,
/// The width of each side's backoff (fadeout)
backoff_width: u8, backoff_width: u8,
/// The total width of the orb, equal to center_width + 2*backoff_width
total_width: u8, total_width: u8,
/// True if the orb should bounce from left to right, otherwise it will wrap around
bounces: bool, bounces: bool,
step: isize, /// The state of the program
step: usize,
/// The maximum number of steps for a given direction. The orb will turn around after this many steps
step_max: usize,
/// Direction of the orb. This can switch if `bounces` is true
direction: bool, direction: bool,
} }
impl Orb { impl Orb {
pub const fn new(color: Rgb, center_width: u8, backoff_width: u8) -> Self { pub const fn new(color: Rgb, center_width: u8, backoff_width: u8) -> Self {
Self { Self {
lights_buf: vec![], lights_buf: VecDeque::new(),
color, color,
center_width, center_width,
backoff_width, backoff_width,
total_width: center_width + backoff_width * 2, total_width: center_width + backoff_width * 2,
bounces: false, bounces: false,
step: 0, step: 0,
step_max: 0,
direction: true, direction: true,
} }
} }
} }
impl Pattern for Orb { impl Pattern for Orb {
fn step(&mut self) -> Result<bool, ()> { fn step(&mut self) -> Result<bool, ()> {
if self.direction { if !self.bounces {
// If we don't bounce, then just wrap and we're done
self.lights_buf.rotate_right(1); self.lights_buf.rotate_right(1);
self.step += 1; return Ok(true);
} else {
self.lights_buf.rotate_left(1);
self.step -= 1;
} }
if step == 0 { if self.direction {
self.direction = true; self.lights_buf.rotate_right(1);
} else if self.lights_buf - self.step == self.total_width { self.step = self.step.saturating_add(1);
self.direction = false; } else {
self.lights_buf.rotate_left(1);
self.step = self.step.saturating_sub(1);
}
if self.step == self.step_max || self.step == 0 {
self.direction = !self.direction;
// } else if self.lights_buf - self.step == self.total_width {
// self.direction = true;
} }
Ok(true) Ok(true)
@ -62,6 +80,13 @@ impl Pattern for Orb {
.take(num_lights.saturating_sub(self.total_width.into()).into()), .take(num_lights.saturating_sub(self.total_width.into()).into()),
) )
.collect(); .collect();
self.step_max = self
.lights_buf
.len()
.checked_sub(self.total_width.into())
.unwrap_or(self.lights_buf.len());
Ok(()) Ok(())
} }
fn get_strip(&self) -> &[Rgb] { fn get_strip(&self) -> &[Rgb] {

View File

@ -1,8 +1,8 @@
use crate::pattern; use crate::pattern;
use crate::strip; use crate::strip;
// use actix_web::web::JsonConfig; use actix_web::error::{ErrorBadRequest, JsonPayloadError};
use actix_web::web::JsonConfig;
use actix_web::{post, web, App, HttpServer, Responder, Result}; use actix_web::{post, web, App, HttpServer, Responder, Result};
// use actix_web::error::InternalError;
use actix_web_static_files; use actix_web_static_files;
use pattern::PatternParameters; use pattern::PatternParameters;
use std::io; use std::io;
@ -12,21 +12,10 @@ include!(concat!(env!("OUT_DIR"), "/generated.rs"));
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
// TODO: Pre-compute binary somehow? So do not have to unwrap
// #[derive(RustEmbed)]
// #[folder = "html/"]
// struct Asset;
struct AppState { struct AppState {
strip_tx: Arc<Mutex<Sender<strip::Message>>>, strip_tx: Arc<Mutex<Sender<strip::Message>>>,
} }
// #[derive(Deserialize, Debug)]
// struct ColorForm {
// color: String,
// e: E
// }
#[post("/setcolor")] #[post("/setcolor")]
async fn set_color( async fn set_color(
data: web::Data<AppState>, data: web::Data<AppState>,
@ -58,7 +47,12 @@ pub async fn start(tx: Sender<strip::Message>) -> std::io::Result<()> {
}) })
.service( .service(
web::scope("/api") web::scope("/api")
// .app_data(JsonConfig::default()) .app_data(
JsonConfig::default().error_handler(|err: JsonPayloadError, _req| {
println!("JSON error: {:?}", err);
err.into()
}),
)
.service(set_color), .service(set_color),
) )
.service(actix_web_static_files::ResourceFiles::new("/", generated)) .service(actix_web_static_files::ResourceFiles::new("/", generated))