@@ -18,7 +18,7 @@ use input::{web_key_to_codepoint, web_to_ruffle_key_code, web_to_ruffle_text_con
1818use js_sys:: { Error as JsError , Uint8Array } ;
1919use ruffle_core:: context:: UpdateContext ;
2020use ruffle_core:: context_menu:: ContextMenuCallback ;
21- use ruffle_core:: events:: { MouseButton , MouseWheelDelta , TextControlCode } ;
21+ use ruffle_core:: events:: { GamepadButton , MouseButton , MouseWheelDelta , TextControlCode } ;
2222use ruffle_core:: tag_utils:: SwfMovie ;
2323use ruffle_core:: { Player , PlayerEvent , StaticCallstack , ViewportDimensions } ;
2424use ruffle_web_common:: JsResult ;
@@ -38,8 +38,8 @@ use wasm_bindgen::convert::FromWasmAbi;
3838use wasm_bindgen:: prelude:: * ;
3939use web_sys:: {
4040 AddEventListenerOptions , ClipboardEvent , Element , Event , EventTarget , FocusEvent ,
41- HtmlCanvasElement , HtmlElement , KeyboardEvent , Node , PointerEvent , ShadowRoot , WheelEvent ,
42- Window ,
41+ Gamepad as WebGamepad , GamepadButton as WebGamepadButton , HtmlCanvasElement , HtmlElement ,
42+ KeyboardEvent , Node , PointerEvent , ShadowRoot , WheelEvent , Window ,
4343} ;
4444
4545static RUFFLE_GLOBAL_PANIC : Once = Once :: new ( ) ;
@@ -140,6 +140,7 @@ struct RuffleInstance {
140140 has_focus : bool ,
141141 trace_observer : Rc < RefCell < JsValue > > ,
142142 log_subscriber : Arc < Layered < WASMLayer , Registry > > ,
143+ pressed_buttons : Vec < GamepadButton > ,
143144}
144145
145146#[ wasm_bindgen( raw_module = "./internal/player/inner" ) ]
@@ -508,6 +509,7 @@ impl RuffleHandle {
508509 has_focus : false ,
509510 trace_observer : player. trace_observer ,
510511 log_subscriber,
512+ pressed_buttons : vec ! [ ] ,
511513 } ;
512514
513515 // Prevent touch-scrolling on canvas.
@@ -1015,6 +1017,7 @@ impl RuffleHandle {
10151017 fn tick ( & mut self , timestamp : f64 ) {
10161018 let mut dt = 0.0 ;
10171019 let mut new_dimensions = None ;
1020+ let mut gamepad_button_events = Vec :: new ( ) ;
10181021 let _ = self . with_instance_mut ( |instance| {
10191022 // Check for canvas resize.
10201023 let canvas_width = instance. canvas . client_width ( ) ;
@@ -1043,6 +1046,60 @@ impl RuffleHandle {
10431046 ) ) ;
10441047 }
10451048
1049+ if let Ok ( gamepads) = instance. window . navigator ( ) . get_gamepads ( ) {
1050+ if let Some ( gamepad) = gamepads
1051+ . into_iter ( )
1052+ . next ( )
1053+ . and_then ( |gamepad| gamepad. dyn_into :: < WebGamepad > ( ) . ok ( ) )
1054+ {
1055+ let mut pressed_buttons = Vec :: new ( ) ;
1056+
1057+ let buttons = gamepad. buttons ( ) ;
1058+ for ( index, button) in buttons. into_iter ( ) . enumerate ( ) {
1059+ let Ok ( button) = button. dyn_into :: < WebGamepadButton > ( ) else {
1060+ continue ;
1061+ } ;
1062+
1063+ if !button. pressed ( ) {
1064+ continue ;
1065+ }
1066+
1067+ // See https://w3c.github.io/gamepad/#remapping
1068+ let gamepad_button = match index {
1069+ 0 => GamepadButton :: South ,
1070+ 1 => GamepadButton :: East ,
1071+ 2 => GamepadButton :: West ,
1072+ 3 => GamepadButton :: North ,
1073+ 12 => GamepadButton :: DPadUp ,
1074+ 13 => GamepadButton :: DPadDown ,
1075+ 14 => GamepadButton :: DPadLeft ,
1076+ 15 => GamepadButton :: DPadRight ,
1077+ _ => continue ,
1078+ } ;
1079+
1080+ pressed_buttons. push ( gamepad_button) ;
1081+ }
1082+
1083+ if pressed_buttons != instance. pressed_buttons {
1084+ for button in pressed_buttons. iter ( ) {
1085+ if !instance. pressed_buttons . contains ( button) {
1086+ gamepad_button_events
1087+ . push ( PlayerEvent :: GamepadButtonDown { button : * button } ) ;
1088+ }
1089+ }
1090+
1091+ for button in instance. pressed_buttons . iter ( ) {
1092+ if !pressed_buttons. contains ( button) {
1093+ gamepad_button_events
1094+ . push ( PlayerEvent :: GamepadButtonUp { button : * button } ) ;
1095+ }
1096+ }
1097+
1098+ instance. pressed_buttons = pressed_buttons;
1099+ }
1100+ }
1101+ }
1102+
10461103 // Request next animation frame.
10471104 if let Some ( handler) = & instance. animation_handler {
10481105 let id = instance
@@ -1065,6 +1122,10 @@ impl RuffleHandle {
10651122
10661123 // Tick the Ruffle core.
10671124 let _ = self . with_core_mut ( |core| {
1125+ for event in gamepad_button_events {
1126+ core. handle_event ( event) ;
1127+ }
1128+
10681129 if let Some ( ( ref canvas, viewport_width, viewport_height, device_pixel_ratio) ) =
10691130 new_dimensions
10701131 {
0 commit comments