Bind a gamepad confirm button — ui_accept had none by default

Siim reported gamepad menu navigation works but pressing a button
does nothing. Checked Godot's actual built-in ui_accept bindings
directly: only Enter/Kp Enter/Space — no joypad button at all. That's
why D-pad/stick focus movement (ui_left/right/up/down do default to
gamepad input) worked while "confirm" never could, on any controller.

Binds both the Xbox-style bottom face button (A, index 0) and the
right-hand one (B, index 1 — physically labelled "A" on a
Nintendo-layout pad, since gamepad mapping normalizes to Xbox
*position* rather than the printed label), so either common "confirm"
button activates the focused menu/end-screen button.

Verified headlessly end-to-end: a synthetic joypad button 0 or button
1 press on the focused end-screen button now reloads the run, matching
what a real gamepad press should do.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MXBNaEBmrYDSMcv4NgUWtV
This commit is contained in:
2026-09-10 19:05:55 +03:00
parent 56a4965ff7
commit d5c6b749d0
+16
View File
@@ -22,10 +22,26 @@ const REBINDABLE_ACTIONS: PackedStringArray = [
func _ready() -> void:
_ensure_gamepad_confirm_binding()
load_saved()
_install_web_fullscreen_hook()
## Godot's built-in ui_accept (menu/button confirm) ships with zero joypad bindings —
## checked directly: only Enter/Kp Enter/Space. ui_left/right/up/down, by contrast, do
## default to the D-pad and stick, which is why gamepad focus navigation on a menu works out
## of the box while "confirming" the focused button does nothing. Bind both the Xbox-style
## bottom face button (A, index 0) and the right-hand one (B, index 1 — physically labelled
## "A" on a Nintendo-layout pad, since SDL/browser gamepad mapping normalizes to Xbox
## *position*, not the printed label) so either the common "confirm" button works.
func _ensure_gamepad_confirm_binding() -> void:
for button_index in [JOY_BUTTON_A, JOY_BUTTON_B]:
var alt := InputEventJoypadButton.new()
alt.button_index = button_index
if not InputMap.action_has_event(&"ui_accept", alt):
InputMap.action_add_event(&"ui_accept", alt)
# ── Web fullscreen + landscape lock ─────────────────────────────────────────────
# The reliable way to force fullscreen on the web: install a NATIVE DOM listener that calls
# requestFullscreen() synchronously inside the real user-gesture event — the same thing