From 0cea5a0a9e5080cac2812910e918d93e40ba912e Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Sat, 24 Feb 2024 20:29:18 +0100 Subject: [PATCH] core: Introduce gamepad button mapping support --- core/src/events.rs | 26 ++++++++++++++++++++++++++ core/src/player.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/core/src/events.rs b/core/src/events.rs index 6e98984d0..a4604baef 100644 --- a/core/src/events.rs +++ b/core/src/events.rs @@ -30,6 +30,12 @@ pub enum PlayerEvent { MouseWheel { delta: MouseWheelDelta, }, + GamepadButtonDown { + button: GamepadButton, + }, + GamepadButtonUp { + button: GamepadButton, + }, TextInput { codepoint: char, }, @@ -381,6 +387,7 @@ impl TextControlCode { } /// Flash virtual keycode. +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)] pub enum KeyCode { Unknown = 0, @@ -674,3 +681,22 @@ pub fn key_code_to_button_key_code(key_code: KeyCode) -> Option { }; Some(out) } + +#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub enum GamepadButton { + South, + East, + North, + West, + LeftTrigger, + LeftTrigger2, + RightTrigger, + RightTrigger2, + Select, + Start, + DPadUp, + DPadDown, + DPadLeft, + DPadRight, +} diff --git a/core/src/player.rs b/core/src/player.rs index 71f9076d3..334286812 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -29,6 +29,7 @@ use crate::display_object::{ EditText, InteractiveObject, Stage, StageAlign, StageDisplayState, StageScaleMode, TInteractiveObject, WindowMode, }; +use crate::events::GamepadButton; use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode, MouseButton, PlayerEvent}; use crate::external::{ExternalInterface, ExternalInterfaceProvider, NullFsCommandProvider}; use crate::external::{FsCommandProvider, Value as ExternalValue}; @@ -356,6 +357,9 @@ pub struct Player { /// Any compatibility rules to apply for this movie. compatibility_rules: CompatibilityRules, + /// A map from gamepad buttons to key codes. + gamepad_button_mapping: HashMap, + /// Debug UI windows #[cfg(feature = "egui")] debug_ui: Rc>, @@ -842,6 +846,7 @@ impl Player { /// Event handling is a complicated affair, involving several different /// concerns that need to resolve with specific priority. /// + /// 0. Transform gamepad button events into key events. /// 1. (In `avm_debug` builds) /// If Ctrl-Alt-V is pressed, dump all AVM1 variables in the player. /// If Ctrl-Alt-D is pressed, toggle debug output for AVM1 and AVM2. @@ -861,6 +866,33 @@ impl Player { /// 8. Mouse state is updated. This triggers button rollovers, which are a /// second wave of event processing. pub fn handle_event(&mut self, event: PlayerEvent) { + // Optionally transform gamepad button events into key events. + let event = match event { + PlayerEvent::GamepadButtonDown { button } => { + if let Some(key_code) = self.gamepad_button_mapping.get(&button) { + PlayerEvent::KeyDown { + key_code: *key_code, + key_char: None, + } + } else { + // Just ignore this event. + return; + } + } + PlayerEvent::GamepadButtonUp { button } => { + if let Some(key_code) = self.gamepad_button_mapping.get(&button) { + PlayerEvent::KeyUp { + key_code: *key_code, + key_char: None, + } + } else { + // Just ignore this event. + return; + } + } + _ => event, + }; + let prev_is_mouse_down = self.input.is_mouse_down(); self.input.handle_event(&event); let is_mouse_button_changed = self.input.is_mouse_down() != prev_is_mouse_down; @@ -2113,6 +2145,7 @@ pub struct PlayerBuilder { load_behavior: LoadBehavior, spoofed_url: Option, compatibility_rules: CompatibilityRules, + gamepad_button_mapping: HashMap, player_version: Option, player_runtime: PlayerRuntime, quality: StageQuality, @@ -2163,6 +2196,7 @@ impl PlayerBuilder { load_behavior: LoadBehavior::Streaming, spoofed_url: None, compatibility_rules: CompatibilityRules::default(), + gamepad_button_mapping: HashMap::new(), player_version: None, player_runtime: PlayerRuntime::default(), quality: StageQuality::High, @@ -2362,6 +2396,11 @@ impl PlayerBuilder { self } + pub fn with_gamepad_button_mapping(mut self, mapping: HashMap) -> Self { + self.gamepad_button_mapping = mapping; + self + } + #[cfg(feature = "known_stubs")] /// Sets the output path for the stub report. When set, the player /// will write the report to this path and exit the process. @@ -2507,6 +2546,7 @@ impl PlayerBuilder { load_behavior: self.load_behavior, spoofed_url: self.spoofed_url.clone(), compatibility_rules: self.compatibility_rules.clone(), + gamepad_button_mapping: self.gamepad_button_mapping, stub_tracker: StubCollection::new(), #[cfg(feature = "egui")] debug_ui: Default::default(),