core: Introduce gamepad button mapping support
This commit is contained in:
parent
9bc6700531
commit
0cea5a0a9e
|
@ -30,6 +30,12 @@ pub enum PlayerEvent {
|
||||||
MouseWheel {
|
MouseWheel {
|
||||||
delta: MouseWheelDelta,
|
delta: MouseWheelDelta,
|
||||||
},
|
},
|
||||||
|
GamepadButtonDown {
|
||||||
|
button: GamepadButton,
|
||||||
|
},
|
||||||
|
GamepadButtonUp {
|
||||||
|
button: GamepadButton,
|
||||||
|
},
|
||||||
TextInput {
|
TextInput {
|
||||||
codepoint: char,
|
codepoint: char,
|
||||||
},
|
},
|
||||||
|
@ -381,6 +387,7 @@ impl TextControlCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flash virtual keycode.
|
/// Flash virtual keycode.
|
||||||
|
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
|
||||||
pub enum KeyCode {
|
pub enum KeyCode {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
|
@ -674,3 +681,22 @@ pub fn key_code_to_button_key_code(key_code: KeyCode) -> Option<ButtonKeyCode> {
|
||||||
};
|
};
|
||||||
Some(out)
|
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,
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use crate::display_object::{
|
||||||
EditText, InteractiveObject, Stage, StageAlign, StageDisplayState, StageScaleMode,
|
EditText, InteractiveObject, Stage, StageAlign, StageDisplayState, StageScaleMode,
|
||||||
TInteractiveObject, WindowMode,
|
TInteractiveObject, WindowMode,
|
||||||
};
|
};
|
||||||
|
use crate::events::GamepadButton;
|
||||||
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode, MouseButton, PlayerEvent};
|
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode, MouseButton, PlayerEvent};
|
||||||
use crate::external::{ExternalInterface, ExternalInterfaceProvider, NullFsCommandProvider};
|
use crate::external::{ExternalInterface, ExternalInterfaceProvider, NullFsCommandProvider};
|
||||||
use crate::external::{FsCommandProvider, Value as ExternalValue};
|
use crate::external::{FsCommandProvider, Value as ExternalValue};
|
||||||
|
@ -356,6 +357,9 @@ pub struct Player {
|
||||||
/// Any compatibility rules to apply for this movie.
|
/// Any compatibility rules to apply for this movie.
|
||||||
compatibility_rules: CompatibilityRules,
|
compatibility_rules: CompatibilityRules,
|
||||||
|
|
||||||
|
/// A map from gamepad buttons to key codes.
|
||||||
|
gamepad_button_mapping: HashMap<GamepadButton, KeyCode>,
|
||||||
|
|
||||||
/// Debug UI windows
|
/// Debug UI windows
|
||||||
#[cfg(feature = "egui")]
|
#[cfg(feature = "egui")]
|
||||||
debug_ui: Rc<RefCell<crate::debug_ui::DebugUi>>,
|
debug_ui: Rc<RefCell<crate::debug_ui::DebugUi>>,
|
||||||
|
@ -842,6 +846,7 @@ impl Player {
|
||||||
/// Event handling is a complicated affair, involving several different
|
/// Event handling is a complicated affair, involving several different
|
||||||
/// concerns that need to resolve with specific priority.
|
/// concerns that need to resolve with specific priority.
|
||||||
///
|
///
|
||||||
|
/// 0. Transform gamepad button events into key events.
|
||||||
/// 1. (In `avm_debug` builds)
|
/// 1. (In `avm_debug` builds)
|
||||||
/// If Ctrl-Alt-V is pressed, dump all AVM1 variables in the player.
|
/// 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.
|
/// 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
|
/// 8. Mouse state is updated. This triggers button rollovers, which are a
|
||||||
/// second wave of event processing.
|
/// second wave of event processing.
|
||||||
pub fn handle_event(&mut self, event: PlayerEvent) {
|
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();
|
let prev_is_mouse_down = self.input.is_mouse_down();
|
||||||
self.input.handle_event(&event);
|
self.input.handle_event(&event);
|
||||||
let is_mouse_button_changed = self.input.is_mouse_down() != prev_is_mouse_down;
|
let is_mouse_button_changed = self.input.is_mouse_down() != prev_is_mouse_down;
|
||||||
|
@ -2113,6 +2145,7 @@ pub struct PlayerBuilder {
|
||||||
load_behavior: LoadBehavior,
|
load_behavior: LoadBehavior,
|
||||||
spoofed_url: Option<String>,
|
spoofed_url: Option<String>,
|
||||||
compatibility_rules: CompatibilityRules,
|
compatibility_rules: CompatibilityRules,
|
||||||
|
gamepad_button_mapping: HashMap<GamepadButton, KeyCode>,
|
||||||
player_version: Option<u8>,
|
player_version: Option<u8>,
|
||||||
player_runtime: PlayerRuntime,
|
player_runtime: PlayerRuntime,
|
||||||
quality: StageQuality,
|
quality: StageQuality,
|
||||||
|
@ -2163,6 +2196,7 @@ impl PlayerBuilder {
|
||||||
load_behavior: LoadBehavior::Streaming,
|
load_behavior: LoadBehavior::Streaming,
|
||||||
spoofed_url: None,
|
spoofed_url: None,
|
||||||
compatibility_rules: CompatibilityRules::default(),
|
compatibility_rules: CompatibilityRules::default(),
|
||||||
|
gamepad_button_mapping: HashMap::new(),
|
||||||
player_version: None,
|
player_version: None,
|
||||||
player_runtime: PlayerRuntime::default(),
|
player_runtime: PlayerRuntime::default(),
|
||||||
quality: StageQuality::High,
|
quality: StageQuality::High,
|
||||||
|
@ -2362,6 +2396,11 @@ impl PlayerBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_gamepad_button_mapping(mut self, mapping: HashMap<GamepadButton, KeyCode>) -> Self {
|
||||||
|
self.gamepad_button_mapping = mapping;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "known_stubs")]
|
#[cfg(feature = "known_stubs")]
|
||||||
/// Sets the output path for the stub report. When set, the player
|
/// Sets the output path for the stub report. When set, the player
|
||||||
/// will write the report to this path and exit the process.
|
/// will write the report to this path and exit the process.
|
||||||
|
@ -2507,6 +2546,7 @@ impl PlayerBuilder {
|
||||||
load_behavior: self.load_behavior,
|
load_behavior: self.load_behavior,
|
||||||
spoofed_url: self.spoofed_url.clone(),
|
spoofed_url: self.spoofed_url.clone(),
|
||||||
compatibility_rules: self.compatibility_rules.clone(),
|
compatibility_rules: self.compatibility_rules.clone(),
|
||||||
|
gamepad_button_mapping: self.gamepad_button_mapping,
|
||||||
stub_tracker: StubCollection::new(),
|
stub_tracker: StubCollection::new(),
|
||||||
#[cfg(feature = "egui")]
|
#[cfg(feature = "egui")]
|
||||||
debug_ui: Default::default(),
|
debug_ui: Default::default(),
|
||||||
|
|
Loading…
Reference in New Issue