feat(service_menu): picker de mando per llista i fix SENSE MANDO
El cycle anterior fallava al desasignar perque Input::resolvePlayerGamepad tenia un fallback per slot que reasignava gamepads_[player_index] quan name+path eren buits. Això el contradeia el slot "SENSE MANDO" del cycle: el YAML quedava buit pero el runtime seguia lligant el mando. Treure el fallback i moure l'autoassignacio inicial al boot (nomes si tots dos jugadors venen buits) restaura la semàntica: buit vol dir buit. Sobre el fix, redissenyem la UX dels items MANDO P1/P2: ja no son CYCLE sino SUBMENU que obrin una pàgina-llista (estil RESOLUCIÓ) amb tots els mandos detectats. Cada item porta sufix (P1)/(P2) nomes si el mando el te l'altre jugador, perque sapigues que assignar-lo li'l "robarà". L'ultim item es "SENSE MANDO" per a desassignar explícitament. La lògica de swap automatic en conflicte queda extreta a assignPadToPlayer i es reutilitza des de la picker. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -503,10 +503,10 @@ auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std::
|
||||
|
||||
// ========== MÉTODOS ESPECÍFICOS POR JUGADOR (ORNI) ==========
|
||||
|
||||
// Cerca el gamepad assignat a un jugador. Prioritat: path > name > slot
|
||||
// per índex (fallback). Retorna nullptr si no n'hi ha cap de connectat.
|
||||
auto Input::resolvePlayerGamepad(const Config::PlayerBindings& bindings,
|
||||
std::size_t fallback_index) -> std::shared_ptr<Gamepad> {
|
||||
// Cerca el gamepad assignat a un jugador. Prioritat path > name. Si els
|
||||
// dos camps venen buits o no n'hi ha cap match retornem nullptr (sense
|
||||
// mando explicit). L'autoassignacio inicial es resol al boot.
|
||||
auto Input::resolvePlayerGamepad(const Config::PlayerBindings& bindings) -> std::shared_ptr<Gamepad> {
|
||||
if (gamepads_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -527,12 +527,6 @@ auto Input::resolvePlayerGamepad(const Config::PlayerBindings& bindings,
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: pad pel slot del jugador (P1=0, P2=1). Si no hi ha pad per al
|
||||
// slot, retornem nullptr en lloc de robar-li el pad a l'altre jugador.
|
||||
if (fallback_index < gamepads_.size() && bindings.gamepad_path.empty() && bindings.gamepad_name.empty()) {
|
||||
return gamepads_[fallback_index];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -545,8 +539,8 @@ void Input::applyPlayer1Bindings(const Config::PlayerBindings& bindings) {
|
||||
player1_keyboard_bindings_[Action::SHOOT].scancode = bindings.keyboard.key_shoot;
|
||||
player1_keyboard_bindings_[Action::START].scancode = bindings.keyboard.key_start;
|
||||
|
||||
// 2. Resoldre gamepad per path/name/slot
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings, 0);
|
||||
// 2. Resoldre gamepad per path/name
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings);
|
||||
|
||||
if (!gamepad) {
|
||||
player1_gamepad_ = nullptr;
|
||||
@@ -574,8 +568,8 @@ void Input::applyPlayer2Bindings(const Config::PlayerBindings& bindings) {
|
||||
player2_keyboard_bindings_[Action::SHOOT].scancode = bindings.keyboard.key_shoot;
|
||||
player2_keyboard_bindings_[Action::START].scancode = bindings.keyboard.key_start;
|
||||
|
||||
// 2. Resoldre gamepad per path/name/slot
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings, 1);
|
||||
// 2. Resoldre gamepad per path/name
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings);
|
||||
|
||||
if (!gamepad) {
|
||||
player2_gamepad_ = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user