From ed8de4988d3f1c81bc4ca833c760dce1497e99d7 Mon Sep 17 00:00:00 2001 From: Sakarias Johansson Date: Mon, 20 Mar 2023 21:25:41 +0100 Subject: =?UTF-8?q?=E2=9C=A8=20Add=20simple=20way=20of=20handling=20inputs?= =?UTF-8?q?=20through=20CBs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racer-tracer/src/error.rs | 4 +++ racer-tracer/src/key_inputs.rs | 57 ++++++++++++++++++++++++++++++++ racer-tracer/src/main.rs | 74 +++++++++++++++++++++++++++++------------- 3 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 racer-tracer/src/key_inputs.rs diff --git a/racer-tracer/src/error.rs b/racer-tracer/src/error.rs index e0e0934..b7cb46d 100644 --- a/racer-tracer/src/error.rs +++ b/racer-tracer/src/error.rs @@ -43,6 +43,9 @@ pub enum TracerError { #[error("Scene failed to load: {0}")] SceneLoad(String), + + #[error("Key callback failed: {0}")] + KeyError(String), } impl From for i32 { @@ -65,6 +68,7 @@ impl From for i32 { TracerError::ImageSave(_) => 12, TracerError::SceneLoad(_) => 13, TracerError::ArgumentParsingError(_) => 14, + TracerError::KeyError(_) => 15, } } } diff --git a/racer-tracer/src/key_inputs.rs b/racer-tracer/src/key_inputs.rs new file mode 100644 index 0000000..06e0f99 --- /dev/null +++ b/racer-tracer/src/key_inputs.rs @@ -0,0 +1,57 @@ +use std::collections::HashMap; + +use minifb::{Key, Window}; + +use crate::error::TracerError; + +pub type KeyClosure<'a> = &'a (dyn Fn(f64) -> Result<(), TracerError> + Send + Sync); + +pub struct KeyInputs<'a> { + is_down_callbacks: HashMap>>, + is_released_callbacks: HashMap>>, +} + +impl<'a> KeyInputs<'a> { + pub fn new() -> Self { + KeyInputs { + is_down_callbacks: HashMap::new(), + is_released_callbacks: HashMap::new(), + } + } + + pub fn release(&mut self, key: Key, closure: KeyClosure<'a>) { + let callbacks = self + .is_released_callbacks + .entry(key) + .or_insert_with(Vec::new); + callbacks.push(closure); + } + + pub fn down(&mut self, key: Key, closure: KeyClosure<'a>) { + let callbacks = self.is_down_callbacks.entry(key).or_insert_with(Vec::new); + callbacks.push(closure); + } + + pub fn update(&mut self, window: &Window, dt: f64) { + self.is_down_callbacks + .iter_mut() + .filter(|(key, _callbacks)| window.is_key_down(**key)) + .for_each(|(_key, callbacks)| { + callbacks.iter_mut().for_each(|callback| { + if let Err(e) = callback(dt) { + println!("Key callback error: {}", e) + } + }) + }); + self.is_released_callbacks + .iter_mut() + .filter(|(key, _callbacks)| window.is_key_released(**key)) + .for_each(|(_key, callbacks)| { + callbacks.iter_mut().for_each(|callback| { + if let Err(e) = callback(dt) { + println!("Key callback error: {}", e) + } + }) + }); + } +} diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs index 0c65208..59c9208 100644 --- a/racer-tracer/src/main.rs +++ b/racer-tracer/src/main.rs @@ -5,6 +5,7 @@ mod config; mod geometry; mod image; mod image_action; +mod key_inputs; mod material; mod ray; mod render; @@ -22,6 +23,7 @@ use std::{ }; use image_action::ImageAction; +use key_inputs::KeyInputs; use minifb::{Key, Window, WindowOptions}; use synchronoise::SignalEvent; @@ -61,6 +63,54 @@ fn run(config: Config) -> Result<(), TracerError> { let image_action: Box = (&config.image_action).into(); + // Setting up controls + let mut key_inputs = KeyInputs::new(); + let render_image_fn = |_| { + render_image.signal(); + Ok(()) + }; + key_inputs.release(Key::R, &render_image_fn); + + let go_forward = |dt: f64| { + camera + .write() + .map_err(|e| TracerError::KeyError(e.to_string())) + .map(|mut cam| { + cam.go_forward(-dt * camera_speed); + }) + }; + key_inputs.down(Key::W, &go_forward); + + let go_back = |dt: f64| { + camera + .write() + .map_err(|e| TracerError::KeyError(e.to_string())) + .map(|mut cam| { + cam.go_forward(dt * camera_speed); + }) + }; + key_inputs.down(Key::S, &go_back); + + let go_left = |dt: f64| { + camera + .write() + .map_err(|e| TracerError::KeyError(e.to_string())) + .map(|mut cam| { + cam.go_right(-dt * camera_speed); + }) + }; + key_inputs.down(Key::A, &go_left); + + let go_right = |dt: f64| { + camera + .write() + .map_err(|e| TracerError::KeyError(e.to_string())) + .map(|mut cam| { + cam.go_right(dt * camera_speed); + }) + }; + key_inputs.down(Key::D, &go_right); + rayon::scope(|s| { s.spawn(|_| { while render_res.is_ok() { @@ -131,29 +181,9 @@ fn run(config: Config) -> Result<(), TracerError> { while window.is_open() && !window.is_key_down(Key::Escape) && !exit.status() { let dt = t.elapsed().as_micros() as f64 / 1000000.0; t = Instant::now(); + key_inputs.update(&window, dt); // Sleep a bit to not hog the lock on the buffer all the time. - std::thread::sleep(std::time::Duration::from_millis(10)); - - if window.is_key_released(Key::R) { - render_image.signal(); - } - - camera - .write() - .map_err(|e| TracerError::FailedToAcquireLock(e.to_string())) - .map(|mut cam| { - if window.is_key_down(Key::W) { - cam.go_forward(-dt * camera_speed); - } else if window.is_key_down(Key::S) { - cam.go_forward(dt * camera_speed); - } - - if window.is_key_down(Key::A) { - cam.go_right(-dt * camera_speed); - } else if window.is_key_down(Key::D) { - cam.go_right(dt * camera_speed); - } - })?; + std::thread::sleep(std::time::Duration::from_millis(1)); screen_buffer .read() -- cgit v1.2.3