diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 120 |
1 files changed, 82 insertions, 38 deletions
diff --git a/src/main.rs b/src/main.rs index 6d07411..c6563f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::{ time::{Duration, Instant}, }; -use gilrs::{Axis, Gilrs}; +use gilrs::{Axis, Button, Gilrs}; use image::Image; use softbuffer::{Context, Surface}; use tracing::level_filters::LevelFilter; @@ -36,18 +36,13 @@ fn main() { y: HEIGHT / 2.0, }, - dial: DialState { - left_x: 0.0, - left_y: 0.0, - right_x: 0.0, - right_y: 0.0, - }, + dial: DialState::default(), left_angle: 0.0, right_angle: 0.0, next_check: Instant::now(), }; - el.run_app(&mut etch); + el.run_app(&mut etch).unwrap(); } fn setup_logging() { @@ -59,11 +54,8 @@ fn setup_logging() { #[derive(Copy, Clone, Debug, Default)] struct DialState { - left_x: f32, - left_y: f32, - - right_x: f32, - right_y: f32, + left: Vec2<f32>, + right: Vec2<f32>, } struct SurfacedWindow { @@ -75,7 +67,7 @@ struct Etch { window: Option<SurfacedWindow>, gilrs: Gilrs, img: Image, - stylus: Vec2, + stylus: Vec2<f32>, dial: DialState, left_angle: f32, @@ -98,10 +90,20 @@ impl Etch { } match axis { - Axis::LeftStickX => self.dial.left_x = value * 100.0, - Axis::LeftStickY => self.dial.left_y = value * 100.0, - Axis::RightStickX => self.dial.right_x = value * 100.0, - Axis::RightStickY => self.dial.right_y = value * 100.0, + Axis::LeftStickX => self.dial.left.x = value * 100.0, + Axis::LeftStickY => self.dial.left.y = value * 100.0, + Axis::RightStickX => self.dial.right.x = value * 100.0, + Axis::RightStickY => self.dial.right.y = value * 100.0, + _ => (), + } + } + gilrs::EventType::ButtonPressed(btn, code) => { + tracing::trace!("Button press! {btn:?}"); + + match btn { + Button::South => { + self.img.fill(BACKGROUND_COLOUR.into()); + } _ => (), } } @@ -112,13 +114,14 @@ impl Etch { } // Why are my consts HERE of all places -const DIAL_SENSETIVITY: f32 = 2.0; +const DIAL_SENSITIVITY: f32 = 10.0; const WIDTH: f32 = 640.0; const HEIGHT: f32 = 480.0; // a very sublte gentle, dark-and-dull green const BACKGROUND_COLOUR: u32 = 0x00868886; const LINE_COLOUR: u32 = 0x00303230; +const STYLUS_COLOUR: u32 = 0x00a0a0a0; impl ApplicationHandler for Etch { fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { @@ -147,45 +150,60 @@ impl ApplicationHandler for Etch { // We check the state of the joystick at 40fps if self.next_check.elapsed() > Duration::from_millis(25) { - let left_angle = xy_to_deg(self.dial.left_x, self.dial.left_y); - let left_delta = if !left_angle.is_nan() { + let left_angle = xy_to_deg(self.dial.left.x, self.dial.left.y); + + let left_is_large = self.dial.left.mag() > 50.0; + let left_neither_nan = !left_angle.is_nan() && !self.left_angle.is_nan(); + + let left_delta = if left_is_large && left_neither_nan { let delta = angle_delta(left_angle, self.left_angle); - self.left_angle = left_angle; delta } else { 0.0 }; + self.left_angle = left_angle; + + let right_angle = xy_to_deg(self.dial.right.x, self.dial.right.y); - let right_angle = xy_to_deg(self.dial.right_x, self.dial.right_y); - let right_delta = if !right_angle.is_nan() { + let right_is_large = self.dial.right.mag() > 50.0; + let right_neither_nan = !right_angle.is_nan() && !self.right_angle.is_nan(); + + let right_delta = if right_is_large && right_neither_nan { let delta = angle_delta(right_angle, self.right_angle); - self.right_angle = right_angle; delta } else { 0.0 }; + self.right_angle = right_angle; tracing::info!( - "ANGLE {left_angle} // {left_delta}v -=- {right_angle} // {right_delta}v" + "ANGLE ({}) {left_angle} // {left_delta}v -=- ({}) {right_angle} // {right_delta}v", + self.dial.left.mag(), self.dial.right.mag() ); let stylus_prev = self.stylus; - let movement_x = left_delta / 10.0; - let movement_y = right_delta / 10.0; + let movement_x = left_delta / DIAL_SENSITIVITY; + let movement_y = right_delta / DIAL_SENSITIVITY; self.stylus.x = (self.stylus.x + movement_x).clamp(0.0, self.img.width() as f32); self.stylus.y = (self.stylus.y - movement_y).clamp(0.0, self.img.height() as f32); self.img.line( - self.stylus.x as u32, - self.stylus.y as u32, - stylus_prev.x as u32, - stylus_prev.y as u32, + self.stylus.as_u32(), + stylus_prev.as_u32(), 2, LINE_COLOUR.into(), ); + // Letting the line-draw take care of overdrawing the stylus + // worked well except going up for some reason, so we + // explicitly overdraw here. + self.img.rect(stylus_prev.as_u32(), Vec2::new(2, 2), LINE_COLOUR.into()); + + // And then draw the stylus + self.img.rect(self.stylus.as_u32(), Vec2::new(2, 2), STYLUS_COLOUR.into()); + tracing::info!("STYLUS: ({},{})", self.stylus.x, self.stylus.y); self.next_check = Instant::now(); @@ -252,10 +270,17 @@ fn xy_to_deg(x: f32, y: f32) -> f32 { /// and the left-hand side. Intelligently handles the zero-crossing. /// lhs should be the newer value, rhs the older. fn angle_delta(lhs: f32, rhs: f32) -> f32 { - if rhs >= 270.0 && lhs < 90.0 { + // If we move too fast, or flick the stick just right, these values can be + // bypassed. Perhaps we can check on either side of 180, but this is working + // for now. It used to be 270 and 90 for high/low, respectively, but it was + // getting a touch jumpy. + const HIGH: f32 = 225.0; + const LOW: f32 = 135.0; + + if rhs >= HIGH && lhs < LOW { // It is likely we crossed zero in the clockwise direction (lhs + 360.0) - rhs - } else if rhs < 90.0 && lhs > 270.0 { + } else if rhs < LOW && lhs > HIGH { // It is likely we crossed zero in the anti-clockwise direction lhs - (rhs + 360.0) } else { @@ -263,8 +288,27 @@ fn angle_delta(lhs: f32, rhs: f32) -> f32 { } } -#[derive(Copy, Clone, Debug)] -pub struct Vec2 { - x: f32, - y: f32, +#[derive(Copy, Clone, Debug, Default)] +pub struct Vec2<T> { + pub x: T, + pub y: T, +} + +impl<T> Vec2<T> { + pub fn new(x: T, y: T) -> Self { + Self { x, y } + } +} + +impl Vec2<f32> { + pub fn as_u32(&self) -> Vec2<u32> { + Vec2 { + x: self.x as u32, + y: self.y as u32, + } + } + + pub fn mag(&self) -> f32 { + (self.x * self.x + self.y * self.y).sqrt() + } } |