Refactor input
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 7m43s

This commit is contained in:
Florian RICHER 2025-05-27 17:13:22 +02:00
parent 1976a8b53e
commit 8c42e7b139
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
14 changed files with 439 additions and 159 deletions

View file

@ -0,0 +1,46 @@
use egui_winit_vulkano::egui::ahash::HashMap;
use winit::{
event::{ElementState, KeyEvent},
keyboard::PhysicalKey,
};
use super::virtual_input::VirtualInput;
#[derive(Debug, Default)]
pub struct KeyboardState {
key_states: HashMap<PhysicalKey, ElementState>,
}
impl KeyboardState {
pub fn get_key_states(&self) -> &HashMap<PhysicalKey, ElementState> {
&self.key_states
}
pub fn get_key_state(&self, key: PhysicalKey) -> &ElementState {
self.key_states.get(&key).unwrap_or(&ElementState::Released)
}
pub fn process_window_event(&mut self, event: &KeyEvent, virtual_input: &mut VirtualInput) {
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 {
ElementState::Released => Some(ElementState::Pressed),
ElementState::Pressed => None,
},
ElementState::Released => match key_state {
ElementState::Released => None,
ElementState::Pressed => Some(ElementState::Released),
},
},
None => match event.state {
ElementState::Pressed => Some(ElementState::Pressed),
ElementState::Released => Some(ElementState::Released),
},
};
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);
}
}
}

64
src/core/input/mod.rs Normal file
View file

@ -0,0 +1,64 @@
use std::collections::HashMap;
use keyboard_state::KeyboardState;
use mouse_state::MouseState;
use virtual_binding::VirtualBinding;
use virtual_input::VirtualInput;
use winit::event::WindowEvent;
pub mod keyboard_state;
pub mod mouse_state;
pub mod virtual_binding;
pub mod virtual_input;
pub mod virtual_state;
#[derive(Default)]
pub struct InputManager {
keyboard_state: KeyboardState,
mouse_state: MouseState,
virtual_input: VirtualInput,
}
impl InputManager {
pub fn process_window_event(&mut self, event: &WindowEvent) {
match event {
WindowEvent::KeyboardInput { event, .. } => {
self.keyboard_state
.process_window_event(event, &mut self.virtual_input);
}
WindowEvent::CursorMoved { position, .. } => {
self.mouse_state.process_window_event(position);
}
_ => {}
}
}
/// Updates deltas before running update
pub fn update(&mut self) {
self.mouse_state.update(&mut self.virtual_input);
}
pub fn get_mouse_state(&self) -> &MouseState {
&self.mouse_state
}
pub fn get_keyboard_state(&self) -> &KeyboardState {
&self.keyboard_state
}
pub fn get_virtual_input(&self) -> &VirtualInput {
&self.virtual_input
}
pub fn add_virtual_binding(&mut self, value_name: String, binding: VirtualBinding) {
self.virtual_input.add_binding(value_name, binding);
}
pub fn add_virtual_bindings(&mut self, value_name: String, bindings: Vec<VirtualBinding>) {
self.virtual_input.add_bindings(value_name, bindings);
}
pub fn get_virtual_input_state(&self, value_name: &str) -> f32 {
self.virtual_input.get_state(value_name)
}
}

View file

@ -0,0 +1,22 @@
use winit::dpi::PhysicalPosition;
use super::virtual_input::VirtualInput;
#[derive(Debug, Default)]
pub struct MouseState {
old_position: glam::Vec2,
pub position: glam::Vec2,
pub delta: glam::Vec2,
}
impl MouseState {
pub fn process_window_event(&mut self, position: &PhysicalPosition<f64>) {
self.position = glam::Vec2::new(position.x as f32, position.y as f32);
}
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_binding(&self.delta);
}
}

View file

@ -0,0 +1,24 @@
use winit::{event::AxisId, keyboard::PhysicalKey};
#[derive(Clone)]
pub enum AxisDirection {
Positive,
Negative,
}
impl From<&AxisDirection> for f32 {
fn from(direction: &AxisDirection) -> Self {
match direction {
AxisDirection::Positive => 1.0,
AxisDirection::Negative => -1.0,
}
}
}
#[derive(Clone)]
pub enum VirtualBinding {
Keyboard(PhysicalKey, AxisDirection),
Axis(AxisId, AxisDirection, f32), // f32 deadzone
MouseX(AxisDirection),
MouseY(AxisDirection),
}

View file

@ -0,0 +1,110 @@
use std::{collections::HashMap, sync::Arc};
use egui_winit_vulkano::egui::mutex::Mutex;
use winit::{event::ElementState, keyboard::PhysicalKey};
use super::{
virtual_binding::VirtualBinding,
virtual_state::{VirtualBindingState, VirtualInputState},
};
#[derive(Default)]
pub struct VirtualInput {
states: HashMap<String, Arc<Mutex<VirtualInputState>>>,
states_by_key: HashMap<PhysicalKey, Vec<Arc<Mutex<VirtualInputState>>>>,
mouse_states: Vec<Arc<Mutex<VirtualInputState>>>,
}
impl std::fmt::Debug for VirtualInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug = f.debug_struct("VirtualInput");
for (name, state) in &self.states {
debug.field(name, &state.lock().value);
}
debug.finish()
}
}
impl VirtualInput {
pub fn get_state(&self, value_name: &str) -> f32 {
self.states
.get(value_name)
.and_then(|state| Some(state.lock().value))
.unwrap_or(0.0)
}
pub fn add_bindings(&mut self, value_name: String, new_bindings: Vec<VirtualBinding>) {
add_bindings(
&mut self.states,
&mut self.states_by_key,
&mut self.mouse_states,
value_name,
new_bindings,
);
}
pub fn add_binding(&mut self, value_name: String, binding: VirtualBinding) {
self.add_bindings(value_name, vec![binding]);
}
pub(super) fn update_key_binding(&mut self, key: PhysicalKey, key_state: ElementState) {
let states = self.states_by_key.get_mut(&key);
if let Some(states) = states {
for state in states {
let mut state = state.lock();
state.update_from_key(key, key_state);
}
} else {
log::trace!("{}", self.states_by_key.keys().len());
log::warn!("No states found for key: {key:?}");
}
}
pub(super) fn update_mouse_binding(&mut self, delta: &glam::Vec2) {
for state in &mut self.mouse_states {
let mut state = state.lock();
state.update_from_mouse(delta);
}
}
}
fn add_bindings(
states: &mut HashMap<String, Arc<Mutex<VirtualInputState>>>,
states_by_key: &mut HashMap<PhysicalKey, Vec<Arc<Mutex<VirtualInputState>>>>,
mouse_states: &mut Vec<Arc<Mutex<VirtualInputState>>>,
value_name: String,
new_bindings: Vec<VirtualBinding>,
) {
let state = states
.entry(value_name)
.or_insert(Arc::new(Mutex::new(VirtualInputState {
value: 0.0,
bindings: Vec::new(),
})));
for binding in &new_bindings {
match binding {
VirtualBinding::Keyboard(key, _) => {
states_by_key
.entry(*key)
.or_insert(Vec::new())
.push(state.clone());
}
VirtualBinding::MouseX(_) | VirtualBinding::MouseY(_) => {
mouse_states.push(state.clone());
}
_ => {}
}
}
let mut state = state.lock();
state
.bindings
.extend(new_bindings.iter().map(|b| VirtualBindingState {
value: 0.0,
binding: b.clone(),
}));
}

View file

@ -0,0 +1,49 @@
use winit::{event::ElementState, keyboard::PhysicalKey};
use super::virtual_binding::VirtualBinding;
pub struct VirtualBindingState {
pub value: f32,
pub binding: VirtualBinding,
}
pub struct VirtualInputState {
pub value: f32,
pub bindings: Vec<VirtualBindingState>,
}
impl VirtualInputState {
pub fn update_from_key(&mut self, key: PhysicalKey, key_state: ElementState) {
let mut new_value = 0.0;
for binding in &mut self.bindings {
if let VirtualBinding::Keyboard(binding_key, direction) = &binding.binding {
if binding_key == &key {
if key_state == ElementState::Pressed {
binding.value += f32::from(direction);
} else {
binding.value = 0.0;
}
}
}
new_value += binding.value;
}
self.value = new_value;
}
pub fn update_from_mouse(&mut self, delta: &glam::Vec2) {
let mut new_value = 0.0;
for binding in &mut self.bindings {
match &binding.binding {
VirtualBinding::MouseX(direction) => {
binding.value = f32::from(direction) * delta.x;
}
VirtualBinding::MouseY(direction) => {
binding.value = f32::from(direction) * delta.y;
}
_ => {}
}
new_value += binding.value;
}
self.value = new_value;
}
}