afegit fix de mandos en emscripten android
This commit is contained in:
@@ -14,6 +14,59 @@ namespace Gamepad {
|
||||
static SDL_Gamepad* pad_ = nullptr;
|
||||
static SDL_JoystickID pad_id_ = 0;
|
||||
|
||||
// Emscripten-only: SDL 3.4+ ja no casa el GUID dels mandos web (el gamepad.id
|
||||
// de Chrome/Android no porta Vendor/Product, el parser extreu valors
|
||||
// escombraries, el GUID no està a gamecontrollerdb i el gamepad queda
|
||||
// obert amb un mapping incorrecte). Com el W3C Gamepad API garanteix
|
||||
// layout estàndard quan mapping=="standard", injectem un mapping SDL
|
||||
// amb eixe layout per al GUID del joystick abans d'obrir-lo com gamepad.
|
||||
// Fora d'Emscripten és 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 || !*name) 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
|
||||
}
|
||||
|
||||
// Recorta el nom visible del mando: trim des del primer '(' o '['
|
||||
// (per a evitar coses com "Retroid Controller (vendor: 1001) ..."),
|
||||
// elimina espais finals i talla a 25 caràcters.
|
||||
static std::string prettyName(const char* raw) {
|
||||
std::string name = (raw && *raw) ? raw : "Gamepad";
|
||||
const auto pos = name.find_first_of("([");
|
||||
if (pos != std::string::npos) {
|
||||
name.erase(pos);
|
||||
}
|
||||
while (!name.empty() && name.back() == ' ') {
|
||||
name.pop_back();
|
||||
}
|
||||
if (name.size() > 25) {
|
||||
name.resize(25);
|
||||
}
|
||||
if (name.empty()) name = "Gamepad";
|
||||
return name;
|
||||
}
|
||||
|
||||
// Dead-zone del stick esquerre (rang Sint16: -32768..32767)
|
||||
static constexpr Sint16 STICK_DEADZONE = 12000;
|
||||
|
||||
@@ -29,27 +82,34 @@ namespace Gamepad {
|
||||
static bool prev_start_ = false;
|
||||
static bool prev_back_ = false;
|
||||
|
||||
static void notify(const char* name, const char* status_key) {
|
||||
std::string msg = (name && *name) ? name : "Gamepad";
|
||||
static void notify(const std::string& name, const char* status_key) {
|
||||
std::string msg = name.empty() ? "Gamepad" : name;
|
||||
msg += ' ';
|
||||
msg += Locale::get(status_key);
|
||||
Overlay::showNotification(msg.c_str(), 2.5F);
|
||||
}
|
||||
|
||||
static void notifyConnected(const char* name) { notify(name, "notifications.gamepad_connected"); }
|
||||
static void notifyDisconnected(const char* name) { notify(name, "notifications.gamepad_disconnected"); }
|
||||
static void notifyConnected(const std::string& name) { notify(name, "notifications.gamepad_connected"); }
|
||||
static void notifyDisconnected(const std::string& name) { notify(name, "notifications.gamepad_disconnected"); }
|
||||
|
||||
// Obri el primer joystick disponible que siga reconegut com a gamepad
|
||||
// (o que ho esdevinga després d'injectar el mapping web estàndard).
|
||||
static void openFirstGamepad() {
|
||||
int count = 0;
|
||||
SDL_JoystickID* ids = SDL_GetGamepads(&count);
|
||||
if (ids && count > 0) {
|
||||
pad_ = SDL_OpenGamepad(ids[0]);
|
||||
SDL_JoystickID* ids = SDL_GetJoysticks(&count);
|
||||
if (ids) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
installWebStandardMapping(ids[i]);
|
||||
if (!SDL_IsGamepad(ids[i])) continue;
|
||||
pad_ = SDL_OpenGamepad(ids[i]);
|
||||
if (pad_) {
|
||||
pad_id_ = ids[0];
|
||||
pad_id_ = ids[i];
|
||||
SDL_Log("Gamepad connectat: %s", SDL_GetGamepadName(pad_));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ids) SDL_free(ids);
|
||||
SDL_free(ids);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
@@ -80,20 +140,25 @@ namespace Gamepad {
|
||||
}
|
||||
|
||||
void handleEvent(const SDL_Event& event) {
|
||||
if (event.type == SDL_EVENT_GAMEPAD_ADDED) {
|
||||
// A Emscripten els dispositius web entren com a JOYSTICK_ADDED (no
|
||||
// GAMEPAD_ADDED) perquè SDL no reconeix el GUID. Escoltem els dos i
|
||||
// injectem el mapping estàndard abans d'obrir el mando.
|
||||
if (event.type == SDL_EVENT_GAMEPAD_ADDED || event.type == SDL_EVENT_JOYSTICK_ADDED) {
|
||||
if (!pad_) {
|
||||
pad_ = SDL_OpenGamepad(event.gdevice.which);
|
||||
SDL_JoystickID jid = event.jdevice.which;
|
||||
installWebStandardMapping(jid);
|
||||
if (!SDL_IsGamepad(jid)) return;
|
||||
pad_ = SDL_OpenGamepad(jid);
|
||||
if (pad_) {
|
||||
pad_id_ = event.gdevice.which;
|
||||
const char* name = SDL_GetGamepadName(pad_);
|
||||
SDL_Log("Gamepad connectat: %s", name ? name : "");
|
||||
pad_id_ = jid;
|
||||
std::string name = prettyName(SDL_GetGamepadName(pad_));
|
||||
SDL_Log("Gamepad connectat: %s", name.c_str());
|
||||
notifyConnected(name);
|
||||
}
|
||||
}
|
||||
} else if (event.type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
if (pad_ && event.gdevice.which == pad_id_) {
|
||||
const char* name = SDL_GetGamepadName(pad_);
|
||||
std::string saved_name = name ? name : "";
|
||||
} else if (event.type == SDL_EVENT_GAMEPAD_REMOVED || event.type == SDL_EVENT_JOYSTICK_REMOVED) {
|
||||
if (pad_ && event.jdevice.which == pad_id_) {
|
||||
std::string saved_name = prettyName(SDL_GetGamepadName(pad_));
|
||||
SDL_Log("Gamepad desconnectat: %s", saved_name.c_str());
|
||||
SDL_CloseGamepad(pad_);
|
||||
pad_ = nullptr;
|
||||
@@ -103,7 +168,7 @@ namespace Gamepad {
|
||||
JI_SetVirtualKey(SDL_SCANCODE_DOWN, JI_VSRC_GAMEPAD, false);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_LEFT, JI_VSRC_GAMEPAD, false);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_RIGHT, JI_VSRC_GAMEPAD, false);
|
||||
notifyDisconnected(saved_name.c_str());
|
||||
notifyDisconnected(saved_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,8 +260,10 @@ void Director::handleEvent(const SDL_Event& event) {
|
||||
JG_QuitSignal();
|
||||
requestQuit();
|
||||
}
|
||||
// Hot-plug de gamepad
|
||||
if (event.type == SDL_EVENT_GAMEPAD_ADDED || event.type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
// Hot-plug de gamepad (a Emscripten els dispositius web entren com
|
||||
// JOYSTICK_ADDED/REMOVED perquè SDL no reconeix el GUID)
|
||||
if (event.type == SDL_EVENT_GAMEPAD_ADDED || event.type == SDL_EVENT_GAMEPAD_REMOVED ||
|
||||
event.type == SDL_EVENT_JOYSTICK_ADDED || event.type == SDL_EVENT_JOYSTICK_REMOVED) {
|
||||
Gamepad::handleEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user