diff options
author | gennyble <gen@nyble.dev> | 2024-11-30 02:00:22 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2024-11-30 02:00:22 -0600 |
commit | b8c68049c767e862589c8ac6620fcf818d9a1be5 (patch) | |
tree | d0406c4ecc047a75cbac5d215309d71c791111a5 /src | |
parent | c5f21d3f9843015ff290368205765002400c4622 (diff) | |
download | really-etches-b8c68049c767e862589c8ac6620fcf818d9a1be5.tar.gz really-etches-b8c68049c767e862589c8ac6620fcf818d9a1be5.zip |
Kind of draws!
Diffstat (limited to 'src')
-rw-r--r-- | src/image.rs | 72 | ||||
-rw-r--r-- | src/main.rs | 143 |
2 files changed, 179 insertions, 36 deletions
diff --git a/src/image.rs b/src/image.rs new file mode 100644 index 0000000..66ca858 --- /dev/null +++ b/src/image.rs @@ -0,0 +1,72 @@ +#[allow(dead_code)] +pub struct Image { + width: u32, + height: u32, + data: Vec<u32>, +} + +impl Image { + pub fn new(width: u32, height: u32, fill: Option<Color>) -> Self { + let size = width as usize * height as usize; + let data = match fill { + None => vec![0; size], + Some(color) => vec![color.into(); size], + }; + + Self { + width, + height, + data, + } + } + + pub fn data(&self) -> &[u32] { + &self.data + } + + pub fn data_mut(&mut self) -> &mut [u32] { + &mut self.data + } + + pub fn width(&self) -> u32 { + self.width + } + + pub fn height(&self) -> u32 { + self.height + } + + pub fn rect(&mut self, x: u32, y: u32, width: u32, height: u32) { + todo!() + } +} + +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl Color { + pub fn new(r: u8, g: u8, b: u8) -> Self { + Color { r, g, b } + } +} + +impl Into<u32> for Color { + fn into(self) -> u32 { + ((self.r as u32) << 16) | ((self.g as u32) << 8) | (self.b as u32) + } +} + +impl Into<Color> for u32 { + fn into(self) -> Color { + let bytes = self.to_be_bytes(); + + Color { + r: bytes[1], + g: bytes[2], + b: bytes[3], + } + } +} diff --git a/src/main.rs b/src/main.rs index cdcb23d..9aed460 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,25 @@ use std::{ num::NonZeroU32, + ops::DerefMut, rc::Rc, time::{Duration, Instant}, }; -use gilrs::{Axis, GamepadId, Gilrs}; -use softbuffer::{Buffer, Context, Surface}; +use gilrs::{Axis, Gilrs}; +use image::Image; +use softbuffer::{Context, Surface}; use tracing::level_filters::LevelFilter; use tracing_subscriber::EnvFilter; use winit::{ application::ApplicationHandler, dpi::LogicalSize, - event::{DeviceEvent, WindowEvent}, + event::WindowEvent, event_loop::{ControlFlow, EventLoop}, window::Window, }; +mod image; + fn main() { setup_logging(); @@ -26,9 +30,20 @@ fn main() { let mut etch = Etch { window: None, gilrs: Gilrs::new().unwrap(), + img: Image::new(WIDTH as u32, HEIGHT as u32, Some(BACKGROUND_COLOUR.into())), + stylus: Vec2 { + x: 10.0, + y: HEIGHT / 2.0, + }, - dial: DialState::default(), + dial: DialState { + left_x: 0.0, + left_y: 0.0, + right_x: 0.0, + right_y: 0.0, + }, left_angle: 0.0, + right_angle: 0.0, next_check: Instant::now(), }; @@ -59,16 +74,52 @@ struct SurfacedWindow { struct Etch { window: Option<SurfacedWindow>, gilrs: Gilrs, + img: Image, + stylus: Vec2, dial: DialState, left_angle: f32, + right_angle: f32, next_check: Instant, } +impl Etch { + pub fn process_gamepad_events(&mut self) { + while let Some(gilrs::Event { + id, event, time, .. + }) = self.gilrs.next_event() + { + match event { + gilrs::EventType::AxisChanged(axis, value, _code) => { + tracing::trace!("{axis:?} value={value}"); + + if value.is_nan() { + continue; + } + + 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, + _ => (), + } + } + _ => (), + } + } + } +} + +// Why are my consts HERE of all places const DIAL_SENSETIVITY: f32 = 2.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; + impl ApplicationHandler for Etch { fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { let window = Rc::new(event_loop.create_window(Window::default_attributes()).unwrap()); @@ -92,37 +143,45 @@ impl ApplicationHandler for Etch { event_loop.exit(); } WindowEvent::RedrawRequested => { - let previous_dial = self.dial; - - // Process gamepad events - while let Some(gilrs::Event { - id, event, time, .. - }) = self.gilrs.next_event() - { - match event { - gilrs::EventType::AxisChanged(axis, value, _code) => { - tracing::trace!("{axis:?} value={value}"); - - 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, - _ => (), - } - } - _ => (), - } - } + self.process_gamepad_events(); - // We check the state of the joystick at 20fps - if self.next_check.elapsed() > Duration::from_millis(50) { + // 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 delta = angle_delta(left_angle, self.left_angle); + self.left_angle = left_angle; + delta + } else { + 0.0 + }; + + let right_angle = xy_to_deg(self.dial.right_x, self.dial.right_y); + let right_delta = if !right_angle.is_nan() { + let delta = angle_delta(right_angle, self.right_angle); + self.right_angle = right_angle; + delta + } else { + 0.0 + }; + + tracing::info!( + "ANGLE {left_angle} // {left_delta}v -=- {right_angle} // {right_delta}v" + ); - let left_delta = angle_delta(left_angle, self.left_angle); - self.left_angle = left_angle; + let movement_x = left_delta / 10.0; + let movement_y = right_delta / 10.0; + 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); + + let w = self.img.width(); + self.img.data_mut() + [w as usize * self.stylus.y as usize + self.stylus.x as usize] = LINE_COLOUR; + + tracing::info!("STYLUS: ({},{})", self.stylus.x, self.stylus.y); - tracing::info!("ANGLE {left_angle} // {left_delta}v"); self.next_check = Instant::now(); } @@ -131,18 +190,25 @@ impl ApplicationHandler for Etch { return; }; - let (width, height) = { + let (window_width, window_height) = { let phys = surfaced.window.inner_size(); (phys.width as usize, phys.height as usize) }; let mut buffer = surfaced.surface.buffer_mut().unwrap(); - for idx in 0..width { - buffer[idx + (height / 2) * width] = 0xFF00FF00; - } + neam::nearest_buffer( + self.img.data(), + 1, + self.img.width(), + self.img.height(), + buffer.deref_mut(), + window_width as u32, + window_height as u32, + ); + surfaced.window.pre_present_notify(); buffer.present().unwrap(); - //surfaced.window.request_redraw(); + surfaced.window.request_redraw(); } WindowEvent::Resized(phys) => { tracing::trace!("resized window: {phys:?}"); @@ -190,3 +256,8 @@ fn angle_delta(lhs: f32, rhs: f32) -> f32 { lhs - rhs } } + +pub struct Vec2 { + x: f32, + y: f32, +} |