feat(gamepad): detecció i notificacions hot-plug amb GamepadManager

This commit is contained in:
JailDesigner committed 2026-04-22 19:39:16 +02:00
1 parent be9309d342
commit 7c35ffaa74
9 files changed
+305 -15

No files matched your search

+39 -4
View File
@@ -12,6 +12,7 @@
#include <utility>
#include "core/audio/audio.hpp"
#include "core/input/gamepad_manager.hpp"
#include "core/input/key_config.hpp"
#include "core/locale/locale.hpp"
#include "core/rendering/notifier.hpp"
@@ -102,6 +103,11 @@ Director::Director() {
// JA_Music_t que continga, així que no queden streams orfes.
Audio::init(Options::buildAudioConfig());
// Gamepad: descobreix mandos presents silenciosament. A partir d'ara
// els events SDL_EVENT_GAMEPAD_ADDED/REMOVED arribaran via
// `processGamepadEvents()` i dispararan notificacions.
GamepadManager::get().init();
// Font compartida pels overlays: construïm una sola instància de Text
// i la injectem als consumidors (Notifier, RenderInfo) per a que cap
// d'ells hagi de conèixer els noms dels recursos concrets.
@@ -200,6 +206,7 @@ Director::~Director() {
// desfà les llibreries abans que corren els destructors estàtics.
current_scene_.reset();
Resource::Cache::get().clearAudio();
GamepadManager::get().shutdown();
Audio::destroy();
Screen::get().shutdown();
SDL_Quit();
@@ -235,6 +242,32 @@ void Director::processEvents() {
if (QUIT_REQUESTED) { current_scene_.reset(); }
}
void Director::processGamepadEvents() {
// Dues responsabilitats: (1) passar ADDED/REMOVED al GamepadManager
// perquè obri/tanqui mandos i emeti les notificacions hot-plug; (2)
// tractar el botó BACK com a toggle del menú quan està tancat (el
// paral·lel de F9 per al teclat). Quan el menú està obert, el BACK
// passa pel pipeline del `ServiceMenu::handleEvent()` via
// `processMenuInput()` i allà es converteix en `close()`.
for (auto it = EventBuffer::events.begin(); it != EventBuffer::events.end();) {
bool consumed = false;
if (it->type == SDL_EVENT_GAMEPAD_ADDED || it->type == SDL_EVENT_GAMEPAD_REMOVED) {
GamepadManager::get().handleEvent(*it);
consumed = true;
} else if (it->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN &&
it->gbutton.button == SDL_GAMEPAD_BUTTON_BACK &&
!ServiceMenu::get().isOpen()) {
ServiceMenu::get().toggle();
consumed = true;
}
if (consumed) {
it = EventBuffer::events.erase(it);
} else {
++it;
}
}
}
void Director::processMenuInput() {
// Intercepta input abans que l'escena vegi els events. Si el menú està
// obert, consumeix TOTS els KEY_DOWN perquè ni GlobalInputs (F1–F8,
@@ -263,10 +296,12 @@ void Director::switchSceneIfRequested() {
}
auto Director::iterate() -> SDL_AppResult {
// Ordre important: primer el menú (pot consumir tecles i INJECTAR un
// SDL_EVENT_QUIT des de l'acció "Eixir del joc"), després processEvents
// perquè vegi el QUIT al mateix frame i tanqui l'escena — altrament el
// QUIT injectat es perdria quan es netegi EventBuffer al final d'iterate.
// Ordre important: primer els events de gamepad (hot-plug + BACK que
// obre el menú quan està tancat), després el menú (pot consumir tecles
// i INJECTAR un SDL_EVENT_QUIT des de l'acció "Eixir del joc"), i
// finalment processEvents perquè vegi el QUIT al mateix frame — altrament
// el QUIT injectat es perdria quan es netegi EventBuffer al final.
processGamepadEvents();
processMenuInput();
processEvents();