Ja es poden conectar i desconectar mandos en calent, que tot el mon s'entera

This commit is contained in:
2025-08-10 11:02:20 +02:00
parent 8eb8e07e0a
commit 983eb7ee6f
10 changed files with 109 additions and 64 deletions

View File

@@ -3,13 +3,37 @@
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory
#include "input.h" // Para Input
#include "lang.h" // Para Lang
#include "mouse.h" // Para handleEvent
#include "options.h" // Para Options
#include "screen.h" // Para Screen
#include "section.hpp" // Para Name, Options, name, options
#include "ui/notifier.h" // Para Notifier
#include "ui/service_menu.h" // Para ServiceMenu
namespace GlobalEvents {
// Comprueba los eventos de Input y muestra notificaciones
void handleInputEvents(const SDL_Event &event) {
static auto *input_ = Input::get();
auto message = input_->handleEvent(event);
if (message.empty()) return;
// Reemplazo de palabras clave por texto localizado
size_t pos;
while ((pos = message.find(" CONNECTED")) != std::string::npos) {
message.replace(pos, std::string(" CONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] CONNECTED"));
}
while ((pos = message.find(" DISCONNECTED")) != std::string::npos) {
message.replace(pos, std::string(" DISCONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] DISCONNECTED"));
}
Options::gamepad_manager.assignAndLinkGamepads();
Options::gamepad_manager.resyncGamepadsWithPlayers();
Notifier::get()->show({message});
ServiceMenu::get()->refresh();
}
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void check(const SDL_Event &event) {
switch (event.type) {
@@ -33,10 +57,6 @@ void check(const SDL_Event &event) {
ServiceMenu::get()->handleEvent(event);
Mouse::handleEvent(event);
static auto *input_ = Input::get();
if (input_->handleEvent(event)) {
Options::gamepad_manager.assignAndLinkGamepads();
}
handleInputEvents(event);
}
} // namespace GlobalEvents

View File

@@ -308,42 +308,45 @@ void Input::update() {
}
}
auto Input::handleEvent(const SDL_Event &event) -> bool {
auto Input::handleEvent(const SDL_Event &event) -> std::string {
switch (event.type) {
case SDL_EVENT_GAMEPAD_ADDED:
addGamepad(event.gdevice.which);
return true;
return addGamepad(event.gdevice.which);
case SDL_EVENT_GAMEPAD_REMOVED:
removeGamepad(event.gdevice.which);
return true;
return removeGamepad(event.gdevice.which);
}
return false;
return std::string();
}
void Input::addGamepad(int device_index) {
auto Input::addGamepad(int device_index) -> std::string {
SDL_Gamepad *pad = SDL_OpenGamepad(device_index);
if (pad == nullptr) {
std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << std::endl;
return;
return std::string();
}
auto gamepad = std::make_shared<Gamepad>(pad);
std::cout << "Gamepad connected (" << gamepad->name << ")" << std::endl;
auto name = gamepad->name;
std::cout << "Gamepad connected (" << name << ")" << std::endl;
applyGamepadConfig(gamepad);
saveGamepadConfigFromGamepad(gamepad);
gamepads_.push_back(std::move(gamepad));
return name + " CONNECTED";
}
void Input::removeGamepad(SDL_JoystickID id) {
auto it = std::remove_if(gamepads_.begin(), gamepads_.end(), [id](const std::shared_ptr<Gamepad> &gamepad) {
auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
auto it = std::find_if(gamepads_.begin(), gamepads_.end(), [id](const std::shared_ptr<Gamepad> &gamepad) {
return gamepad->instance_id == id;
});
if (it != gamepads_.end()) {
std::cout << "Gamepad disconnected (" << (*it)->name << ")" << std::endl;
gamepads_.erase(it, gamepads_.end());
std::string name = (*it)->name;
std::cout << "Gamepad disconnected (" << name << ")" << std::endl;
gamepads_.erase(it);
return name + " DISCONNECTED";
} else {
std::cerr << "No se encontró el gamepad con ID " << id << std::endl;
return {};
}
}

View File

@@ -168,7 +168,7 @@ class Input {
void resetInputStates();
// --- Eventos ---
auto handleEvent(const SDL_Event &event) -> bool;
auto handleEvent(const SDL_Event &event) -> std::string;
void printConnectedGamepads() const;
@@ -190,8 +190,8 @@ class Input {
// --- Métodos internos ---
void initSDLGamePad();
static auto checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
void addGamepad(int device_index);
void removeGamepad(SDL_JoystickID id);
auto addGamepad(int device_index) -> std::string;
auto removeGamepad(SDL_JoystickID id) -> std::string;
void addGamepadMappingsFromFile();
void discoverGamepads();

View File

@@ -157,10 +157,12 @@ class GamepadManager {
std::swap(gamepads_[0].name, gamepads_[1].name);
std::swap(gamepads_[0].path, gamepads_[1].path);
for (auto player: players)
{
switch (player->getId())
{
resyncGamepadsWithPlayers();
}
void resyncGamepadsWithPlayers() {
for (auto player : players) {
switch (player->getId()) {
case Player::Id::PLAYER1:
player->setGamepad(gamepads_[0].instance);
break;
@@ -168,7 +170,7 @@ class GamepadManager {
player->setGamepad(gamepads_[1].instance);
break;
default:
break;
break;
}
}
}
@@ -229,7 +231,6 @@ class GamepadManager {
// Asigna el mando a un jugador
void assignTo(Input::Gamepad gamepad, Player::Id player_id) {
}
// Asigna los mandos físicos basándose en la configuración actual de nombres.
@@ -246,7 +247,7 @@ class GamepadManager {
private:
static constexpr std::string_view UNASSIGNED_TEXT = "---";
static constexpr size_t MAX_PLAYERS = 2;
std::array<Gamepad, MAX_PLAYERS> gamepads_; // Punteros a las estructuras de mandos de Options
std::array<Gamepad, MAX_PLAYERS> gamepads_; // Punteros a las estructuras de mandos de Options
std::vector<std::shared_ptr<Player>> players; // Punteros a los jugadores
// Convierte Player::Id a índice del array

View File

@@ -258,7 +258,7 @@ void Game::updateStage() {
createMessage(paths, Resource::get()->getTexture("game_text_last_stage"));
} else {
auto text = Resource::get()->getText("04b_25_2x");
const std::string CAPTION = std::to_string(10 - Stage::number) + Lang::getText("[GAME_TEXT] 2");
const std::string CAPTION = Lang::getText("[GAME_TEXT] 2") + std::to_string(10 - Stage::number) + Lang::getText("[GAME_TEXT] 2A");
createMessage(paths, text->writeToTexture(CAPTION, 1, -4));
}
}

View File

@@ -49,13 +49,12 @@ void ServiceMenu::toggle() {
if (enabled_) {
// Primero resetea el estado y luego muestra la animación
// reset();
reset();
Options::gamepad_manager.assignAndLinkGamepads();
renderer_->show(this);
} else {
// Al cerrar, solo inicia la animación de ocultar
renderer_->hide();
// NO llames a reset() aquí
}
}
@@ -614,4 +613,14 @@ auto ServiceMenu::isAnimating() const -> bool {
auto ServiceMenu::isDefiningButtons() const -> bool {
return define_buttons_ && define_buttons_->isEnabled();
}
void ServiceMenu::refresh() {
// Este método está diseñado para ser llamado desde fuera, por ejemplo,
// cuando un mando se conecta o desconecta mientras el menú está abierto.
// La función updateMenu() es la forma más completa de refrescar, ya que
// sincroniza los valores, actualiza la lista de opciones visibles y notifica
// al renderer de cualquier cambio de layout que pueda haber ocurrido.
updateMenu();
}

View File

@@ -45,6 +45,9 @@ class ServiceMenu {
// --- Método para manejar eventos ---
void handleEvent(const SDL_Event &event);
bool checkInput();
// --- Método principal para refresco externo ---
void refresh(); // Refresca los valores y el layout del menú bajo demanda
// --- Getters para el estado ---
[[nodiscard]] auto isDefiningButtons() const -> bool;