78 lines
2.9 KiB
C++
78 lines
2.9 KiB
C++
#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};
|
|
};
|