use std::{ collections::HashMap, sync::{Arc, RwLock}, }; use bevy_ecs::resource::Resource; use cache::{CachedElementState, CachedMovement}; use virtual_input::VirtualInput; use winit::{ event::{DeviceEvent, MouseButton, MouseScrollDelta, WindowEvent}, keyboard::PhysicalKey, }; mod cache; mod virtual_binding; mod virtual_input; mod virtual_state; pub use virtual_binding::{AxisDirection, VirtualBinding}; #[derive(Default)] pub struct InputManager { keys_state: CachedElementState, mouse_buttons_state: CachedElementState, mouse_position_delta: CachedMovement, mouse_wheel_delta: CachedMovement, virtual_input: VirtualInput, } #[derive(Resource)] pub struct InputManagerResource(pub Arc>); impl std::fmt::Debug for InputManager { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("InputManager") .field("virtual_input", &self.virtual_input) .finish() } } impl InputManager { pub fn new(input_mapping: HashMap>) -> Self { let mut input_manager = InputManager::default(); for (value_name, bindings) in input_mapping { input_manager.add_virtual_bindings(value_name, bindings); } input_manager } pub fn process_device_event(&mut self, event: &DeviceEvent) { if let DeviceEvent::MouseMotion { delta, .. } = event { self.mouse_position_delta += glam::Vec2::new(delta.0 as f32, delta.1 as f32); } } pub fn process_window_event(&mut self, event: &WindowEvent) { match event { WindowEvent::AxisMotion { axis, value, .. } => { self.virtual_input.update_axis_binding(*axis, *value as f32); } 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::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, *y), }; } _ => {} } } /// Updates deltas before running update pub fn update(&mut self) { 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 { self.virtual_input.get_state(value_name) } fn add_virtual_bindings(&mut self, value_name: String, bindings: Vec) { self.virtual_input.add_bindings(value_name, bindings); } }