fix(input): dedup de mandos, auto-assign per ordre i cycles sense col·lisió

This commit is contained in:
JailDesigner committed 2026-04-24 18:06:24 +02:00
1 parent e5b8d7731b
commit 996ff0053e
4 files changed
+111 -20

No files matched your search

+31 -16
View File
@@ -755,12 +755,31 @@ auto ServiceMenu::buildKeyboardControls() -> Page {
namespace {
// Índex del cycle per a un jugador donat. 0 = "Cap" (desassignat o
// sense coincidència amb cap mando connectat); 1..N = mando `idx-1`
// de la llista actual de `GamepadManager::getAll()`. La coincidència
// es fa primer per ruta (estable entre sessions) i si no, per nom.
// Mandos visibles al cycle d'un jugador: tots els connectats
// EXCEPTE els reclamats per l'altre jugador. Així l'usuari mai pot
// assignar el mateix mando a dos jugadors des de la UI — per
// reassignar-lo ha d'alliberar-lo primer posant-lo a "Cap" a l'altre
// slot. L'ordre de la llista manté el de `getAll()`.
auto visiblePads(int player_id) -> std::vector<GamepadManager::Info> {
const auto ALL = GamepadManager::get().getAll();
const auto& other = (player_id == 0) ? Options::controls().gamepad_p2
: Options::controls().gamepad_p1;
std::vector<GamepadManager::Info> out;
out.reserve(ALL.size());
for (const auto& p : ALL) {
const bool OWNED_BY_OTHER =
(!other.path.empty() && p.path == other.path) ||
(other.path.empty() && !other.name.empty() && p.name == other.name);
if (!OWNED_BY_OTHER) { out.push_back(p); }
}
return out;
}
// Índex del cycle dins de la llista `visiblePads(player_id)`.
// 0 = "Cap" (desassignat o sense coincidència amb cap mando visible);
// 1..N = mando `idx-1`. Primer match per ruta, fallback per nom.
auto currentPadIndex(int player_id) -> std::size_t {
const auto PADS = GamepadManager::get().getAll();
const auto PADS = visiblePads(player_id);
const auto& slot = (player_id == 0) ? Options::controls().gamepad_p1
: Options::controls().gamepad_p2;
if (slot.name.empty() && slot.path.empty()) { return 0; }
@@ -773,29 +792,25 @@ namespace {
return 0;
}
// Text visible per a cada índex del cycle. 0 → "Cap"; altrament
// el nom del mando. Si l'índex queda fora de rang (p.ex. un mando
// desenchufat just abans que es repinte el label) mostrem el nom
// persistit amb un sufix "(desconnectat)" per no deixar l'usuari
// sense feedback.
auto padLabel(int player_id, std::size_t idx) -> std::string {
if (idx == 0) { return Locale::get().text("menu.values.gamepad_none"); }
const auto PADS = GamepadManager::get().getAll();
const auto PADS = visiblePads(player_id);
const std::size_t POS = idx - 1;
if (POS < PADS.size()) { return PADS[POS].name; }
// Fora de rang: l'assignació guardada no és visible ara (p. ex.
// el mando s'acaba de desconnectar). Mostrem el nom persistit
// amb un sufix per no deixar l'usuari sense feedback.
const auto& slot = (player_id == 0) ? Options::controls().gamepad_p1
: Options::controls().gamepad_p2;
return slot.name + " (" + Locale::get().text("menu.values.gamepad_disconnected") + ')';
}
// Aplica la selecció del cycle: 0 desassigna, altres índexs vinculen
// el mando corresponent. Options persisteix i crida el GamepadManager.
void applyPadSelection(int player_id, std::size_t idx) {
if (idx == 0) {
Options::setGamepadAssignment(player_id, "", "");
return;
}
const auto PADS = GamepadManager::get().getAll();
const auto PADS = visiblePads(player_id);
const std::size_t POS = idx - 1;
if (POS >= PADS.size()) { return; }
Options::setGamepadAssignment(player_id, PADS[POS].name, PADS[POS].path);
@@ -814,14 +829,14 @@ auto ServiceMenu::buildGamepadControls() -> Page {
page.items.push_back(makeCycle(
"menu.items.gamepad_p1",
[]() { return currentPadIndex(0); },
[]() { return GamepadManager::get().getAll().size() + 1; },
[]() { return visiblePads(0).size() + 1; },
[](std::size_t idx) { applyPadSelection(0, idx); },
[](std::size_t idx) { return padLabel(0, idx); }));
page.items.push_back(makeCycle(
"menu.items.gamepad_p2",
[]() { return currentPadIndex(1); },
[]() { return GamepadManager::get().getAll().size() + 1; },
[]() { return visiblePads(1).size() + 1; },
[](std::size_t idx) { applyPadSelection(1, idx); },
[](std::size_t idx) { return padLabel(1, idx); }));