build d'emscripten

This commit is contained in:
2026-04-17 10:00:37 +02:00
parent 6ea50cf35e
commit 5eb178b039
12 changed files with 316 additions and 44 deletions

View File

@@ -45,6 +45,11 @@ namespace GlobalInputs {
return;
}
#ifdef __EMSCRIPTEN__
// En la versión web no se puede salir del juego desde fuera de la escena GAME
// (el navegador gestiona la pestaña; Escape no cierra nada).
return;
#else
// Comportamiento normal fuera del modo kiosko
const std::string CODE = "PRESS AGAIN TO EXIT";
if (stringInVector(Notifier::get()->getCodes(), CODE)) {
@@ -52,6 +57,7 @@ namespace GlobalInputs {
} else {
Notifier::get()->show({Locale::get()->get("ui.press_again_exit")}, Notifier::Style::DEFAULT, -1, true, CODE);
}
#endif // __EMSCRIPTEN__
}
void handleSkipSection() {

View File

@@ -10,6 +10,40 @@
#include "game/options.hpp" // Para Options::controls
// Emscripten-only: SDL 3.4+ no casa el GUID de los mandos de Chrome Android
// con gamecontrollerdb (el gamepad.id de Android no lleva Vendor/Product, el
// parser extrae valores basura, el GUID resultante no está en la db y el
// gamepad queda abierto con un mapping incorrecto). Como la W3C Gamepad API
// garantiza el layout estándar cuando el navegador reporta mapping=="standard",
// inyectamos un mapping SDL con ese layout para el GUID del joystick antes
// de abrirlo como gamepad. Fuera de Emscripten es un no-op.
static void installWebStandardMapping(SDL_JoystickID jid) {
#ifdef __EMSCRIPTEN__
SDL_GUID guid = SDL_GetJoystickGUIDForID(jid);
char guidStr[33];
SDL_GUIDToString(guid, guidStr, sizeof(guidStr));
const char* name = SDL_GetJoystickNameForID(jid);
if ((name == nullptr) || (*name == 0)) { name = "Standard Gamepad"; }
char mapping[512];
SDL_snprintf(mapping, sizeof(mapping),
"%s,%s,"
"a:b0,b:b1,x:b2,y:b3,"
"leftshoulder:b4,rightshoulder:b5,"
"lefttrigger:b6,righttrigger:b7,"
"back:b8,start:b9,"
"leftstick:b10,rightstick:b11,"
"dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,"
"guide:b16,"
"leftx:a0,lefty:a1,rightx:a2,righty:a3,"
"platform:Emscripten",
guidStr, name);
SDL_AddGamepadMapping(mapping);
#else
(void)jid;
#endif
}
// Singleton
Input* Input::instance = nullptr;
@@ -397,6 +431,7 @@ auto Input::handleEvent(const SDL_Event& event) -> std::string {
}
auto Input::addGamepad(int device_index) -> std::string {
installWebStandardMapping(device_index);
SDL_Gamepad* pad = SDL_OpenGamepad(device_index);
if (pad == nullptr) {
std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << '\n';
@@ -407,7 +442,13 @@ auto Input::addGamepad(int device_index) -> std::string {
auto name = gamepad->name;
std::cout << "Gamepad connected (" << name << ")" << '\n';
gamepads_.push_back(std::move(gamepad));
return name + " CONNECTED";
// Aplica los bindings de Options al nuevo gamepad. En hot-plug (incluido wasm,
// donde el navegador sólo expone los gamepads tras activación del usuario) el
// ctor ya llamó a applyGamepadBindingsFromOptions() pero gamepads_ estaba vacío.
applyGamepadBindingsFromOptions();
return name;
}
auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
@@ -419,7 +460,7 @@ auto Input::removeGamepad(SDL_JoystickID id) -> std::string {
std::string name = (*it)->name;
std::cout << "Gamepad disconnected (" << name << ")" << '\n';
gamepads_.erase(it);
return name + " DISCONNECTED";
return name;
}
std::cerr << "No se encontró el gamepad con ID " << id << '\n';
return {};

View File

@@ -51,10 +51,20 @@ class Input {
std::string path; // Ruta del dispositivo
std::unordered_map<Action, ButtonState> bindings; // Mapa de acciones a estados de botón
// Recorta el nombre del mando hasta el primer '(' o '[' y elimina espacios finales.
// Evita nombres como "Retroid Controller (vendor: 1001) ..." en las notificaciones.
static auto trimName(const char* raw) -> std::string {
std::string s(raw != nullptr ? raw : "");
const auto pos = s.find_first_of("([");
if (pos != std::string::npos) { s.erase(pos); }
while (!s.empty() && s.back() == ' ') { s.pop_back(); }
return s;
}
explicit Gamepad(SDL_Gamepad* gamepad)
: pad(gamepad),
instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))),
name(std::string(SDL_GetGamepadName(gamepad))),
name(trimName(SDL_GetGamepadName(gamepad))),
path(std::string(SDL_GetGamepadPath(pad))),
bindings{
// Movimiento del jugador