use sdl2; use sdl2::controller::Button; use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; use sdl2::keyboard::Keycode; use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}; use sdl2::EventPump; use sdl2::EventSubsystem; use sdl2::GameControllerSubsystem; use sdl2::Sdl; use ui::prelude::*; use std::ops::Deref; use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard}; use crate::Result; use super::controller::{Controller, ControllerDeadzones}; fn convert_button(button: Button) -> ControllerButton { match button { Button::A => ControllerButton::A, Button::B => ControllerButton::B, Button::Y => ControllerButton::Y, Button::X => ControllerButton::X, Button::Start => ControllerButton::Start, Button::Back => ControllerButton::Select, Button::RightShoulder => ControllerButton::RightButton, Button::LeftShoulder => ControllerButton::LeftButton, Button::DPadUp => ControllerButton::DPadUp, Button::DPadDown => ControllerButton::DPadDown, Button::DPadRight => ControllerButton::DPadRight, Button::DPadLeft => ControllerButton::DPadLeft, Button::Guide => ControllerButton::Guide, Button::LeftStick => ControllerButton::LeftStick, Button::RightStick => ControllerButton::RightStick, Button::Misc1 => ControllerButton::Misc, Button::Paddle1 => ControllerButton::Paddle1, Button::Paddle2 => ControllerButton::Paddle2, Button::Paddle3 => ControllerButton::Paddle3, Button::Paddle4 => ControllerButton::Paddle4, Button::Touchpad => ControllerButton::Touchpad, } } #[derive(Debug)] pub enum Event { // mouse events MouseMotion(u32, u32), MouseButtonDown(MouseButton), MouseButtonUp(MouseButton), MouseWheel(i32, i32, MouseWheelDirection), // keyboard events KeyDown(Keycode), KeyUp(Keycode), TextInput(String), // controller events ControllerAxis(Arc>), ControllerButtonDown(ControllerButton), ControllerButtonUp(ControllerButton), ControllerAdded(Arc>), ControllerRemoved(Arc>), // drag'n'drop FileDrop(String), } pub struct EventSystem { event_pump: RwLock, mouse: Mutex, controller_subsystem: Mutex, event_subsystem: Mutex, controller_deadzones: RwLock, selected_controller: RwLock>>>, connected_controllers: RwLock>>>, } impl EventSystem { pub fn new(sdl2_context: &Sdl) -> Result { let event_system = EventSystem { event_pump: RwLock::new( sdl2_context .event_pump() .map_err(|s| anyhow::Error::msg(s))?, ), mouse: Mutex::new(sdl2_context.mouse()), controller_subsystem: Mutex::new( sdl2_context .game_controller() .map_err(|s| anyhow::Error::msg(s))?, ), event_subsystem: Mutex::new(sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?), controller_deadzones: RwLock::new(ControllerDeadzones::default()), selected_controller: RwLock::new(None), connected_controllers: RwLock::new(Vec::new()), }; event_system.disable_mouse(); event_system.disable_keyboard(); event_system.disable_controller(); Ok(event_system) } pub fn enable_mouse(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.enable_event(SdlEventType::MouseMotion); event_pump.enable_event(SdlEventType::MouseButtonDown); event_pump.enable_event(SdlEventType::MouseButtonUp); self.mouse.lock().unwrap().show_cursor(true); } pub fn disable_mouse(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.disable_event(SdlEventType::MouseMotion); event_pump.disable_event(SdlEventType::MouseButtonDown); event_pump.disable_event(SdlEventType::MouseButtonUp); self.mouse.lock().unwrap().show_cursor(false); } pub fn enable_keyboard(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.enable_event(SdlEventType::KeyUp); event_pump.enable_event(SdlEventType::KeyDown); } pub fn disable_keyboard(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.disable_event(SdlEventType::KeyUp); event_pump.disable_event(SdlEventType::KeyDown); } pub fn enable_controller(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.enable_event(SdlEventType::ControllerAxisMotion); event_pump.enable_event(SdlEventType::ControllerButtonDown); event_pump.enable_event(SdlEventType::ControllerButtonUp); } pub fn disable_controller(&self) { let mut event_pump = self.event_pump.write().unwrap(); event_pump.disable_event(SdlEventType::ControllerAxisMotion); event_pump.disable_event(SdlEventType::ControllerButtonDown); event_pump.disable_event(SdlEventType::ControllerButtonUp); } pub fn set_controller_axis_enable_deadzone(&self, deadzone: f32) { self.controller_deadzones .write() .unwrap() .axis_enable_deadzone = deadzone; } pub fn set_controller_axis_disable_deadzone(&self, deadzone: f32) { self.controller_deadzones .write() .unwrap() .axis_disable_deadzone = deadzone; } pub fn set_controller_trigger_enable_deadzone(&self, deadzone: f32) { self.controller_deadzones .write() .unwrap() .trigger_enable_deadzone = deadzone; } pub fn set_controller_trigger_disable_deadzone(&self, deadzone: f32) { self.controller_deadzones .write() .unwrap() .trigger_disable_deadzone = deadzone; } pub fn quit(&self) -> Result<()> { Ok(self .event_subsystem .lock() .unwrap() .push_event(SdlEvent::Quit { timestamp: 0 }) .map_err(|s| anyhow::Error::msg(s))?) } pub fn poll_events(&self, event_callback: F, mut resize: R) -> Result where F: Fn(Event) -> Result<()>, R: FnMut(u32, u32) -> Result<()>, { let mut controller_axis_changed = false; let mut event_pump = self.event_pump.write().unwrap(); for event in event_pump.poll_iter() { match event { SdlEvent::Window { win_event, .. } => match win_event { WindowEvent::Resized(w, h) | WindowEvent::SizeChanged(w, h) => { resize(w as u32, h as u32)?; } _ => (), }, SdlEvent::Quit { .. } => return Ok(false), // ----------------- Mouse Events --------------------- SdlEvent::MouseMotion { x, y, .. } => { event_callback(Event::MouseMotion(x as u32, y as u32))?; } SdlEvent::MouseButtonDown { mouse_btn, .. } => { let mouse_button = match mouse_btn { SdlMouseButton::Left => MouseButton::Left, SdlMouseButton::Right => MouseButton::Right, SdlMouseButton::Middle => MouseButton::Middle, SdlMouseButton::X1 => MouseButton::Forward, SdlMouseButton::X2 => MouseButton::Backward, SdlMouseButton::Unknown => continue, }; event_callback(Event::MouseButtonDown(mouse_button))?; } SdlEvent::MouseButtonUp { mouse_btn, .. } => { let mouse_button = match mouse_btn { SdlMouseButton::Left => MouseButton::Left, SdlMouseButton::Right => MouseButton::Right, SdlMouseButton::Middle => MouseButton::Middle, SdlMouseButton::X1 => MouseButton::Forward, SdlMouseButton::X2 => MouseButton::Backward, SdlMouseButton::Unknown => continue, }; event_callback(Event::MouseButtonUp(mouse_button))?; } SdlEvent::MouseWheel { x, y, direction, .. } => { event_callback(Event::MouseWheel(x, y, direction))?; } // ------------------- Key Events --------------------- SdlEvent::KeyDown { keycode, repeat, .. } => { if repeat { continue; } if let Some(keycode) = keycode { event_callback(Event::KeyDown(keycode))?; } } SdlEvent::KeyUp { keycode, repeat, .. } => { if repeat { continue; } if let Some(keycode) = keycode { event_callback(Event::KeyUp(keycode))?; } } SdlEvent::TextInput { text, .. } => { event_callback(Event::TextInput(text))?; } // --------------- Controller Events ------------------- SdlEvent::ControllerDeviceAdded { which, .. } => { if cfg!(debug_assertions) { println!("New Device: {}", which); } if let Ok(controller) = Controller::new( self.controller_subsystem.lock().unwrap().deref(), which as u32, self.controller_deadzones.read().unwrap().clone(), ) { let controller = { if cfg!(debug_assertions) { println!( "Controller added: {}({})", controller.name(), controller.id() ); } let mut connected_controllers = self.connected_controllers.write().unwrap(); let mut selected_controller = self.selected_controller.write().unwrap(); let arc_controller = Arc::new(RwLock::new(controller)); connected_controllers.push(arc_controller.clone()); if selected_controller.is_none() { if cfg!(debug_assertions) { let contr = arc_controller.read().unwrap(); println!( "New active controller: {}({})", contr.name(), contr.id() ); } *selected_controller = Some(arc_controller.clone()); } arc_controller }; event_callback(Event::ControllerAdded(controller))?; } } SdlEvent::ControllerDeviceRemoved { which, .. } => { let removed_controller = { let mut selected_controller = self.selected_controller.write().unwrap(); if selected_controller.is_some() { if cfg!(debug_assertions) { let contr = 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 selected_controller.as_ref().unwrap().read().unwrap().id() == which { *selected_controller = None; } } let mut connected_controllers = self.connected_controllers.write().unwrap(); connected_controllers .iter() .position(|controller_cell| { let controller = controller_cell.read().unwrap(); controller.id() == which }) .map(|remove_index| { let removed_controller = 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 selected_controller.is_none() && !connected_controllers.is_empty() { if cfg!(debug_assertions) { println!( "Set active controller: {}", connected_controllers[0].read().unwrap().name() ); } *selected_controller = Some(connected_controllers[0].clone()); } removed_controller }) }; if let Some(removed_controller) = removed_controller { event_callback(Event::ControllerRemoved(removed_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)))?; } // 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::ControllerAxisMotion { axis, value, // which, .. } => { let mut selected_controller = self.selected_controller.write().unwrap(); if let Some(controller) = selected_controller.as_mut() { let mut controller = controller.write().unwrap(); // // 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); } } controller_axis_changed = true; } } SdlEvent::DropFile { filename, .. } => { event_callback(Event::FileDrop(filename))?; } _ => (), } } if controller_axis_changed { if let Some(controller) = self.selected_controller.read().unwrap().as_ref() { 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) -> RwLockReadGuard<'_, Vec>>> { self.connected_controllers.read().unwrap() } pub fn active_controller(&self) -> Result>>> { Ok(self.selected_controller.read().unwrap().clone()) } pub fn set_active_controller(&self, controller: &Arc>) { if let Some(res) = self .connected_controllers .read() .unwrap() .iter() .find(|c| Arc::ptr_eq(c, controller)) { *self.selected_controller.write().unwrap() = Some(res.clone()); } } } unsafe impl Send for EventSystem {} unsafe impl Sync for EventSystem {}