diff --git a/src/render/app.rs b/src/render/app.rs index ee33768..bbd4a22 100644 --- a/src/render/app.rs +++ b/src/render/app.rs @@ -16,6 +16,7 @@ use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; +use super::input::InputState; use super::vulkan_context::VulkanContext; pub struct App { @@ -24,6 +25,7 @@ pub struct App { gui: HashMap, scene: Option, clear_color: [f32; 3], + input_state: InputState, } impl From for App { @@ -34,6 +36,7 @@ impl From for App { gui: HashMap::new(), scene: None, clear_color: [0.0, 0.0, 0.0], + input_state: InputState::default(), } } } @@ -80,7 +83,10 @@ impl ApplicationHandler for App { fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { let renderer = self.vulkano_windows.get_renderer_mut(id).unwrap(); let gui = self.gui.get_mut(&id).unwrap(); - gui.update(&event); + + if !gui.update(&event) { + self.input_state.process_event(&event); + } match event { WindowEvent::CloseRequested => { @@ -94,6 +100,8 @@ impl ApplicationHandler for App { renderer.resize(); } WindowEvent::RedrawRequested => { + self.input_state.update(); + let acquire_future = renderer.acquire(None, |_| {}).unwrap(); let mut builder = AutoCommandBufferBuilder::primary( diff --git a/src/render/input.rs b/src/render/input.rs new file mode 100644 index 0000000..2b1075e --- /dev/null +++ b/src/render/input.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use winit::{ + dpi::PhysicalPosition, + event::{ElementState, KeyEvent, WindowEvent}, + keyboard::PhysicalKey, +}; + +#[derive(Debug, Default)] +pub enum KeyState { + #[default] + Pressed, + Released, + Held, +} + +#[derive(Debug, Default)] +pub struct MouseState { + old_position: glam::Vec2, + pub position: glam::Vec2, + pub delta: glam::Vec2, +} + +#[derive(Debug, Default)] +pub struct InputState { + pub key_states: HashMap, + pub mouse_state: MouseState, +} + +impl InputState { + pub fn process_event(&mut self, event: &WindowEvent) { + match event { + WindowEvent::KeyboardInput { event, .. } => { + self.update_key_state(event.physical_key, event); + } + WindowEvent::CursorMoved { position, .. } => { + self.update_mouse_position(position); + } + _ => {} + } + } + + /// Updates deltas before running update + pub fn update(&mut self) { + self.mouse_state.delta = self.mouse_state.position - self.mouse_state.old_position; + self.mouse_state.old_position = self.mouse_state.position; + } + + pub fn get_key_state(&self, key: PhysicalKey) -> &KeyState { + self.key_states.get(&key).unwrap_or(&KeyState::Released) + } + + pub fn get_mouse_state(&self) -> &MouseState { + &self.mouse_state + } + + fn update_key_state(&mut self, key: PhysicalKey, event: &KeyEvent) { + let key_state = self.key_states.get(&event.physical_key); + let new_key_state = match key_state { + Some(key_state) => match event.state { + ElementState::Pressed => match key_state { + KeyState::Released => Some(KeyState::Pressed), + KeyState::Pressed => Some(KeyState::Held), + KeyState::Held => None, + }, + ElementState::Released => match key_state { + KeyState::Released => None, + _ => Some(KeyState::Released), + }, + }, + None => match event.state { + ElementState::Pressed => Some(KeyState::Pressed), + ElementState::Released => Some(KeyState::Released), + }, + }; + if let Some(new_key_state) = new_key_state { + log::trace!( + "New key state {:?} for key {:?}", + new_key_state, + event.physical_key + ); + self.key_states.insert(key, new_key_state); + } + } + + fn update_mouse_position(&mut self, position: &PhysicalPosition) { + self.mouse_state.position = glam::Vec2::new(position.x as f32, position.y as f32); + } +} diff --git a/src/render/mod.rs b/src/render/mod.rs index d93a2e0..164a07e 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,4 +1,5 @@ pub mod app; +pub mod input; pub mod pipelines; pub mod scene; pub mod vertex;