From d5c6b749d05030c781bbb31be7fbcda6587baec9 Mon Sep 17 00:00:00 2001 From: Richard Aasa Date: Thu, 10 Sep 2026 19:05:55 +0300 Subject: [PATCH] =?UTF-8?q?Bind=20a=20gamepad=20confirm=20button=20?= =?UTF-8?q?=E2=80=94=20ui=5Faccept=20had=20none=20by=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01MXBNaEBmrYDSMcv4NgUWtV --- systems/input/controls_manager.gd | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/systems/input/controls_manager.gd b/systems/input/controls_manager.gd index 8e1a7ea..4e4d3fe 100644 --- a/systems/input/controls_manager.gd +++ b/systems/input/controls_manager.gd @@ -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