From ae1e06d52ef8996df18dc9f98a803305332932e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20H=C3=BCbner?= Date: Mon, 3 Mar 2025 09:47:37 +0100 Subject: [PATCH] Start reworking event system --- context/src/core/context.rs | 14 +- engine/src/engine/engine_event_handling.rs | 32 +-- engine/src/engine/engine_settings.rs | 96 +++---- examples/simple_window/src/main.rs | 4 +- presentation/src/input/controller.rs | 16 +- presentation/src/input/eventsystem.rs | 309 ++++++--------------- presentation/src/input/joystick.rs | 40 +++ presentation/src/input/mod.rs | 1 + presentation/src/presentationcore.rs | 2 +- 9 files changed, 201 insertions(+), 313 deletions(-) create mode 100644 presentation/src/input/joystick.rs diff --git a/context/src/core/context.rs b/context/src/core/context.rs index 1a22959..5481b59 100644 --- a/context/src/core/context.rs +++ b/context/src/core/context.rs @@ -60,7 +60,7 @@ impl Context { pub fn next_frame(&mut self, world: &mut World, mut f: F) -> Result where C: Send + Sync + 'static, - F: FnMut(&mut World, &mut C, Event) -> Result<()> + Send + Sync + 'static, + F: FnMut(&mut World, &mut C, Event<'_>) -> Result<()> + Send + Sync + 'static, { let render_core = self.render_core.clone(); let consumer = world.resources.get_mut_unchecked::(); @@ -116,19 +116,9 @@ impl Context { self.core.queue() } - pub fn controllers(&self) -> &[Arc>] { + pub fn controllers(&self) -> impl Iterator { self.presentation.event_system().controllers() } - - pub fn active_controller(&self) -> &Option>> { - self.presentation.event_system().active_controller() - } - - pub fn set_active_controller(&mut self, controller: &Arc>) { - self.presentation - .event_system_mut() - .set_active_controller(controller) - } } impl std::fmt::Debug for Context { diff --git a/engine/src/engine/engine_event_handling.rs b/engine/src/engine/engine_event_handling.rs index cecc6d3..52607df 100644 --- a/engine/src/engine/engine_event_handling.rs +++ b/engine/src/engine/engine_event_handling.rs @@ -1,14 +1,9 @@ use crate::prelude::*; - use anyhow::Result; - use std::collections::HashMap; -use std::sync::{Arc, RwLock}; - -// use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle}; #[derive(Debug)] -pub enum EngineEvent { +pub enum EngineEvent<'a> { MouseMotion(u32, u32), MouseButtonDown(MouseButton), MouseButtonUp(MouseButton), @@ -21,14 +16,14 @@ pub enum EngineEvent { ButtonUp(ControllerButton), ControllerAxis(ControllerAxis), - ControllerAdded(Arc>), - ControllerRemoved(Arc>), + ControllerAdded(&'a Controller), + ControllerRemoved(&'a Controller), FileDrop(String), } pub trait EventConsumer: Send + Sync + 'static { - fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()>; + fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()>; } pub struct InputMap { @@ -42,7 +37,7 @@ impl Engine { gui_handler: &GuiHandler, input: &InputMap, consumer: &mut T, - event: Event, + event: Event<'_>, ) -> anyhow::Result<()> { match event { Event::MouseMotion(x, y) => { @@ -71,15 +66,13 @@ impl Engine { Event::TextInput(text) => { Self::text_input(gui_handler, text)?; } - Event::ControllerButtonDown(button) => { + Event::ControllerButtonDown(_controller, button) => { Self::button_down_event(world, gui_handler, consumer, button)?; } - Event::ControllerButtonUp(button) => { + Event::ControllerButtonUp(_controller, button) => { Self::button_up_event(world, consumer, button)?; } Event::ControllerAxis(controller) => { - let controller = controller.read().unwrap(); - if !gui_handler.check_navigatable()? { Self::axis_event(world, consumer, &controller)? } else { @@ -92,6 +85,13 @@ impl Engine { Event::ControllerRemoved(controller) => { Self::controller_removed(world, consumer, controller)? } + + Event::JoystickAxis(_joystick) => todo!(), + Event::JoystickButtonDown(_joystick) => todo!(), + Event::JoystickButtonUp(_joystick) => todo!(), + Event::JoystickAdded(_joystick) => todo!(), + Event::JoystickRemoved(_joystick) => todo!(), + Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?, } @@ -104,7 +104,7 @@ impl Engine { fn controller_added( world: &mut World, consumer: &mut T, - controller: Arc>, + controller: &Controller, ) -> Result<()> { consumer.event(world, EngineEvent::ControllerAdded(controller))?; @@ -115,7 +115,7 @@ impl Engine { fn controller_removed( world: &mut World, consumer: &mut T, - controller: Arc>, + controller: &Controller, ) -> Result<()> { consumer.event(world, EngineEvent::ControllerRemoved(controller))?; diff --git a/engine/src/engine/engine_settings.rs b/engine/src/engine/engine_settings.rs index 34f632e..ec2b9c7 100644 --- a/engine/src/engine/engine_settings.rs +++ b/engine/src/engine/engine_settings.rs @@ -205,7 +205,7 @@ impl EngineSettings { button: ControllerButton, ) -> Result>> { // TODO: don't check it every time we request a button - self.check_controller(context)?; + // self.check_controller(context)?; match self.current_controller_type.read().unwrap().as_ref() { Some(controller_type) => Ok(Some(self.controller_button_for( @@ -347,61 +347,61 @@ impl EngineSettings { } } - fn check_controller(&self, context: &Context) -> Result<()> { - let active_controller = context.active_controller(); + // fn check_controller(&self, context: &Context) -> Result<()> { + // let active_controller = context.active_controller(); - match &active_controller { - // there is an controller connected - Some(controller) => { - let controller_name = controller.read().unwrap().name().clone(); + // match &active_controller { + // // there is an controller connected + // Some(controller) => { + // let controller_name = controller.read().unwrap().name().clone(); - // predict controller type from name - let controller_type = if controller_name.contains("PS4") { - ControllerType::PS4 - } else if controller_name.contains("Steam") { - ControllerType::Steam - } else { - ControllerType::XBox - }; + // // predict controller type from name + // let controller_type = if controller_name.contains("PS4") { + // ControllerType::PS4 + // } else if controller_name.contains("Steam") { + // ControllerType::Steam + // } else { + // ControllerType::XBox + // }; - let mut current_controller_type = self.current_controller_type.write().unwrap(); + // let mut current_controller_type = self.current_controller_type.write().unwrap(); - // check if current controller type is set + // // check if current controller type is set - if current_controller_type.is_some() { - // if controller type is set, check if it is different - if *current_controller_type.as_ref().unwrap() != controller_type { - *current_controller_type = Some(controller_type); + // if current_controller_type.is_some() { + // // if controller type is set, check if it is different + // if *current_controller_type.as_ref().unwrap() != controller_type { + // *current_controller_type = Some(controller_type); - let mut map = self.controller_buttons.write().unwrap(); + // let mut map = self.controller_buttons.write().unwrap(); - // clear map if filled - if !map.is_empty() { - map.clear(); - } - } - } else { - // set the controller type - *current_controller_type = Some(controller_type); - } - } - // there is no controller connected - None => { - let mut current_controller_type = self.current_controller_type.write().unwrap(); - let mut map = self.controller_buttons.write().unwrap(); + // // clear map if filled + // if !map.is_empty() { + // map.clear(); + // } + // } + // } else { + // // set the controller type + // *current_controller_type = Some(controller_type); + // } + // } + // // there is no controller connected + // None => { + // let mut current_controller_type = self.current_controller_type.write().unwrap(); + // let mut map = self.controller_buttons.write().unwrap(); - // clear current type if set - if current_controller_type.is_some() { - *current_controller_type = None; - } + // // clear current type if set + // if current_controller_type.is_some() { + // *current_controller_type = None; + // } - // clear map if filled - if !map.is_empty() { - map.clear(); - } - } - } + // // clear map if filled + // if !map.is_empty() { + // map.clear(); + // } + // } + // } - Ok(()) - } + // Ok(()) + // } } diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs index cc75e14..5fbc9ea 100644 --- a/examples/simple_window/src/main.rs +++ b/examples/simple_window/src/main.rs @@ -53,7 +53,7 @@ impl GameState { } impl EventConsumer for GameState { - fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> { + fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { match self { GameState::Startup => (), GameState::Loading => (), @@ -72,7 +72,7 @@ impl Game { Ok(()) } - fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> { + fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { Ok(()) } } diff --git a/presentation/src/input/controller.rs b/presentation/src/input/controller.rs index f212f1f..3c9e196 100644 --- a/presentation/src/input/controller.rs +++ b/presentation/src/input/controller.rs @@ -3,7 +3,7 @@ use ui::prelude::*; use super::controlleraxis::ControllerAxis; -use sdl2; +use sdl2::{self, GameControllerSubsystem}; #[derive(PartialEq)] enum State { @@ -51,7 +51,7 @@ pub struct Controller { impl Controller { pub fn new( - controller_subsystem: &sdl2::GameControllerSubsystem, + controller_subsystem: &GameControllerSubsystem, id: u32, deadzones: ControllerDeadzones, ) -> Result { @@ -199,7 +199,7 @@ impl Controller { } } - pub fn set_left_x(&mut self, x: f32) { + pub(crate) fn set_left_x(&mut self, x: f32) { self.controller_axis.left_stick.x = x; let direction = self.check_direction( @@ -212,7 +212,7 @@ impl Controller { } } - pub fn set_left_y(&mut self, y: f32) { + pub(crate) fn set_left_y(&mut self, y: f32) { self.controller_axis.left_stick.y = y; let direction = self.check_direction( @@ -225,15 +225,15 @@ impl Controller { } } - pub fn set_right_x(&mut self, x: f32) { + pub(crate) fn set_right_x(&mut self, x: f32) { self.controller_axis.right_stick.x = x; } - pub fn set_right_y(&mut self, y: f32) { + pub(crate) fn set_right_y(&mut self, y: f32) { self.controller_axis.right_stick.y = y; } - pub fn set_left_trigger(&mut self, trigger: f32) { + pub(crate) fn set_left_trigger(&mut self, trigger: f32) { self.controller_axis.left_trigger = trigger; let left_trigger = self.check_trigger(trigger, self.last_left_trigger); @@ -244,7 +244,7 @@ impl Controller { } } - pub fn set_right_trigger(&mut self, trigger: f32) { + pub(crate) fn set_right_trigger(&mut self, trigger: f32) { self.controller_axis.right_trigger = trigger; let right_trigger = self.check_trigger(trigger, self.last_right_trigger); diff --git a/presentation/src/input/eventsystem.rs b/presentation/src/input/eventsystem.rs index 803c554..f00f1c4 100644 --- a/presentation/src/input/eventsystem.rs +++ b/presentation/src/input/eventsystem.rs @@ -2,7 +2,9 @@ use sdl2; use sdl2::EventPump; use sdl2::EventSubsystem; use sdl2::GameControllerSubsystem; +use sdl2::JoystickSubsystem; use sdl2::Sdl; +use sdl2::controller::Axis; use sdl2::controller::Button; use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; use sdl2::keyboard::Keycode; @@ -10,11 +12,12 @@ use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection} use ui::prelude::*; -use std::sync::{Arc, RwLock}; +use std::collections::HashMap; use crate::Result; use super::controller::{Controller, ControllerDeadzones}; +use super::joystick::Joystick; fn convert_button(button: Button) -> ControllerButton { match button { @@ -51,7 +54,7 @@ fn convert_button(button: Button) -> ControllerButton { } #[derive(Debug)] -pub enum Event { +pub enum Event<'a> { // mouse events MouseMotion(u32, u32), MouseButtonDown(MouseButton), @@ -64,11 +67,18 @@ pub enum Event { TextInput(String), // controller events - ControllerAxis(Arc>), - ControllerButtonDown(ControllerButton), - ControllerButtonUp(ControllerButton), - ControllerAdded(Arc>), - ControllerRemoved(Arc>), + ControllerAxis(&'a Controller), + ControllerButtonDown(&'a Controller, ControllerButton), + ControllerButtonUp(&'a Controller, ControllerButton), + ControllerAdded(&'a Controller), + ControllerRemoved(&'a Controller), + + // joystick events + JoystickAxis(&'a Joystick), + JoystickButtonDown(&'a Joystick), + JoystickButtonUp(&'a Joystick), + JoystickAdded(&'a Joystick), + JoystickRemoved(&'a Joystick), // drag'n'drop FileDrop(String), @@ -78,12 +88,13 @@ pub struct EventSystem { event_pump: EventPump, mouse: MouseUtil, controller_subsystem: GameControllerSubsystem, + joystick_subsystem: JoystickSubsystem, event_subsystem: EventSubsystem, controller_deadzones: ControllerDeadzones, - selected_controller: Option>>, - connected_controllers: Vec>>, + connected_controllers: HashMap, + connected_joysticks: HashMap, } impl EventSystem { @@ -96,12 +107,13 @@ impl EventSystem { controller_subsystem: sdl2_context .game_controller() .map_err(|s| anyhow::Error::msg(s))?, + joystick_subsystem: sdl2_context.joystick().map_err(|s| anyhow::Error::msg(s))?, event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?, controller_deadzones: ControllerDeadzones::default(), - selected_controller: None, - connected_controllers: Vec::new(), + connected_controllers: HashMap::new(), + connected_joysticks: HashMap::new(), }; event_system.disable_mouse(); @@ -180,11 +192,9 @@ impl EventSystem { pub fn poll_events(&mut self, mut event_callback: F, mut resize: R) -> Result where - F: FnMut(Event) -> Result<()>, + F: FnMut(Event<'_>) -> Result<()>, R: FnMut(u32, u32) -> Result<()>, { - let mut controller_axis_changed = false; - for event in self.event_pump.poll_iter() { match event { SdlEvent::Window { win_event, .. } => match win_event { @@ -266,184 +276,78 @@ impl EventSystem { which as u32, self.controller_deadzones.clone(), ) { - let controller = { - if cfg!(debug_assertions) { - println!( - "Controller added: {}({})", - controller.name(), - controller.id() - ); - } + if cfg!(debug_assertions) { + println!( + "Controller added: {}({})", + controller.name(), + controller.id() + ); + } - let arc_controller = Arc::new(RwLock::new(controller)); - self.connected_controllers.push(arc_controller.clone()); - - if self.selected_controller.is_none() { - if cfg!(debug_assertions) { - let contr = arc_controller.read().unwrap(); - - println!( - "New active controller: {}({})", - contr.name(), - contr.id() - ); - } - - self.selected_controller = Some(arc_controller.clone()); - } - - arc_controller - }; - - event_callback(Event::ControllerAdded(controller))?; + event_callback(Event::ControllerAdded(&controller))?; + self.connected_controllers + .insert(controller.id(), controller); } } SdlEvent::ControllerDeviceRemoved { which, .. } => { - let removed_controller = { - if self.selected_controller.is_some() { - if cfg!(debug_assertions) { - let contr = - self.selected_controller.as_ref().unwrap().read().unwrap(); - - println!( - "Remove active controller: {}({})", - contr.name(), - contr.id() - ); - } - - // unwrap is save since we just tested for `is_some()` - if self - .selected_controller - .as_ref() - .unwrap() - .read() - .unwrap() - .id() - == which - { - self.selected_controller = None; - } + if let Some(controller) = self.connected_controllers.remove(&which) { + if cfg!(debug_assertions) { + println!( + "Controller removed: {}({})", + controller.name(), + controller.id() + ); } - self.connected_controllers - .iter() - .position(|controller_cell| { - let controller = controller_cell.read().unwrap(); - controller.id() == which - }) - .map(|remove_index| { - let removed_controller = - self.connected_controllers.swap_remove(remove_index); - - if cfg!(debug_assertions) { - let contr = removed_controller.read().unwrap(); - println!( - "Controller removed: {}({})", - contr.name(), - contr.id() - ); - } - - // if we removed the selected controller, take the controller at the first position if possible - if self.selected_controller.is_none() - && !self.connected_controllers.is_empty() - { - if cfg!(debug_assertions) { - println!( - "Set active controller: {}", - self.connected_controllers[0].read().unwrap().name() - ); - } - - self.selected_controller = - Some(self.connected_controllers[0].clone()); - } - - removed_controller - }) - }; - - if let Some(removed_controller) = removed_controller { - event_callback(Event::ControllerRemoved(removed_controller))?; + event_callback(Event::ControllerRemoved(&controller))?; } } - // maybe make use of `which`, for support of multiple controllers - SdlEvent::ControllerButtonDown { - button, - // which, - .. - } => { - // // only call back if the selected controller pressed a button - // match self.selected_controller.read().unwrap().as_ref() { - // Some(selected_controller) => { - // if selected_controller.read().unwrap().id() != which { - // continue; - // } - // } - // None => continue, - // } - - event_callback(Event::ControllerButtonDown(convert_button(button)))?; + SdlEvent::ControllerButtonDown { button, which, .. } => { + event_callback(Event::ControllerButtonDown( + self.connected_controllers.get(&which).unwrap(), + convert_button(button), + ))?; } - // maybe make use of `which`, for support of multiple controllers - SdlEvent::ControllerButtonUp { - button, - // which, - .. - } => { - // // only call back if the selected controller released a button - // match self.selected_controller.read().unwrap().as_ref() { - // Some(selected_controller) => { - // if selected_controller.read().unwrap().id() != which { - // continue; - // } - // } - // None => continue, - // } - - event_callback(Event::ControllerButtonUp(convert_button(button)))?; + SdlEvent::ControllerButtonUp { button, which, .. } => { + event_callback(Event::ControllerButtonUp( + self.connected_controllers.get(&which).unwrap(), + convert_button(button), + ))?; } SdlEvent::ControllerAxisMotion { - axis, - value, - // which, - .. + axis, value, which, .. } => { - if let Some(controller) = self.selected_controller.as_mut() { - let mut controller = controller.write().unwrap(); + let controller = self.connected_controllers.get_mut(&which).unwrap(); + let normalized = value as f32 * 0.000_030_518; - // // only update axis, when selected controller made the change - // if controller.id() != which { - // continue; - // } - - // 1 / 32768 = 0,000030518 - let normalized = value as f32 * 0.000_030_518; - - match axis { - sdl2::controller::Axis::LeftX => { - controller.set_left_x(normalized); - } - sdl2::controller::Axis::RightX => { - controller.set_right_x(normalized); - } - sdl2::controller::Axis::LeftY => { - controller.set_left_y(-normalized); - } - sdl2::controller::Axis::RightY => { - controller.set_right_y(normalized); - } - sdl2::controller::Axis::TriggerLeft => { - controller.set_left_trigger(normalized); - } - sdl2::controller::Axis::TriggerRight => { - controller.set_right_trigger(normalized); - } + match axis { + Axis::LeftX => { + controller.set_left_x(normalized); + } + Axis::RightX => { + controller.set_right_x(normalized); + } + Axis::LeftY => { + controller.set_left_y(-normalized); + } + Axis::RightY => { + controller.set_right_y(normalized); + } + Axis::TriggerLeft => { + controller.set_left_trigger(normalized); + } + Axis::TriggerRight => { + controller.set_right_trigger(normalized); } - - controller_axis_changed = true; } + + event_callback(Event::ControllerAxis(&*controller))?; + } + SdlEvent::JoyDeviceAdded { which, .. } => { + let joystick = Joystick::new(&self.joystick_subsystem, which)?; + + event_callback(Event::JoystickAdded(&joystick))?; + self.connected_joysticks.insert(joystick.id(), joystick); } SdlEvent::DropFile { filename, .. } => { event_callback(Event::FileDrop(filename))?; @@ -452,58 +356,11 @@ impl EventSystem { } } - if controller_axis_changed { - if let Some(controller) = &self.selected_controller { - let (left_trigger, right_trigger) = { - let mut controller_lock = controller.write().unwrap(); - - ( - controller_lock.left_trigger(), - controller_lock.right_trigger(), - ) - }; - - if let Some(right_trigger) = right_trigger { - if right_trigger { - event_callback(Event::ControllerButtonDown( - ControllerButton::RightTrigger, - ))?; - } else { - event_callback(Event::ControllerButtonUp(ControllerButton::RightTrigger))?; - } - } - - if let Some(left_trigger) = left_trigger { - if left_trigger { - event_callback(Event::ControllerButtonDown(ControllerButton::LeftTrigger))?; - } else { - event_callback(Event::ControllerButtonUp(ControllerButton::LeftTrigger))?; - } - } - - event_callback(Event::ControllerAxis(controller.clone()))?; - } - } - Ok(true) } - pub fn controllers(&self) -> &[Arc>] { - &self.connected_controllers - } - - pub fn active_controller(&self) -> &Option>> { - &self.selected_controller - } - - pub fn set_active_controller(&mut self, controller: &Arc>) { - if let Some(res) = self - .connected_controllers - .iter() - .find(|c| Arc::ptr_eq(c, controller)) - { - self.selected_controller = Some(res.clone()); - } + pub fn controllers(&self) -> impl Iterator { + self.connected_controllers.values() } } diff --git a/presentation/src/input/joystick.rs b/presentation/src/input/joystick.rs new file mode 100644 index 0000000..592c822 --- /dev/null +++ b/presentation/src/input/joystick.rs @@ -0,0 +1,40 @@ +use anyhow::Result; +use sdl2::JoystickSubsystem; + +pub struct Joystick { + _sdl2_joystick: sdl2::joystick::Joystick, + id: u32, + name: String, +} + +impl Joystick { + pub fn new(joystick_subsystem: &JoystickSubsystem, id: u32) -> Result { + let sdl2_joystick = joystick_subsystem.open(id)?; + + Ok(Self { + name: sdl2_joystick.name(), + id, + _sdl2_joystick: sdl2_joystick, + }) + } + + pub fn id(&self) -> u32 { + self.id + } + + pub fn name(&self) -> &str { + &self.name + } +} + +impl std::fmt::Debug for Joystick { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Joystick") + .field("id", &self.id) + .field("name", &self.name) + .finish() + } +} + +unsafe impl Send for Joystick {} +unsafe impl Sync for Joystick {} diff --git a/presentation/src/input/mod.rs b/presentation/src/input/mod.rs index 72bb1a9..c0f7c5f 100644 --- a/presentation/src/input/mod.rs +++ b/presentation/src/input/mod.rs @@ -3,3 +3,4 @@ pub mod controller; pub mod controlleraxis; pub mod eventsystem; +pub mod joystick; diff --git a/presentation/src/presentationcore.rs b/presentation/src/presentationcore.rs index 2f86797..b8e87e5 100644 --- a/presentation/src/presentationcore.rs +++ b/presentation/src/presentationcore.rs @@ -113,7 +113,7 @@ impl PresentationCore { pub fn poll_events(&mut self, event_callback: F, resize_event: R) -> Result where - F: FnMut(Event) -> Result<()>, + F: FnMut(Event<'_>) -> Result<()>, R: FnMut(u32, u32) -> Result<()>, { self.event_system.poll_events(event_callback, resize_event)