Skip to content

Commit

Permalink
Created intermediate enum for events
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorKoenders committed Sep 16, 2024
1 parent d96bb53 commit e3e6656
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 119 deletions.
23 changes: 19 additions & 4 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
use fermium::prelude::SDL_QUIT;

use crate::graphics::Graphics;
use crate::input::Input;
use crate::input::{Event, Input};
use crate::time::Timer;
use crate::window::Window;

/// The generic event handler for the game. You should implement this yourself
///
/// ## Call order:
/// 1. `event`: 0 to n times based on what events are received
/// 2. `update`: 0 to n times based on the tick rate
/// 3. `draw`: 1 time per frame
pub trait EventHandler {
/// Handle a raw event for the game. This is useful for one-off events, like key down events.
/// For continuous events, like moving a character when you hold a key, use the update method.
///
/// note: this will be called after the `app.input` has been updated with the event.
fn event(&mut self, _app: &mut App, _event: Event) {}
fn update(&mut self, _app: &mut App) {}
fn draw(&mut self, _app: &mut App) {}
}
Expand Down Expand Up @@ -42,7 +53,7 @@ impl App {
while self.is_running {
self.timer.tick_until_update_ready();

self.handle_events();
self.handle_events(event_handler);

while self.timer.consume_time() {
event_handler.update(self);
Expand All @@ -56,15 +67,19 @@ impl App {
}
}

pub fn handle_events(&mut self) {
pub fn handle_events(&mut self, event_handler: &mut impl EventHandler) {
while let Some(event) = self.window.next_event() {
unsafe {
if event.type_ == SDL_QUIT {
self.is_running = false;
}
}

self.input.event(&event);
if let Some(event) = crate::input::Event::try_from_sdl_event(&event) {
self.input.event(&event);

event_handler.event(self, event);
}
}
}
}
154 changes: 42 additions & 112 deletions src/input.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
mod event;
mod gamepad;
mod key;
mod mouse;

use std::collections::{HashMap, HashSet};
use std::hash::Hash;

use fermium::prelude::*;
use glam::Vec2;

pub use self::event::*;
pub use self::gamepad::*;
pub use self::key::*;
pub use self::mouse::*;
Expand All @@ -21,7 +22,7 @@ pub struct Input {
mouse_position: Vec2,

gamepads: Vec<Option<Gamepad>>,
joystick_ids: HashMap<SDL_JoystickID, usize>,
joystick_ids: HashMap<JoystickID, usize>,
}

impl Input {
Expand All @@ -39,123 +40,52 @@ impl Input {
}
}

pub fn event(&mut self, event: &SDL_Event) {
unsafe {
match event.type_ {
SDL_KEYDOWN if event.key.repeat == 0 => {
if let Some(key) = Key::from_raw(event.key.keysym.scancode) {
self.keys.set_down(key);
pub fn event(&mut self, event: &Event) {
match event {
Event::KeyDown(key) => self.keys.set_down(*key),
Event::KeyUp(key) => self.keys.set_up(*key),
Event::MouseButtonDown(button) => self.mouse_buttons.set_down(*button),
Event::MouseButtonUp(button) => self.mouse_buttons.set_up(*button),
Event::MouseMotion { new_position } => self.mouse_position = *new_position,
Event::ControllerDeviceAdded { joystick, gamepad } => {
let empty_slot = self.gamepads.iter().position(Option::is_none);

let gamepad_id = match empty_slot {
Some(slot) => {
self.gamepads[slot] = Some(gamepad.clone());
slot
}
}

SDL_KEYUP if event.key.repeat == 0 => {
if let Some(key) = Key::from_raw(event.key.keysym.scancode) {
self.keys.set_up(key);
}
}

SDL_MOUSEBUTTONDOWN => {
if let Some(button) = MouseButton::from_raw(event.button.button as u32) {
self.mouse_buttons.set_down(button);
None => {
self.gamepads.push(Some(gamepad.clone()));
self.gamepads.len() - 1
}
}

SDL_MOUSEBUTTONUP => {
if let Some(button) = MouseButton::from_raw(event.button.button as u32) {
self.mouse_buttons.set_up(button);
}
}

SDL_MOUSEMOTION => {
self.mouse_position = Vec2::new(event.motion.x as f32, event.motion.y as f32);
}

SDL_CONTROLLERDEVICEADDED => {
let handle = SDL_GameControllerOpen(event.cdevice.which);

if handle.is_null() {
// TODO: Should probably log here
return;
}

let joystick = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(handle));

let gamepad = Gamepad::from_raw(handle);

let mut empty_slot = None;
};

for (i, slot) in self.gamepads.iter_mut().enumerate() {
if slot.is_none() {
empty_slot = Some(i);
break;
}
}

let gamepad_id = match empty_slot {
Some(slot) => {
self.gamepads[slot] = Some(gamepad);
slot
}
None => {
self.gamepads.push(Some(gamepad));
self.gamepads.len() - 1
}
};

self.joystick_ids.insert(joystick, gamepad_id);
}

SDL_CONTROLLERDEVICEREMOVED => {
if let Some(gamepad_id) = self
.joystick_ids
.remove(&SDL_JoystickID(event.cdevice.which))
{
self.gamepads[gamepad_id] = None;
}
self.joystick_ids.insert(*joystick, gamepad_id);
}
Event::ControllerDeviceRemoved { joystick } => {
if let Some(gamepad_id) = self.joystick_ids.remove(joystick) {
self.gamepads[gamepad_id] = None;
}

SDL_CONTROLLERBUTTONDOWN => {
if let Some(button) = GamepadButton::from_raw(SDL_GameControllerButton(
event.cbutton.button as i32,
)) {
if let Some(gamepad_id) = self.joystick_ids.get(&event.cbutton.which) {
self.gamepad_buttons.set_down((*gamepad_id, button));
}
}
}
Event::ControllerButtonDown { joystick, button } => {
if let Some(gamepad_id) = self.joystick_ids.get(joystick) {
self.gamepad_buttons.set_down((*gamepad_id, *button));
}

SDL_CONTROLLERBUTTONUP => {
if let Some(button) = GamepadButton::from_raw(SDL_GameControllerButton(
event.cbutton.button as i32,
)) {
if let Some(gamepad_id) = self.joystick_ids.get(&event.cbutton.which) {
self.gamepad_buttons.set_up((*gamepad_id, button));
}
}
}
Event::ControllerButtonUp { joystick, button } => {
if let Some(gamepad_id) = self.joystick_ids.get(joystick) {
self.gamepad_buttons.set_up((*gamepad_id, *button));
}

SDL_CONTROLLERAXISMOTION => {
if let Some(axis) =
GamepadAxis::from_raw(SDL_GameControllerAxis(event.caxis.axis as i32))
{
if let Some(gamepad_id) = self.joystick_ids.get(&event.cbutton.which) {
let mut value = if event.caxis.value > 0 {
event.caxis.value as f32 / 32767.0
} else {
event.caxis.value as f32 / 32768.0
};

// TODO: Add less hacky deadzone logic
if value.abs() < 0.2 {
value = 0.0;
}

self.axes.set_value(*gamepad_id, axis, value);
}
}
}
Event::ControllerAxisMotion {
joystick,
axis,
value,
} => {
if let Some(gamepad_id) = self.joystick_ids.get(joystick) {
self.axes.set_value(*gamepad_id, *axis, *value);
}

_ => {}
}
}
}
Expand Down
Loading

0 comments on commit e3e6656

Please sign in to comment.