From 975490e4e4283188cce4bf754af0e0f5c959e641 Mon Sep 17 00:00:00 2001 From: David Spies Date: Thu, 8 Jan 2026 12:55:50 -0800 Subject: [PATCH 1/2] Add gamepad support --- js/gl.js | 33 ++++++++++++++++++++++++++++++++- src/native/wasm.rs | 13 +++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/js/gl.js b/js/gl.js index df0116ac..6ddb709a 100644 --- a/js/gl.js +++ b/js/gl.js @@ -1458,7 +1458,38 @@ var importObject = { } animation_frame_timeout = window.requestAnimationFrame(animation); }, - init_webgl + init_webgl, + + // Gamepad support (W3C Gamepad API) + // https://w3c.github.io/gamepad/#remapping + sapp_gamepad_count: function() { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + var count = 0; + for (var i = 0; i < gamepads.length && i < 4; i++) { + if (gamepads[i]) count = i + 1; + } + return count; + }, + sapp_gamepad_connected: function(id) { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + if (id < 0 || id >= gamepads.length) return 0; + var gp = gamepads[id]; + return (gp && gp.connected) ? 1 : 0; + }, + sapp_gamepad_button: function(id, btn) { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + if (id < 0 || id >= gamepads.length) return 0; + var gp = gamepads[id]; + if (!gp || !gp.connected || btn < 0 || btn >= gp.buttons.length) return 0; + return gp.buttons[btn].pressed ? 1 : 0; + }, + sapp_gamepad_axis: function(id, axis) { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + if (id < 0 || id >= gamepads.length) return 0.0; + var gp = gamepads[id]; + if (!gp || !gp.connected || axis < 0 || axis >= gp.axes.length) return 0.0; + return gp.axes[axis]; + } } }; diff --git a/src/native/wasm.rs b/src/native/wasm.rs index 6ac297e5..34dbfca6 100644 --- a/src/native/wasm.rs +++ b/src/native/wasm.rs @@ -138,6 +138,19 @@ extern "C" { pub fn sapp_schedule_update(); pub fn init_webgl(version: i32); pub fn now() -> f64; + + // Gamepad support (W3C Gamepad API) + // https://w3c.github.io/gamepad/#remapping + /// Returns the number of connected gamepads (0-4). + pub fn sapp_gamepad_count() -> i32; + /// Returns 1 if gamepad at index is connected, 0 otherwise. + pub fn sapp_gamepad_connected(id: i32) -> i32; + /// Returns 1 if button is pressed, 0 otherwise. + /// Button indices follow W3C standard gamepad mapping. + pub fn sapp_gamepad_button(id: i32, btn: i32) -> i32; + /// Returns axis value (-1.0 to 1.0). + /// Axis indices: 0=LeftX, 1=LeftY, 2=RightX, 3=RightY + pub fn sapp_gamepad_axis(id: i32, axis: i32) -> f32; } unsafe fn show_mouse(shown: bool) { From 376b202f9c965f269369ca3f385d7a8e1d2dd7ff Mon Sep 17 00:00:00 2001 From: David Spies Date: Thu, 8 Jan 2026 13:27:49 -0800 Subject: [PATCH 2/2] Clarify weird behavior in docs --- js/gl.js | 1 + src/native/wasm.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/js/gl.js b/js/gl.js index 6ddb709a..b0799e08 100644 --- a/js/gl.js +++ b/js/gl.js @@ -1462,6 +1462,7 @@ var importObject = { // Gamepad support (W3C Gamepad API) // https://w3c.github.io/gamepad/#remapping + // Returns highest occupied gamepad slot + 1 (not count of connected gamepads) sapp_gamepad_count: function() { var gamepads = navigator.getGamepads ? navigator.getGamepads() : []; var count = 0; diff --git a/src/native/wasm.rs b/src/native/wasm.rs index 34dbfca6..5ad61636 100644 --- a/src/native/wasm.rs +++ b/src/native/wasm.rs @@ -141,7 +141,8 @@ extern "C" { // Gamepad support (W3C Gamepad API) // https://w3c.github.io/gamepad/#remapping - /// Returns the number of connected gamepads (0-4). + /// Returns the number of gamepad slots to check (0-4). + /// This is the highest occupied index + 1, not the count of connected gamepads. pub fn sapp_gamepad_count() -> i32; /// Returns 1 if gamepad at index is connected, 0 otherwise. pub fn sapp_gamepad_connected(id: i32) -> i32;