engine/presentation/src/input/eventsystem.rs

542 lines
20 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
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<RwLock<Controller>>),
ControllerButtonDown(ControllerButton),
ControllerButtonUp(ControllerButton),
ControllerAdded(Arc<RwLock<Controller>>),
ControllerRemoved(Arc<RwLock<Controller>>),
// drag'n'drop
FileDrop(String),
}
pub struct EventSystem {
event_pump: RwLock<EventPump>,
mouse: Mutex<MouseUtil>,
controller_subsystem: Mutex<GameControllerSubsystem>,
event_subsystem: Mutex<EventSubsystem>,
controller_deadzones: RwLock<ControllerDeadzones>,
selected_controller: RwLock<Option<Arc<RwLock<Controller>>>>,
connected_controllers: RwLock<Vec<Arc<RwLock<Controller>>>>,
}
impl EventSystem {
pub fn new(sdl2_context: &Sdl) -> Result<EventSystem> {
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<F, R>(&self, event_callback: F, mut resize: R) -> Result<bool>
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<Arc<RwLock<Controller>>>> {
self.connected_controllers.read().unwrap()
}
pub fn active_controller(&self) -> Result<Option<Arc<RwLock<Controller>>>> {
Ok(self.selected_controller.read().unwrap().clone())
}
pub fn set_active_controller(&self, controller: &Arc<RwLock<Controller>>) {
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 {}