summaryrefslogtreecommitdiff
path: root/racer-tracer
diff options
context:
space:
mode:
authorSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-03-20 21:25:41 +0100
committerSakarias Johansson <sakariasjohansson@hotmail.com>2023-03-20 21:33:38 +0100
commited8de4988d3f1c81bc4ca833c760dce1497e99d7 (patch)
tree9c96da4d3f2b5216f6e7f455f77ab5cd931d7c8f /racer-tracer
parent60139fe0629a2680160549b525c7cb18bb43be13 (diff)
downloadracer-tracer-ed8de4988d3f1c81bc4ca833c760dce1497e99d7.tar.gz
racer-tracer-ed8de4988d3f1c81bc4ca833c760dce1497e99d7.tar.xz
racer-tracer-ed8de4988d3f1c81bc4ca833c760dce1497e99d7.zip
✨ Add simple way of handling inputs through CBs
Diffstat (limited to 'racer-tracer')
-rw-r--r--racer-tracer/src/error.rs4
-rw-r--r--racer-tracer/src/key_inputs.rs57
-rw-r--r--racer-tracer/src/main.rs74
3 files changed, 113 insertions, 22 deletions
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<TracerError> for i32 {
@@ -65,6 +68,7 @@ impl From<TracerError> 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<Key, Vec<KeyClosure<'a>>>,
+ is_released_callbacks: HashMap<Key, Vec<KeyClosure<'a>>>,
+}
+
+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<dyn ImageAction> = (&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()