diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index eda690a86..b54e4ce77 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -153,6 +153,7 @@ public: virtual bool isGamepadDown(const std::vector &blist) const = 0; virtual JoystickInput getGamepadMapping(const GamepadInput &input) const = 0; + virtual std::string getGamepadMappingString() const = 0; virtual void *getHandle() const = 0; diff --git a/src/modules/joystick/JoystickModule.h b/src/modules/joystick/JoystickModule.h index f0343cd71..22f24a724 100644 --- a/src/modules/joystick/JoystickModule.h +++ b/src/modules/joystick/JoystickModule.h @@ -37,7 +37,7 @@ public: virtual ~JoystickModule() {} // Implements Module. - virtual ModuleType getModuleType() const { return M_JOYSTICK; } + ModuleType getModuleType() const override { return M_JOYSTICK; } /** * Adds a connected Joystick device and opens it for use. @@ -96,6 +96,11 @@ public: **/ virtual std::string saveGamepadMappings() = 0; + /** + * Gets the gamepad mapping string for the given GUID. + **/ + virtual std::string getGamepadMappingString(const std::string &guid) const = 0; + }; // JoystickModule } // joystick diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index 2de06b0d0..bb41916af 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -301,6 +301,33 @@ Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput &input) c return jinput; } +std::string Joystick::getGamepadMappingString() const +{ + char *sdlmapping = nullptr; + + if (controller != nullptr) + sdlmapping = SDL_GameControllerMapping(controller); + + if (sdlmapping == nullptr) + { + SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(pguid.c_str()); + sdlmapping = SDL_GameControllerMappingForGUID(sdlguid); + } + + if (sdlmapping == nullptr) + return ""; + + std::string mappingstr(sdlmapping); + SDL_free(sdlmapping); + + // Matches SDL_GameControllerAddMappingsFromRW. + if (mappingstr.find_last_of(',') != mappingstr.length() - 1) + mappingstr += ","; + mappingstr += "platform:" + std::string(SDL_GetPlatform()); + + return mappingstr; +} + void *Joystick::getHandle() const { return joyhandle; diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index 077ff3575..fc4c6dc07 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -68,6 +68,7 @@ public: bool isGamepadDown(const std::vector &blist) const override; JoystickInput getGamepadMapping(const GamepadInput &input) const override; + std::string getGamepadMappingString() const override; void *getHandle() const override; diff --git a/src/modules/joystick/sdl/JoystickModule.cpp b/src/modules/joystick/sdl/JoystickModule.cpp index 17029bfaa..bda77dcc3 100644 --- a/src/modules/joystick/sdl/JoystickModule.cpp +++ b/src/modules/joystick/sdl/JoystickModule.cpp @@ -451,6 +451,25 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings) throw love::Exception("Invalid gamepad mappings."); } +std::string JoystickModule::getGamepadMappingString(const std::string &guid) const +{ + SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(guid.c_str()); + + char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid); + if (sdlmapping == nullptr) + return ""; + + std::string mapping(sdlmapping); + SDL_free(sdlmapping); + + // Matches SDL_GameControllerAddMappingsFromRW. + if (mapping.find_last_of(',') != mapping.length() - 1) + mapping += ","; + mapping += "platform:" + std::string(SDL_GetPlatform()); + + return mapping; +} + std::string JoystickModule::saveGamepadMappings() { std::string mappings; diff --git a/src/modules/joystick/sdl/JoystickModule.h b/src/modules/joystick/sdl/JoystickModule.h index 8af9e9330..f20c3d9ca 100644 --- a/src/modules/joystick/sdl/JoystickModule.h +++ b/src/modules/joystick/sdl/JoystickModule.h @@ -45,19 +45,21 @@ public: virtual ~JoystickModule(); // Implements Module. - const char *getName() const; + const char *getName() const override; // Implements JoystickModule. - love::joystick::Joystick *addJoystick(int deviceindex); - void removeJoystick(love::joystick::Joystick *joystick); - love::joystick::Joystick *getJoystickFromID(int instanceid); - love::joystick::Joystick *getJoystick(int joyindex); - int getIndex(const love::joystick::Joystick *joystick); - int getJoystickCount() const; + love::joystick::Joystick *addJoystick(int deviceindex) override; + void removeJoystick(love::joystick::Joystick *joystick) override; + love::joystick::Joystick *getJoystickFromID(int instanceid) override; + love::joystick::Joystick *getJoystick(int joyindex) override; + int getIndex(const love::joystick::Joystick *joystick) override; + int getJoystickCount() const override; - bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput); - void loadGamepadMappings(const std::string &mappings); - std::string saveGamepadMappings(); + bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput) override; + void loadGamepadMappings(const std::string &mappings) override; + + std::string getGamepadMappingString(const std::string &guid) const override; + std::string saveGamepadMappings() override; private: diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index 5faf68a91..ef1e86f54 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -292,6 +292,17 @@ int w_Joystick_getGamepadMapping(lua_State *L) return 1; } +int w_Joystick_getGamepadMappingString(lua_State *L) +{ + Joystick *j = luax_checkjoystick(L, 1); + std::string mapping = j->getGamepadMappingString(); + if (mapping.empty()) + lua_pushnil(L); + else + luax_pushstring(L, mapping); + return 1; +} + int w_Joystick_isVibrationSupported(lua_State *L) { Joystick *j = luax_checkjoystick(L, 1); @@ -351,6 +362,7 @@ static const luaL_Reg w_Joystick_functions[] = { "getGamepadAxis", w_Joystick_getGamepadAxis }, { "isGamepadDown", w_Joystick_isGamepadDown }, { "getGamepadMapping", w_Joystick_getGamepadMapping }, + { "getGamepadMappingString", w_Joystick_getGamepadMappingString }, { "isVibrationSupported", w_Joystick_isVibrationSupported }, { "setVibration", w_Joystick_setVibration }, diff --git a/src/modules/joystick/wrap_JoystickModule.cpp b/src/modules/joystick/wrap_JoystickModule.cpp index b9291b211..1a7879dfc 100644 --- a/src/modules/joystick/wrap_JoystickModule.cpp +++ b/src/modules/joystick/wrap_JoystickModule.cpp @@ -160,6 +160,17 @@ int w_saveGamepadMappings(lua_State *L) return 1; } +int w_getGamepadMappingString(lua_State *L) +{ + const char *guid = luaL_checkstring(L, 1); + std::string mapping = instance()->getGamepadMappingString(guid); + if (mapping.empty()) + lua_pushnil(L); + else + luax_pushstring(L, mapping); + return 1; +} + // List of functions to wrap. static const luaL_Reg functions[] = { @@ -168,6 +179,7 @@ static const luaL_Reg functions[] = { "setGamepadMapping", w_setGamepadMapping }, { "loadGamepadMappings", w_loadGamepadMappings }, { "saveGamepadMappings", w_saveGamepadMappings }, + { "getGamepadMappingString", w_getGamepadMappingString }, { 0, 0 } };