feat(input): assignació mando↔jugador persistida a config.yaml

This commit is contained in:
JailDesigner committed 2026-04-24 15:13:44 +02:00
1 parent 4e9d5df872
commit a725b76684
5 files changed
+226 -13

No files matched your search

+52 -3
View File
@@ -2,6 +2,7 @@
#include <SDL3/SDL.h>
#include <array>
#include <cstddef>
#include <string>
#include <vector>
@@ -41,22 +42,70 @@ class GamepadManager {
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.
// Ús típic: navegació del ServiceMenu. Per al gameplay els jugadors
// usen `getForPlayer(id)`.
[[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.
// Retorna el mand del jugador `idx`-èsim (0-indexed) en l'ordre de
// connexió. Per al gameplay, `getForPlayer` fa servir l'assignació
// persistida, no l'ordre de connexió.
[[nodiscard]] auto getByPlayerIndex(std::size_t idx) const -> SDL_Gamepad*;
// Informació exposada al menú de servei (llista de mandos
// disponibles). `path` pot estar buit si SDL no l'exposa (p. ex. a
// alguns backends web).
struct Info {
SDL_Gamepad* pad{nullptr};
std::string name;
std::string path;
};
[[nodiscard]] auto getAll() const -> std::vector<Info>;
// Retorna el mand assignat al jugador `player_id` (0 = P1, 1 = P2)
// o `nullptr` si no n'hi ha cap. L'assignació la fixa
// `assignToPlayer` (cridat per Options en carregar `config.yaml` o
// des del ServiceMenu quan l'usuari tria un mando).
[[nodiscard]] auto getForPlayer(int player_id) const -> SDL_Gamepad*;
// Assigna un mando per nom + ruta física. Si ja hi ha un mando
// connectat que coincideix per ruta (o per nom com a fallback), el
// vincula immediatament; si no, l'assignació queda pendent i
// s'aplicarà si el mando es connecta més tard (hot-plug).
// Política last-wins: si l'altre jugador tenia el mateix mando
// vinculat, se'l desvincula silenciosament.
void assignToPlayer(int player_id, const std::string& name, const std::string& path);
// Esborra l'assignació (per si l'usuari trie "Cap" al menú).
void unassignFromPlayer(int player_id);
private:
struct Entry {
SDL_Gamepad* pad{nullptr};
SDL_JoystickID instance_id{0};
std::string pretty_name;
std::string path;
};
// Assignació persistent per jugador. `name` i `path` venen d'Options
// (o del menú de servei) i poden referenciar un mando encara no
// connectat; en aquest cas `pad` és `nullptr` i el hot-plug el
// vincularà quan aparegui.
struct Assignment {
std::string name;
std::string path;
SDL_Gamepad* pad{nullptr};
};
static constexpr int MAX_PLAYERS = 2;
std::array<Assignment, MAX_PLAYERS> assignments_{};
// Busca a `entries_` el millor match per a una assignació (primer
// per path, després per nom). Retorna l'iterador o `entries_.end()`.
// També accepta assignar `path` nou si ha coincidit per nom
// (cas mando reenchufat a un altre port USB).
void rebindAssignment(Assignment& a);
GamepadManager() = default;
~GamepadManager() = default;