From 10bed1087ab040aaddf5e13634589271bdb390c9 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Mon, 11 May 2020 20:18:42 +0300 Subject: [PATCH] Add analogue stick support for controllers in SDL2 Former-commit-id: b3ccff53ded59930a0fe997f1bbbf83fd5e356d8 Former-commit-id: c3c286d1fccf6d9fc5478cd9f6b13d6a7d670b4b --- platform/rustboyadvance-sdl2/src/input.rs | 32 +++++++++++++++++++++-- platform/rustboyadvance-sdl2/src/main.rs | 14 ++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/platform/rustboyadvance-sdl2/src/input.rs b/platform/rustboyadvance-sdl2/src/input.rs index 407ddf6..ad524dc 100644 --- a/platform/rustboyadvance-sdl2/src/input.rs +++ b/platform/rustboyadvance-sdl2/src/input.rs @@ -1,5 +1,6 @@ -use sdl2::keyboard::Scancode; +use sdl2::controller::Axis; use sdl2::controller::Button; +use sdl2::keyboard::Scancode; use rustboyadvance_core::keypad as gba_keypad; use rustboyadvance_core::InputInterface; @@ -9,11 +10,12 @@ use bit::BitIndex; pub struct Sdl2Input { keyinput: u16, + axis_keyinput: u16, } impl InputInterface for Sdl2Input { fn poll(&mut self) -> u16 { - self.keyinput + !(!self.keyinput | !self.axis_keyinput) } } @@ -41,6 +43,31 @@ impl Sdl2Input { self.keyinput.set_bit(key as usize, true); } } + + pub fn on_axis_motion(&mut self, axis: Axis, val: i16) { + use gba_keypad::Keys as GbaKeys; + let keys = match axis { + Axis::LeftX => (GbaKeys::Left, GbaKeys::Right), + Axis::LeftY => (GbaKeys::Up, GbaKeys::Down), + Axis::TriggerLeft => (GbaKeys::ButtonL, GbaKeys::ButtonL), + Axis::TriggerRight => (GbaKeys::ButtonR, GbaKeys::ButtonR), + _ => { + return; + } + }; + + // Axis motion is an absolute value in the range + // [-32768, 32767]. Let's simulate a very rough dead + // zone to ignore spurious events. + let dead_zone = 10_000; + if val > dead_zone || val < -dead_zone { + let key = if val < 0 { keys.0 } else { keys.1 }; + self.axis_keyinput.set_bit(key as usize, false); + } else { + self.axis_keyinput.set_bit(keys.0 as usize, true); + self.axis_keyinput.set_bit(keys.1 as usize, true); + } + } } fn scancode_to_keypad(scancode: Scancode) -> Option { @@ -78,5 +105,6 @@ fn controller_button_to_keypad(button: Button) -> Option { pub fn create_input() -> Sdl2Input { Sdl2Input { keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, + axis_keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, } } diff --git a/platform/rustboyadvance-sdl2/src/main.rs b/platform/rustboyadvance-sdl2/src/main.rs index 17011db..6e8ada0 100644 --- a/platform/rustboyadvance-sdl2/src/main.rs +++ b/platform/rustboyadvance-sdl2/src/main.rs @@ -193,7 +193,8 @@ fn main() -> Result<(), Box> { canvas.set_logical_size(CANVAS_WIDTH, CANVAS_HEIGHT)?; let controller_subsystem = sdl_context.game_controller()?; - let controller_mappings = include_str!("../../../external/SDL_GameControllerDB/gamecontrollerdb.txt"); + let controller_mappings = + include_str!("../../../external/SDL_GameControllerDB/gamecontrollerdb.txt"); controller_subsystem.load_mappings_from_read(&mut Cursor::new(controller_mappings))?; let available_controllers = (0..controller_subsystem.num_joysticks()?) @@ -205,11 +206,11 @@ fn main() -> Result<(), Box> { let controller = controller_subsystem.open(id)?; info!("Found game controller: {}", controller.name()); Some(controller) - }, + } _ => { info!("No game controllers were found"); None - }, + } }; let mut rom_path = match matches.value_of("game_rom") { @@ -320,10 +321,13 @@ fn main() -> Result<(), Box> { }, Event::ControllerButtonDown { button, .. } => { input.borrow_mut().on_controller_button_down(button); - }, + } Event::ControllerButtonUp { button, .. } => { input.borrow_mut().on_controller_button_up(button); - }, + } + Event::ControllerAxisMotion { axis, value, .. } => { + input.borrow_mut().on_axis_motion(axis, value); + } Event::Quit { .. } => break 'running, Event::DropFile { filename, .. } => { // load the new rom