diff --git a/source/input.h b/source/input.h index 387cf8b..1677c09 100644 --- a/source/input.h +++ b/source/input.h @@ -92,12 +92,14 @@ class Input { SDL_Gamepad *pad; SDL_JoystickID instance_id; std::string name; + std::string path; std::unordered_map bindings; Gamepad(SDL_Gamepad *gamepad) : pad(gamepad), instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))), name(std::string(SDL_GetGamepadName(gamepad))), + path(std::string(SDL_GetGamepadPath(pad))), bindings{ // Movimiento del jugador {Action::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)}, diff --git a/source/options.cpp b/source/options.cpp index 4ff87e7..5a7a824 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -294,33 +294,34 @@ std::string getGamepadInfo(Player::Id player_id) { } } -// Asigna los mandos físicos basándose en la configuración actual de nombres. +// Asigna los mandos físicos basándose en la configuración actual. void GamepadManager::assignAndLinkGamepads() { // 1. Obtenemos todos los mandos físicos que están conectados ahora mismo. auto physical_gamepads = Input::get()->getGamepads(); - // 2. Reiniciamos las asignaciones actuales y guardamos los nombres que teníamos en la config. - std::array desired_names; + // 2. Reiniciamos las asignaciones actuales y guardamos los datos deseados de la config. + std::array desired_paths; // <--- CAMBIO: Guardamos las rutas deseadas. for (size_t i = 0; i < MAX_PLAYERS; ++i) { - desired_names[i] = gamepads[i].name; // Guardamos el nombre deseado - gamepads[i].instance = nullptr; // Limpiamos la instancia + desired_paths[i] = gamepads[i].path; // <--- CAMBIO: Obtenemos la ruta. + gamepads[i].instance = nullptr; // Limpiamos la instancia } // 3. Vector para rastrear los mandos físicos que ya hemos asignado. std::vector> assigned_instances; - // --- PRIMERA PASADA: Buscar coincidencias exactas por nombre --- - // Recorremos la configuración de nuestros jugadores (P1, P2). + // --- PRIMERA PASADA: Buscar coincidencias exactas por RUTA (path) --- + // Este es el método más fiable para identificar un mando de forma única. for (size_t i = 0; i < MAX_PLAYERS; ++i) { - const std::string& desired_name = desired_names[i]; - if (desired_name.empty()) { - continue; // Si no se pide un nombre específico, pasamos a la siguiente fase. + const std::string& desired_path = desired_paths[i]; // <--- CAMBIO: Usamos la ruta. + if (desired_path.empty()) { + continue; // Si no hay una ruta guardada para este slot, lo saltamos. } - // Buscamos un mando físico que coincida con el nombre deseado. + // Buscamos un mando físico que coincida con la ruta deseada. for (const auto& physical_gamepad : physical_gamepads) { - if (physical_gamepad->name == desired_name) { - // ¡Coincidencia! Ahora, comprobamos que no lo hayamos asignado ya. + if (physical_gamepad->path == desired_path) { // <--- CAMBIO: Comparamos por ruta. + // ¡Coincidencia por ruta! Es casi seguro que es el mando correcto. + // La comprobación de 'already_assigned' es una seguridad extra. bool already_assigned = false; for (const auto& assigned : assigned_instances) { if (assigned == physical_gamepad) { @@ -330,18 +331,19 @@ void GamepadManager::assignAndLinkGamepads() { } if (!already_assigned) { - gamepads[i].instance = physical_gamepad; // Enlazamos la instancia - assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado - break; // Mando encontrado para este jugador, pasamos al siguiente. + gamepads[i].instance = physical_gamepad; // Enlazamos la instancia + // No actualizamos el nombre ni la ruta aquí, ya que coinciden con la config. + assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado + break; // Mando encontrado para este jugador, pasamos al siguiente. } } } } // --- SEGUNDA PASADA: Asignar los mandos restantes a los jugadores sin mando --- - // Recorremos de nuevo la configuración de nuestros jugadores. + // Esto se ejecuta para slots vacíos o si un mando guardado no se encontró (p. ej. se desconectó). for (size_t i = 0; i < MAX_PLAYERS; ++i) { - if (gamepads[i].instance == nullptr) { // Si este jugador aún no tiene mando... + if (gamepads[i].instance == nullptr) { // Si este jugador aún no tiene mando... // ...buscamos un mando físico que todavía esté libre. for (const auto& physical_gamepad : physical_gamepads) { @@ -354,12 +356,14 @@ void GamepadManager::assignAndLinkGamepads() { } if (!already_assigned) { - gamepads[i].instance = physical_gamepad; // Se lo asignamos - // MUY IMPORTANTE: Actualizamos el nombre en la configuración. - // Si guardamos, ahora se guardará el nombre del mando real que se le asignó. - gamepads[i].name = physical_gamepad->name; - assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado - break; // Mando encontrado, pasamos al siguiente jugador. + gamepads[i].instance = physical_gamepad; // Se lo asignamos + + // MUY IMPORTANTE: Actualizamos la configuración para reflejar la realidad. + gamepads[i].name = physical_gamepad->name; // Actualizamos el nombre + gamepads[i].path = physical_gamepad->path; // <--- AÑADIDO: Y también la ruta! + + assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado + break; // Mando encontrado, pasamos al siguiente jugador. } } } diff --git a/source/options.h b/source/options.h index 7e6b906..706fb4c 100644 --- a/source/options.h +++ b/source/options.h @@ -97,6 +97,7 @@ struct Settings { struct Gamepad { std::shared_ptr instance = nullptr; // Referencia al mando std::string name; // Nombre del mando + std::string path; // Ruta física del dispositivo Player::Id player_id; // Jugador asociado al mando Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER) @@ -170,6 +171,7 @@ class GamepadManager { for (size_t i = 0; i < MAX_PLAYERS; ++i) { const auto& gamepad = gamepads[i]; file << "controller." << i << ".name=" << gamepad.name << "\n"; + file << "controller." << i << ".path=" << gamepad.path << "\n"; file << "controller." << i << ".player=" << static_cast(gamepad.player_id) << "\n"; } } @@ -185,6 +187,9 @@ class GamepadManager { if (property == "name") { gamepad.name = value; return true; + } else if (property == "path") { + gamepad.path = value; + return true; } else if (property == "player") { try { int player_int = std::stoi(value);