feat(input): notifica connexio/desconnexio de mandos via Notifier
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+73
-18
@@ -8,6 +8,9 @@
|
||||
#include <unordered_map> // Para unordered_map, _Node_iterator, operator==, _Node_iterator_base, _Node_const_iterator
|
||||
#include <utility> // Para move
|
||||
|
||||
#include "core/locale/locale.hpp"
|
||||
#include "core/system/notifier.hpp"
|
||||
|
||||
// Singleton
|
||||
Input* Input::instance = nullptr;
|
||||
|
||||
@@ -407,6 +410,16 @@ auto Input::addGamepad(int device_index) -> std::string {
|
||||
auto name = gamepad->name;
|
||||
std::cout << "Gamepad connected (" << name << ")" << '\n';
|
||||
gamepads_.push_back(std::move(gamepad));
|
||||
|
||||
// Toast a pantalla. Pot ser nullptr durant discoverGamepads() inicial
|
||||
// (l'Input::init() es crida abans que el Director instanciï el Notifier).
|
||||
if (auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
||||
notifier->notifyInfo(localeSubstitute(
|
||||
Locale::get().text("notification.gamepad_connected"),
|
||||
"{name}",
|
||||
name));
|
||||
}
|
||||
|
||||
return name + " CONNECTED";
|
||||
}
|
||||
|
||||
@@ -419,6 +432,14 @@ auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
|
||||
std::string name = (*it)->name;
|
||||
std::cout << "Gamepad disconnected (" << name << ")" << '\n';
|
||||
gamepads_.erase(it);
|
||||
|
||||
if (auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
||||
notifier->notifyInfo(localeSubstitute(
|
||||
Locale::get().text("notification.gamepad_disconnected"),
|
||||
"{name}",
|
||||
name));
|
||||
}
|
||||
|
||||
return name + " DISCONNECTED";
|
||||
}
|
||||
std::cerr << "No se encontró el gamepad con ID " << id << '\n';
|
||||
@@ -465,6 +486,39 @@ 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> {
|
||||
if (gamepads_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!bindings.gamepad_path.empty()) {
|
||||
for (const auto& pad : gamepads_) {
|
||||
if (pad && pad->path == bindings.gamepad_path) {
|
||||
return pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bindings.gamepad_name.empty()) {
|
||||
for (const auto& pad : gamepads_) {
|
||||
if (pad && pad->name == bindings.gamepad_name) {
|
||||
return pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Aplica configuración de controles del player 1
|
||||
void Input::applyPlayer1Bindings(const Config::PlayerBindings& bindings) {
|
||||
// 1. Aplicar bindings de teclado (NO usar bindKey, llenar mapa específico)
|
||||
@@ -474,15 +528,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. Encontrar gamepad por nombre (o usar primer gamepad como fallback)
|
||||
std::shared_ptr<Gamepad> gamepad = nullptr;
|
||||
if (bindings.gamepad_name.empty()) {
|
||||
// Fallback: usar primer gamepad disponible
|
||||
gamepad = (!gamepads_.empty()) ? gamepads_[0] : nullptr;
|
||||
} else {
|
||||
// Buscar por nombre
|
||||
gamepad = findAvailableGamepadByName(bindings.gamepad_name);
|
||||
}
|
||||
// 2. Resoldre gamepad per path/name/slot
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings, 0);
|
||||
|
||||
if (!gamepad) {
|
||||
player1_gamepad_ = nullptr;
|
||||
@@ -494,6 +541,8 @@ void Input::applyPlayer1Bindings(const Config::PlayerBindings& bindings) {
|
||||
gamepad->bindings[Action::RIGHT].button = bindings.gamepad.button_right;
|
||||
gamepad->bindings[Action::THRUST].button = bindings.gamepad.button_thrust;
|
||||
gamepad->bindings[Action::SHOOT].button = bindings.gamepad.button_shoot;
|
||||
gamepad->bindings[Action::START].button = bindings.gamepad.button_start;
|
||||
gamepad->bindings[Action::MENU].button = bindings.gamepad.button_menu;
|
||||
|
||||
// 4. Cachear referencia
|
||||
player1_gamepad_ = gamepad;
|
||||
@@ -508,15 +557,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. Encontrar gamepad por nombre (o usar segundo gamepad como fallback)
|
||||
std::shared_ptr<Gamepad> gamepad = nullptr;
|
||||
if (bindings.gamepad_name.empty()) {
|
||||
// Fallback: usar segundo gamepad disponible
|
||||
gamepad = (gamepads_.size() > 1) ? gamepads_[1] : nullptr;
|
||||
} else {
|
||||
// Buscar por nombre
|
||||
gamepad = findAvailableGamepadByName(bindings.gamepad_name);
|
||||
}
|
||||
// 2. Resoldre gamepad per path/name/slot
|
||||
std::shared_ptr<Gamepad> gamepad = resolvePlayerGamepad(bindings, 1);
|
||||
|
||||
if (!gamepad) {
|
||||
player2_gamepad_ = nullptr;
|
||||
@@ -528,6 +570,8 @@ void Input::applyPlayer2Bindings(const Config::PlayerBindings& bindings) {
|
||||
gamepad->bindings[Action::RIGHT].button = bindings.gamepad.button_right;
|
||||
gamepad->bindings[Action::THRUST].button = bindings.gamepad.button_thrust;
|
||||
gamepad->bindings[Action::SHOOT].button = bindings.gamepad.button_shoot;
|
||||
gamepad->bindings[Action::START].button = bindings.gamepad.button_start;
|
||||
gamepad->bindings[Action::MENU].button = bindings.gamepad.button_menu;
|
||||
|
||||
// 4. Cachear referencia
|
||||
player2_gamepad_ = gamepad;
|
||||
@@ -555,6 +599,17 @@ auto Input::checkActionPlayer1(Action action, bool repeat) -> bool {
|
||||
return keyboard_active || gamepad_active;
|
||||
}
|
||||
|
||||
// Retorna el pad assignat (0=P1, 1=P2). Pot ser nullptr.
|
||||
auto Input::getPlayerGamepad(int player_index) const -> std::shared_ptr<Input::Gamepad> {
|
||||
if (player_index == 0) {
|
||||
return player1_gamepad_;
|
||||
}
|
||||
if (player_index == 1) {
|
||||
return player2_gamepad_;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Consulta de input para player 2
|
||||
auto Input::checkActionPlayer2(Action action, bool repeat) -> bool {
|
||||
// Comprobar teclado con el mapa específico de P2
|
||||
|
||||
Reference in New Issue
Block a user