engine/presentation/src/input/eventsystem.rs
2025-03-03 09:47:37 +01:00

368 lines
13 KiB
Rust

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;
use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection};
use ui::prelude::*;
use std::collections::HashMap;
use crate::Result;
use super::controller::{Controller, ControllerDeadzones};
use super::joystick::Joystick;
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<'a> {
// mouse events
MouseMotion(u32, u32),
MouseButtonDown(MouseButton),
MouseButtonUp(MouseButton),
MouseWheel(i32, i32, MouseWheelDirection),
// keyboard events
KeyDown(Keycode),
KeyUp(Keycode),
TextInput(String),
// controller events
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),
}
pub struct EventSystem {
event_pump: EventPump,
mouse: MouseUtil,
controller_subsystem: GameControllerSubsystem,
joystick_subsystem: JoystickSubsystem,
event_subsystem: EventSubsystem,
controller_deadzones: ControllerDeadzones,
connected_controllers: HashMap<u32, Controller>,
connected_joysticks: HashMap<u32, Joystick>,
}
impl EventSystem {
pub fn new(sdl2_context: &Sdl) -> Result<EventSystem> {
let mut event_system = EventSystem {
event_pump: sdl2_context
.event_pump()
.map_err(|s| anyhow::Error::msg(s))?,
mouse: sdl2_context.mouse(),
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(),
connected_controllers: HashMap::new(),
connected_joysticks: HashMap::new(),
};
event_system.disable_mouse();
event_system.disable_keyboard();
event_system.disable_controller();
Ok(event_system)
}
pub fn enable_mouse(&mut self) {
self.event_pump.enable_event(SdlEventType::MouseMotion);
self.event_pump.enable_event(SdlEventType::MouseButtonDown);
self.event_pump.enable_event(SdlEventType::MouseButtonUp);
self.mouse.show_cursor(true);
}
pub fn disable_mouse(&mut self) {
self.event_pump.disable_event(SdlEventType::MouseMotion);
self.event_pump.disable_event(SdlEventType::MouseButtonDown);
self.event_pump.disable_event(SdlEventType::MouseButtonUp);
self.mouse.show_cursor(false);
}
pub fn enable_keyboard(&mut self) {
self.event_pump.enable_event(SdlEventType::KeyUp);
self.event_pump.enable_event(SdlEventType::KeyDown);
}
pub fn disable_keyboard(&mut self) {
self.event_pump.disable_event(SdlEventType::KeyUp);
self.event_pump.disable_event(SdlEventType::KeyDown);
}
pub fn enable_controller(&mut self) {
self.event_pump
.enable_event(SdlEventType::ControllerAxisMotion);
self.event_pump
.enable_event(SdlEventType::ControllerButtonDown);
self.event_pump
.enable_event(SdlEventType::ControllerButtonUp);
}
pub fn disable_controller(&mut self) {
self.event_pump
.disable_event(SdlEventType::ControllerAxisMotion);
self.event_pump
.disable_event(SdlEventType::ControllerButtonDown);
self.event_pump
.disable_event(SdlEventType::ControllerButtonUp);
}
pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones.axis_enable_deadzone = deadzone;
}
pub fn set_controller_axis_disable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones.axis_disable_deadzone = deadzone;
}
pub fn set_controller_trigger_enable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones.trigger_enable_deadzone = deadzone;
}
pub fn set_controller_trigger_disable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones.trigger_disable_deadzone = deadzone;
}
pub fn quit(&self) -> Result<()> {
Ok(self
.event_subsystem
.push_event(SdlEvent::Quit { timestamp: 0 })
.map_err(|s| anyhow::Error::msg(s))?)
}
pub fn poll_events<F, R>(&mut self, mut event_callback: F, mut resize: R) -> Result<bool>
where
F: FnMut(Event<'_>) -> Result<()>,
R: FnMut(u32, u32) -> Result<()>,
{
for event in self.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,
which as u32,
self.controller_deadzones.clone(),
) {
if cfg!(debug_assertions) {
println!(
"Controller added: {}({})",
controller.name(),
controller.id()
);
}
event_callback(Event::ControllerAdded(&controller))?;
self.connected_controllers
.insert(controller.id(), controller);
}
}
SdlEvent::ControllerDeviceRemoved { which, .. } => {
if let Some(controller) = self.connected_controllers.remove(&which) {
if cfg!(debug_assertions) {
println!(
"Controller removed: {}({})",
controller.name(),
controller.id()
);
}
event_callback(Event::ControllerRemoved(&controller))?;
}
}
SdlEvent::ControllerButtonDown { button, which, .. } => {
event_callback(Event::ControllerButtonDown(
self.connected_controllers.get(&which).unwrap(),
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, ..
} => {
let controller = self.connected_controllers.get_mut(&which).unwrap();
let normalized = value as f32 * 0.000_030_518;
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);
}
}
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))?;
}
_ => (),
}
}
Ok(true)
}
pub fn controllers(&self) -> impl Iterator<Item = &Controller> {
self.connected_controllers.values()
}
}
unsafe impl Send for EventSystem {}
unsafe impl Sync for EventSystem {}