diff --git a/src/main.rs b/src/main.rs index 8bc3a7b..57bdd2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ use core::f32; -use std::{io::stdin, time::Duration}; +use std::time::Duration; use macroquad::prelude::*; +use serialport::SerialPort; const THICKNESS: f32 = 2.0; const TAIL_LEN: usize = 500; @@ -49,47 +50,66 @@ enum Axis { One, Two } -struct Tail { + +/// # Graph +/// Holds 1 contiguous line. Can be graphed on 1 or 2 axis. +struct Graph { points: [Point; TAIL_LEN], head: usize, - axis: Axis, + axises: Axis, /// What the tail treats as 0 - x_offset: f32, - /// What the tail treats as 0 - y_offset: f32, + head_tracker: f32, + /// The graph's local origin + x_origin: f32, + /// The graph's local origin + y_origin: f32, /// How fast X scrolls when using a since axis tail px_per_s: f32, } -impl Tail { - fn new(axis: Axis, y_axis_offset: f32) -> Self { - let (x_offset, y_offset) = match axis { - Axis::One => (0., y_axis_offset), - Axis::Two => (screen_width() /2., y_axis_offset), +impl Graph { + fn new(axises: Axis) -> Self { + let (x_offset, y_offset) = match axises { + Axis::One => { + (0., screen_height()*0.5) + }, + Axis::Two => { + (screen_width()/2.,screen_height()/2.) + }, }; + Self { // start all the dots off screen points: [Point::new(-1.,-1.); TAIL_LEN], head: 0, - axis, - x_offset, - y_offset, + axises, + x_origin: x_offset, + y_origin: y_offset, px_per_s: 750., + head_tracker: 0., } } - fn place_next(&mut self, delta_time: f32, x_displace: f32, y_displace: f32) { - match self.axis { + fn draw_axises(&self) { + // Horzontal line + // (0, y_origin) -> (max, y_origin) + draw_line(0.,self.y_origin,screen_width(),self.y_origin,1.,DARKGRAY); + // Vertical line + // (x_origin, 0) -> (x_origin, max) + draw_line(self.x_origin,0.,self.x_origin,screen_height(),1.,DARKGRAY); + } + fn place_next(&mut self, delta_time: f32, x_displacement: f32, y_displacement: f32) { + match self.axises { Axis::One => { // x will scroll while y gets displaced - if self.x_offset >= screen_width() { - self.x_offset = 0.; + if self.head_tracker >= screen_width() { + self.head_tracker = 0.; } else { - self.x_offset = self.x_offset + (delta_time * self.px_per_s) + self.head_tracker = self.head_tracker + (delta_time * self.px_per_s) } - self.push(Point::new(self.x_offset, self.y_offset+y_displace)); + self.push(Point::new(self.head_tracker, self.y_origin-y_displacement)); }, Axis::Two => { // both x and y will get displaced - self.push(Point::new(self.x_offset+x_displace,self.y_offset+y_displace)) + self.push(Point::new(self.x_origin+x_displacement,self.y_origin-y_displacement)) }, } } @@ -139,27 +159,65 @@ impl Tail { }; self.points[prev] } - fn points(&self) -> usize { - self.points.len() - } } #[macroquad::main("Graph")] async fn main() { // Dot params - let realtive_y_origin =screen_height()*0.75; - // FIXME realtive_x_origin doesn't work yet - let realtive_x_origin =0.; - let mut tail = Tail::new(Axis::One, realtive_y_origin); + let mut graph = Graph::new(Axis::One); - // Selection box - let mut inital_x_pos = 0.; - let mut inital_y_pos = 0.; - // Tooling let mut show_debug = true; + let mut plot_delta_time = 0.; // Serial + let mut port = get_serial_port(); + let mut serial_buf: Vec = vec![0; 8]; + loop { + clear_background(BLACK); + + graph.draw_axises(); + + let frame_delta_time = get_frame_time(); + // keep track of the delta time since last plot + plot_delta_time += frame_delta_time; + + if let Ok(x) = port.read(serial_buf.as_mut_slice()) { + let s: String = serial_buf.iter().take(x-1).map(|x| *x as char).collect(); + if let Ok(parse) = s.parse::() { + // Only draw when requied + graph.place_next(plot_delta_time, 0., parse); + plot_delta_time = 0.; + } + } + + graph.draw(); + + if is_key_pressed(KeyCode::F3) { + show_debug = !show_debug; + } + // toggle debug box + if show_debug { + // Debug cursor information + let (mouse_x, mouse_y) = mouse_position(); + let size = measure_text(&format!("x{mouse_x}, y{}",-(mouse_y-graph.y_origin)), None, 30,1.); + draw_rectangle(mouse_x, mouse_y+(size.offset_y/4.), size.width, -(size.height), WHITE); + draw_text(&format!("x{}, y{}", mouse_x+graph.x_origin,-(mouse_y-graph.y_origin)), mouse_x, mouse_y, 30., BLACK); + + // Debug textbox + let mut debug = DebugWindow::new(); + debug.add_line(format!("FPS {:04}, Frametime {:05.2}ms", get_fps(), frame_delta_time * 1000.0)); + debug.add_line(format!("Tail Length {TAIL_LEN}, px/s {:.2}", graph.px_per_s)); + debug.add_line(format!("Cursor Pos {:?}", mouse_position())); + debug.add_line(format!("Serial Port {}, Baud Rate {}", port.name().unwrap_or("Unknown".to_string()), port.baud_rate().map_or(String::from("N/A"), |f| f.to_string()))); + debug.draw(); + } + + next_frame().await; + } +} + +fn get_serial_port() -> Box { let port = serialport::available_ports() .expect("No ports found!") .iter() @@ -170,95 +228,7 @@ async fn main() { .open().expect("Failed to open port"); Some(x) }); - let mut port = port.expect("Failed to find valid serial port"); - let mut serial_buf: Vec = vec![0; 8]; - let mut plot_delta_time = 0.; - loop { - clear_background(BLACK); - match tail.axis { - Axis::One => { - draw_line(realtive_x_origin,realtive_y_origin,screen_width(),realtive_y_origin,1.,DARKGRAY); - }, - Axis::Two => { - // horizontal (x) - draw_line(0.,realtive_y_origin,screen_width(),realtive_y_origin,1.,DARKGRAY); - // vertical (y) - draw_line(realtive_x_origin,realtive_y_origin, realtive_x_origin,screen_height(),1.,DARKGRAY); - }, - } - let frame_delta_time = get_frame_time(); - let mut y_displacement = 0.; - let mut x_displacement = 0.; - // keep track of the delta time since last plot - plot_delta_time += frame_delta_time; - - if let Ok(x) = port.read(serial_buf.as_mut_slice()) { - let s: String = serial_buf.iter().take(x-1).map(|x| *x as char).collect(); - if let Ok(parse) = s.parse::() { - y_displacement = parse; - - // only draw when requied - tail.place_next(plot_delta_time, x_displacement, -y_displacement); - plot_delta_time = 0.; - } - } - - tail.draw(); - - // Info about the cursor locaiton - let (mouse_x, mouse_y) = mouse_position(); - - let size = measure_text(&format!("x{mouse_x}, y{}",-1.*(mouse_y-realtive_y_origin)), None, 30,1.); - draw_rectangle(mouse_x, mouse_y, size.width, -(size.height+5.), WHITE); - draw_text(&format!("x{}, y{}", mouse_x+realtive_x_origin,-1.*(mouse_y-realtive_y_origin)), mouse_x, mouse_y-5., 30., BLACK); - - - if is_key_down(KeyCode::S) { - if y_displacement < screen_height()/2. { - y_displacement += 10.; - } - } - if is_key_down(KeyCode::W) { - if y_displacement > -(screen_height()/2.) { - y_displacement -= 10.; - } - } - if is_key_down(KeyCode::D) { - if x_displacement < screen_width()/2. { - x_displacement += 10.; - } - } - if is_key_down(KeyCode::A) { - if x_displacement > -(screen_width()/2.) { - x_displacement -= 10.; - } - } - if is_key_pressed(KeyCode::F3) { - show_debug = !show_debug; - } - // selection box - if is_mouse_button_pressed(MouseButton::Left) { - (inital_x_pos, inital_y_pos) = mouse_position(); - } - if is_mouse_button_down(MouseButton::Left) { - - let (x, y) = mouse_position(); - let width = x - inital_x_pos; - let height = y - inital_y_pos; - - draw_rectangle(inital_x_pos, inital_y_pos, width, height, Color { r: 0.2, g: 0.1, b: 1., a: 0.3 }); - } - // toggle debug box - if show_debug { - let mut debug = DebugWindow::new(); - debug.add_line(format!("FPS {:03}, Latency {:.2}ms", get_fps(), frame_delta_time * 1000.0)); - debug.add_line(format!("Tail Length {TAIL_LEN}, px/s {:.2}", tail.px_per_s)); - debug.add_line(format!("Cursor Pos {:?}", mouse_position())); - debug.add_line(format!("Serial Port {}, Baud Rate {}", port.name().unwrap_or("Unknown".to_string()), port.baud_rate().unwrap_or(0))); - debug.draw(); - } - - next_frame().await; - } + let port = port.expect("Failed to find valid serial port"); + port }