From 5b0ab192078b1357acea720ebc858bcdf5c9eece Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Tue, 27 May 2025 19:44:21 +0200 Subject: [PATCH] input: Refactor all previous states --- src/core/input/cache.rs | 86 ++++++++++++++++++++++++++++++++ src/core/input/keyboard_state.rs | 25 ---------- src/core/input/mod.rs | 86 ++++++++++++++++---------------- src/core/input/mouse_state.rs | 49 ------------------ src/core/input/virtual_state.rs | 7 ++- 5 files changed, 135 insertions(+), 118 deletions(-) create mode 100644 src/core/input/cache.rs delete mode 100644 src/core/input/keyboard_state.rs delete mode 100644 src/core/input/mouse_state.rs diff --git a/src/core/input/cache.rs b/src/core/input/cache.rs new file mode 100644 index 0000000..b9d562c --- /dev/null +++ b/src/core/input/cache.rs @@ -0,0 +1,86 @@ +use std::{ + collections::HashMap, + hash::Hash, + ops::{Add, AddAssign, Sub}, +}; + +use winit::event::ElementState; + +pub struct CachedElementState { + cache: HashMap, +} + +impl Default for CachedElementState { + fn default() -> Self { + Self { + cache: HashMap::new(), + } + } +} + +impl CachedElementState { + pub fn set_key_state(&mut self, key: K, state: ElementState) -> Option { + let key_state = self.cache.get(&key); + let new_key_state = match key_state { + Some(old) => match state { + ElementState::Pressed => match old { + ElementState::Released => Some(ElementState::Pressed), + ElementState::Pressed => None, + }, + ElementState::Released => match old { + ElementState::Released => None, + ElementState::Pressed => Some(ElementState::Released), + }, + }, + None => match state { + ElementState::Pressed => Some(ElementState::Pressed), + ElementState::Released => Some(ElementState::Released), + }, + }; + if let Some(new_key_state) = new_key_state { + self.cache.insert(key, new_key_state); + } + new_key_state + } +} + +#[derive(Default)] +pub struct CachedMovement +where + T: Sub + Add + Default + Copy, +{ + pub old_value: Option, + pub value: T, +} + +impl CachedMovement +where + T: Sub + Add + Default + Copy, +{ + pub fn set_value(&mut self, value: T) { + self.value = value; + } + + pub fn reset(&mut self) -> T { + match self.old_value.as_ref() { + Some(old_value) => { + let diff = self.value - *old_value; + self.old_value = Some(self.value); + diff + } + None => { + self.old_value = Some(self.value); + T::default() + } + } + } +} + +impl AddAssign for CachedMovement +where + T: Add + Sub + Default + Copy, +{ + fn add_assign(&mut self, rhs: T) { + self.value = self.value + rhs; + } +} diff --git a/src/core/input/keyboard_state.rs b/src/core/input/keyboard_state.rs deleted file mode 100644 index f35e448..0000000 --- a/src/core/input/keyboard_state.rs +++ /dev/null @@ -1,25 +0,0 @@ -use egui_winit_vulkano::egui::ahash::HashMap; -use winit::{ - event::{ElementState, WindowEvent}, - keyboard::PhysicalKey, -}; - -use super::{process_new_element_state, virtual_input::VirtualInput}; - -#[derive(Debug, Default)] -pub struct KeyboardState { - key_states: HashMap, -} - -impl KeyboardState { - pub fn process_window_event(&mut self, event: &WindowEvent, virtual_input: &mut VirtualInput) { - if let WindowEvent::KeyboardInput { event, .. } = event { - let key_state = self.key_states.get(&event.physical_key); - let new_key_state = process_new_element_state(key_state, event.state); - if let Some(new_key_state) = new_key_state { - self.key_states.insert(event.physical_key, new_key_state); - virtual_input.update_key_binding(event.physical_key, new_key_state); - } - } - } -} diff --git a/src/core/input/mod.rs b/src/core/input/mod.rs index 00ebe18..08c1862 100644 --- a/src/core/input/mod.rs +++ b/src/core/input/mod.rs @@ -1,12 +1,13 @@ use std::collections::HashMap; -use keyboard_state::KeyboardState; -use mouse_state::MouseState; +use cache::{CachedElementState, CachedMovement}; use virtual_input::VirtualInput; -use winit::event::{ElementState, WindowEvent}; +use winit::{ + event::{MouseButton, MouseScrollDelta, WindowEvent}, + keyboard::PhysicalKey, +}; -mod keyboard_state; -mod mouse_state; +mod cache; mod virtual_binding; mod virtual_input; mod virtual_state; @@ -14,8 +15,10 @@ pub use virtual_binding::{AxisDirection, VirtualBinding}; #[derive(Default)] pub struct InputManager { - keyboard_state: KeyboardState, - mouse_state: MouseState, + keys_state: CachedElementState, + mouse_buttons_state: CachedElementState, + mouse_position_delta: CachedMovement, + mouse_wheel_delta: CachedMovement, virtual_input: VirtualInput, } @@ -41,18 +44,45 @@ impl InputManager { WindowEvent::AxisMotion { axis, value, .. } => { self.virtual_input.update_axis_binding(*axis, *value as f32); } - _ => { - self.keyboard_state - .process_window_event(event, &mut self.virtual_input); - self.mouse_state - .process_window_event(event, &mut self.virtual_input); + WindowEvent::KeyboardInput { event, .. } => { + let new_key_state = self + .keys_state + .set_key_state(event.physical_key, event.state); + if let Some(new_key_state) = new_key_state { + self.virtual_input + .update_key_binding(event.physical_key, new_key_state); + } } + WindowEvent::CursorMoved { position, .. } => { + self.mouse_position_delta + .set_value(glam::Vec2::new(position.x as f32, position.y as f32)); + } + WindowEvent::MouseInput { button, state, .. } => { + let new_mouse_button_state = + self.mouse_buttons_state.set_key_state(*button, *state); + if let Some(new_mouse_button_state) = new_mouse_button_state { + self.virtual_input + .update_mouse_button_binding(*button, new_mouse_button_state); + } + } + WindowEvent::MouseWheel { delta, .. } => { + self.mouse_wheel_delta += match delta { + MouseScrollDelta::PixelDelta(position) => { + glam::Vec2::new(position.x as f32, position.y as f32) + } + MouseScrollDelta::LineDelta(x, y) => glam::Vec2::new(*x as f32, *y as f32), + }; + } + _ => {} } } /// Updates deltas before running update pub fn update(&mut self) { - self.mouse_state.update(&mut self.virtual_input); + self.virtual_input + .update_mouse_move_binding(&self.mouse_position_delta.reset()); + self.virtual_input + .update_mouse_wheel_binding(&self.mouse_wheel_delta.reset()); } pub fn get_virtual_input_state(&self, value_name: &str) -> f32 { @@ -63,33 +93,3 @@ impl InputManager { self.virtual_input.add_bindings(value_name, bindings); } } - -/// Maps the old element state to the new element state. -/// if is changed, returns Some(new_state), otherwise returns None -#[inline] -fn process_new_element_state( - old: Option<&ElementState>, - new: ElementState, -) -> Option { - match old { - Some(old) => match new { - ElementState::Pressed => match old { - ElementState::Released => Some(ElementState::Pressed), - ElementState::Pressed => None, - }, - ElementState::Released => match old { - ElementState::Released => None, - ElementState::Pressed => Some(ElementState::Released), - }, - }, - None => match new { - ElementState::Pressed => Some(ElementState::Pressed), - ElementState::Released => Some(ElementState::Released), - }, - } -} - -#[inline] -fn process_axis_deadzone(value: f32, deadzone: f32) -> f32 { - if value.abs() < deadzone { 0.0 } else { value } -} diff --git a/src/core/input/mouse_state.rs b/src/core/input/mouse_state.rs deleted file mode 100644 index 084f43c..0000000 --- a/src/core/input/mouse_state.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::collections::HashMap; - -use winit::event::{ElementState, MouseButton, MouseScrollDelta, WindowEvent}; - -use super::{process_new_element_state, virtual_input::VirtualInput}; - -#[derive(Debug, Default)] -pub struct MouseState { - old_position: glam::Vec2, - position: glam::Vec2, - delta: glam::Vec2, - wheel_delta: glam::Vec2, - mouse_button_state: HashMap, -} - -impl MouseState { - pub fn process_window_event(&mut self, event: &WindowEvent, virtual_input: &mut VirtualInput) { - match event { - WindowEvent::CursorMoved { position, .. } => { - self.position = glam::Vec2::new(position.x as f32, position.y as f32); - } - WindowEvent::MouseWheel { delta, .. } => { - self.wheel_delta += match delta { - MouseScrollDelta::PixelDelta(position) => { - glam::Vec2::new(position.x as f32, position.y as f32) - } - MouseScrollDelta::LineDelta(x, y) => glam::Vec2::new(*x as f32, *y as f32), - }; - } - WindowEvent::MouseInput { button, state, .. } => { - let key_state = self.mouse_button_state.get(button); - let new_key_state = process_new_element_state(key_state, *state); - if let Some(new_key_state) = new_key_state { - self.mouse_button_state.insert(*button, new_key_state); - virtual_input.update_mouse_button_binding(*button, new_key_state); - } - } - _ => {} - } - } - - pub fn update(&mut self, virtual_input: &mut VirtualInput) { - self.delta = self.position - self.old_position; - self.old_position = self.position; - virtual_input.update_mouse_move_binding(&self.delta); - virtual_input.update_mouse_wheel_binding(&self.wheel_delta); - self.wheel_delta = glam::Vec2::ZERO; - } -} diff --git a/src/core/input/virtual_state.rs b/src/core/input/virtual_state.rs index 93cf28f..779b8ea 100644 --- a/src/core/input/virtual_state.rs +++ b/src/core/input/virtual_state.rs @@ -3,7 +3,7 @@ use winit::{ keyboard::PhysicalKey, }; -use super::{process_axis_deadzone, virtual_binding::VirtualBinding}; +use super::virtual_binding::VirtualBinding; pub struct VirtualBindingState { pub value: f32, @@ -101,3 +101,8 @@ impl VirtualInputState { self.value = new_value; } } + +#[inline] +fn process_axis_deadzone(value: f32, deadzone: f32) -> f32 { + if value.abs() < deadzone { 0.0 } else { value } +}