feat(gamepad): detecció i notificacions hot-plug amb GamepadManager
This commit is contained in:
1 parent
be9309d342
commit
7c35ffaa74
9 files changed
+305
-15
No files matched your search
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Gestor global de gamepads. Descobreix els mandos presents a `init()`
|
||||
// sense emetre notificacions (el jugador ja els té posats al llançar el
|
||||
// joc). Durant el runtime, `handleEvent()` processa els events de hot-plug
|
||||
// i emet notificacions visibles via `Notification::notify`.
|
||||
//
|
||||
// El polling real de botons i eixos NO es fa a través d'aquesta classe:
|
||||
// els consumidors obtenen el `SDL_Gamepad*` primari (o l'enèsim per a
|
||||
// multi-jugador futur) i el passen a `InputState::getGamepadButton/Axis`,
|
||||
// que ho filtra pel flag de bloqueig de la UI (mateixa estratègia que
|
||||
// amb el teclat).
|
||||
class GamepadManager {
|
||||
public:
|
||||
static auto get() -> GamepadManager&;
|
||||
|
||||
GamepadManager(const GamepadManager&) = delete;
|
||||
GamepadManager(GamepadManager&&) = delete;
|
||||
auto operator=(const GamepadManager&) -> GamepadManager& = delete;
|
||||
auto operator=(GamepadManager&&) -> GamepadManager& = delete;
|
||||
|
||||
// Inicialitza el subsistema SDL de gamepad, intenta carregar un
|
||||
// `gamecontrollerdb.txt` opcional i obri silenciosament tots els
|
||||
// mandos ja connectats. Cridat una sola vegada des de Director.
|
||||
void init();
|
||||
|
||||
// Tanca tots els gamepads oberts i treu el subsistema SDL. Cridat
|
||||
// des de `~Director` abans de `SDL_Quit` per evitar handles orfes.
|
||||
void shutdown();
|
||||
|
||||
// Processa SDL_EVENT_GAMEPAD_ADDED i SDL_EVENT_GAMEPAD_REMOVED
|
||||
// emesos durant el runtime. Emet notificacions "<nom> connectat" o
|
||||
// "<nom> desconnectat". El Director decideix quins events li arriben
|
||||
// via `processGamepadEvents()`.
|
||||
void handleEvent(const SDL_Event& ev);
|
||||
|
||||
// Primary = primer gamepad al vector. `nullptr` si no n'hi ha cap.
|
||||
// Ús típic: Player 1 i navegació del ServiceMenu.
|
||||
[[nodiscard]] auto getPrimary() const -> SDL_Gamepad*;
|
||||
|
||||
[[nodiscard]] auto getCount() const -> std::size_t;
|
||||
|
||||
// Retorna el mand del jugador `idx`-èsim (0-indexed) o `nullptr` si
|
||||
// encara no hi ha prou mandos connectats. Reservat per a multi-jugador.
|
||||
[[nodiscard]] auto getByPlayerIndex(std::size_t idx) const -> SDL_Gamepad*;
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
SDL_Gamepad* pad{nullptr};
|
||||
SDL_JoystickID instance_id{0};
|
||||
std::string pretty_name;
|
||||
};
|
||||
|
||||
GamepadManager() = default;
|
||||
~GamepadManager() = default;
|
||||
|
||||
// Retalla `raw` al primer '(' o '[', elimina espais finals i talla
|
||||
// a 25 caràcters. Fallback "Gamepad" si queda buit.
|
||||
[[nodiscard]] static auto prettyName(const char* raw) -> std::string;
|
||||
|
||||
// Si `base` ja existeix al vector, afegeix " #2", " #3", ... fins que
|
||||
// trobi un nom lliure. Així dos mandos idèntics es distingeixen a les
|
||||
// notificacions.
|
||||
[[nodiscard]] auto uniqueName(const std::string& base) const -> std::string;
|
||||
|
||||
void addGamepad(SDL_JoystickID jid, bool notify);
|
||||
void removeGamepad(SDL_JoystickID jid);
|
||||
|
||||
std::vector<Entry> entries_;
|
||||
bool initialized_{false};
|
||||
};
|
||||
Reference in new issue
Block a user