diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index 1aceb6f2a..bbc56f39b 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -152,6 +152,8 @@ public: virtual float getGamepadAxis(GamepadAxis axis) const = 0; virtual bool isGamepadDown(const std::vector &blist) const = 0; + virtual JoystickInput getGamepadMapping(const GamepadInput &input) const = 0; + virtual void *getHandle() const = 0; virtual std::string getGUID() const = 0; diff --git a/src/modules/joystick/JoystickModule.h b/src/modules/joystick/JoystickModule.h index b30dbf661..5bba69c10 100644 --- a/src/modules/joystick/JoystickModule.h +++ b/src/modules/joystick/JoystickModule.h @@ -82,12 +82,6 @@ public: **/ virtual bool setGamepadMapping(const std::string &pguid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput) = 0; - /** - * Gets the joystick input value the gamepad input value is bound to for the - * specified joystick product GUID. - **/ - virtual Joystick::JoystickInput getGamepadMapping(const std::string &pguid, Joystick::GamepadInput gpinput) = 0; - /** * Loads a newline-separated list of virtual Gamepad mapping strings for * multiple joysticks at a time. The mapping strings must have been diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index ae2e8a8b8..2fd49eefc 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -248,6 +248,59 @@ bool Joystick::isGamepadDown(const std::vector &blist) const return false; } +Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput &input) const +{ + Joystick::JoystickInput jinput; + jinput.type = INPUT_TYPE_MAX_ENUM; + + if (!isGamepad()) + return jinput; + + SDL_GameControllerButtonBind sdlbind = {}; + sdlbind.bindType = SDL_CONTROLLER_BINDTYPE_NONE; + + SDL_GameControllerButton sdlbutton; + SDL_GameControllerAxis sdlaxis; + + switch (input.type) + { + case INPUT_TYPE_BUTTON: + if (getConstant(input.button, sdlbutton)) + sdlbind = SDL_GameControllerGetBindForButton(controller, sdlbutton); + break; + case INPUT_TYPE_AXIS: + if (getConstant(input.axis, sdlaxis)) + sdlbind = SDL_GameControllerGetBindForAxis(controller, sdlaxis); + break; + default: + break; + } + + switch (sdlbind.bindType) + { + case SDL_CONTROLLER_BINDTYPE_BUTTON: + jinput.type = INPUT_TYPE_BUTTON; + jinput.button = sdlbind.value.button; + break; + case SDL_CONTROLLER_BINDTYPE_AXIS: + jinput.type = INPUT_TYPE_AXIS; + jinput.axis = sdlbind.value.axis; + break; + case SDL_CONTROLLER_BINDTYPE_HAT: + if (getConstant(sdlbind.value.hat.hat_mask, jinput.hat.value)) + { + jinput.type = INPUT_TYPE_HAT; + jinput.hat.index = sdlbind.value.hat.hat; + } + break; + case SDL_CONTROLLER_BINDTYPE_NONE: + default: + break; + } + + return jinput; +} + void *Joystick::getHandle() const { return joyhandle; diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index 6ee764e67..156255af3 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -44,39 +44,41 @@ public: virtual ~Joystick(); - bool open(int deviceindex); - void close(); + bool open(int deviceindex) override; + void close() override; - bool isConnected() const; + bool isConnected() const override; - const char *getName() const; + const char *getName() const override; - int getAxisCount() const; - int getButtonCount() const; - int getHatCount() const; + int getAxisCount() const override; + int getButtonCount() const override; + int getHatCount() const override; - float getAxis(int axisindex) const; - std::vector getAxes() const; - Hat getHat(int hatindex) const; + float getAxis(int axisindex) const override; + std::vector getAxes() const override; + Hat getHat(int hatindex) const override; - bool isDown(const std::vector &buttonlist) const; + bool isDown(const std::vector &buttonlist) const override; - bool openGamepad(int deviceindex); - bool isGamepad() const; + bool openGamepad(int deviceindex) override; + bool isGamepad() const override; - float getGamepadAxis(GamepadAxis axis) const; - bool isGamepadDown(const std::vector &blist) const; + float getGamepadAxis(GamepadAxis axis) const override; + bool isGamepadDown(const std::vector &blist) const override; - void *getHandle() const; + JoystickInput getGamepadMapping(const GamepadInput &input) const override; - std::string getGUID() const; - int getInstanceID() const; - int getID() const; + void *getHandle() const override; - bool isVibrationSupported(); - bool setVibration(float left, float right, float duration = -1.0f); - bool setVibration(); - void getVibration(float &left, float &right); + std::string getGUID() const override; + int getInstanceID() const override; + int getID() const override; + + bool isVibrationSupported() override; + bool setVibration(float left, float right, float duration = -1.0f) override; + bool setVibration() override; + void getVibration(float &left, float &right) override; static bool getConstant(Hat in, Uint8 &out); static bool getConstant(Uint8 in, Hat &out); diff --git a/src/modules/joystick/sdl/JoystickModule.cpp b/src/modules/joystick/sdl/JoystickModule.cpp index e30f3236c..2ef298b64 100644 --- a/src/modules/joystick/sdl/JoystickModule.cpp +++ b/src/modules/joystick/sdl/JoystickModule.cpp @@ -271,54 +271,6 @@ bool JoystickModule::setGamepadMapping(const std::string &guid, Joystick::Gamepa return status >= 0; } -Joystick::JoystickInput JoystickModule::getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput) -{ - // All SDL joystick GUID strings are 32 characters. - if (guid.length() != 32) - throw love::Exception("Invalid joystick GUID: %s", guid.c_str()); - - Joystick::JoystickInput jinput; - jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; - - SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(guid.c_str()); - - std::string mapstr; - - char *sdlmapstr = SDL_GameControllerMappingForGUID(sdlguid); - if (!sdlmapstr) - return jinput; - - mapstr = sdlmapstr; - SDL_free(sdlmapstr); - - std::string gpbindname = stringFromGamepadInput(gpinput); - - size_t findpos = mapstr.find(std::string(",") + gpbindname + ":"); - if (findpos == std::string::npos) - return jinput; - - size_t endpos = mapstr.find_first_of(',', findpos + 1); - if (endpos == std::string::npos) - { - // Assume end-of-string if we can't find the next comma. - endpos = mapstr.length() - 1; - } - - if (endpos >= mapstr.length()) - return jinput; // Something went wrong. - - // Strip out the trailing comma from our search position, if it exists. - if (mapstr[endpos] == ',') - endpos--; - - // New start position: comma + gamepadinputlength + ":". - findpos += 1 + gpbindname.length() + 1; - std::string jbindstr = mapstr.substr(findpos, endpos - findpos + 1); - - jinput = JoystickInputFromString(jbindstr); - return jinput; -} - std::string JoystickModule::stringFromGamepadInput(Joystick::GamepadInput gpinput) const { SDL_GameControllerAxis sdlaxis; @@ -346,51 +298,6 @@ std::string JoystickModule::stringFromGamepadInput(Joystick::GamepadInput gpinpu return std::string(gpinputname); } -Joystick::JoystickInput JoystickModule::JoystickInputFromString(const std::string &str) const -{ - Joystick::JoystickInput jinput; - jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; - - // Return an invalid value rather than throwing an exception. - if (str.length() < 2) - return jinput; - - // The input type will always be the first character in the string. - char inputtype = str[0]; - std::string bindvalues = str.substr(1); - - Uint8 sdlhat; - switch (inputtype) - { - case 'a': - jinput.type = Joystick::INPUT_TYPE_AXIS; - jinput.axis = (int) strtol(bindvalues.c_str(), nullptr, 10); - break; - case 'b': - jinput.type = Joystick::INPUT_TYPE_BUTTON; - jinput.button = (int) strtol(bindvalues.c_str(), nullptr, 10); - break; - case 'h': - // Hat string syntax is "index.value". - if (bindvalues.length() < 3) - break; - jinput.type = Joystick::INPUT_TYPE_HAT; - jinput.hat.index = (int) strtol(bindvalues.substr(0, 1).c_str(), nullptr, 10); - sdlhat = (Uint8) strtol(bindvalues.substr(2).c_str(), nullptr, 10); - if (!Joystick::getConstant(sdlhat, jinput.hat.value)) - { - // Return an invalid value if we can't find the hat constant. - jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; - return jinput; - } - break; - default: - break; - } - - return jinput; -} - void JoystickModule::removeBindFromMapString(std::string &mapstr, const std::string &joybindstr) const { // Find the joystick part of the bind in the string. diff --git a/src/modules/joystick/sdl/JoystickModule.h b/src/modules/joystick/sdl/JoystickModule.h index a4c702fa4..e8f392acf 100644 --- a/src/modules/joystick/sdl/JoystickModule.h +++ b/src/modules/joystick/sdl/JoystickModule.h @@ -56,14 +56,12 @@ public: int getJoystickCount() const; bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput); - Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput); void loadGamepadMappings(const std::string &mappings); std::string saveGamepadMappings(); private: std::string stringFromGamepadInput(Joystick::GamepadInput gpinput) const; - Joystick::JoystickInput JoystickInputFromString(const std::string &str) const; void removeBindFromMapString(std::string &mapstr, const std::string &joybindstr) const; void checkGamepads(const std::string &guid) const; diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index 8c4ed8491..ab9f4c861 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -225,6 +225,59 @@ int w_Joystick_isGamepadDown(lua_State *L) return 1; } +int w_Joystick_getGamepadMapping(lua_State *L) +{ + Joystick *j = luax_checkjoystick(L, 1); + + const char *gpbindstr = luaL_checkstring(L, 2); + Joystick::GamepadInput gpinput; + + if (Joystick::getConstant(gpbindstr, gpinput.axis)) + gpinput.type = Joystick::INPUT_TYPE_AXIS; + else if (Joystick::getConstant(gpbindstr, gpinput.button)) + gpinput.type = Joystick::INPUT_TYPE_BUTTON; + else + return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); + + Joystick::JoystickInput jinput; + jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; + + luax_catchexcept(L, [&](){ jinput = j->getGamepadMapping(gpinput); }); + + if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM) + return 0; + + const char *inputtypestr; + if (!Joystick::getConstant(jinput.type, inputtypestr)) + return luaL_error(L, "Unknown joystick input type."); + + lua_pushstring(L, inputtypestr); + + const char *hatstr; + switch (jinput.type) + { + case Joystick::INPUT_TYPE_AXIS: + lua_pushinteger(L, jinput.axis + 1); + return 2; + case Joystick::INPUT_TYPE_BUTTON: + lua_pushinteger(L, jinput.button + 1); + return 2; + case Joystick::INPUT_TYPE_HAT: + lua_pushinteger(L, jinput.hat.index + 1); + if (Joystick::getConstant(jinput.hat.value, hatstr)) + { + lua_pushstring(L, hatstr); + return 3; + } + else + return luaL_error(L, "Unknown joystick hat."); + default: + return luaL_error(L, "Unknown joystick input type."); + } + + return 1; +} + int w_Joystick_isVibrationSupported(lua_State *L) { Joystick *j = luax_checkjoystick(L, 1); @@ -282,6 +335,7 @@ static const luaL_Reg w_Joystick_functions[] = { "isGamepad", w_Joystick_isGamepad }, { "getGamepadAxis", w_Joystick_getGamepadAxis }, { "isGamepadDown", w_Joystick_isGamepadDown }, + { "getGamepadMapping", w_Joystick_getGamepadMapping }, { "isVibrationSupported", w_Joystick_isVibrationSupported }, { "setVibration", w_Joystick_setVibration }, @@ -289,7 +343,6 @@ static const luaL_Reg w_Joystick_functions[] = // From wrap_JoystickModule. { "getConnectedIndex", w_getIndex }, - { "getGamepadMapping", w_getGamepadMapping }, { 0, 0 }, }; diff --git a/src/modules/joystick/wrap_JoystickModule.cpp b/src/modules/joystick/wrap_JoystickModule.cpp index 5a2e5845a..2fe3991db 100644 --- a/src/modules/joystick/wrap_JoystickModule.cpp +++ b/src/modules/joystick/wrap_JoystickModule.cpp @@ -114,69 +114,6 @@ int w_setGamepadMapping(lua_State *L) return 1; } -int w_getGamepadMapping(lua_State *L) -{ - std::string guid; - - // Accept either a GUID string or a Joystick object. This way we can re-use - // the function for Joystick:getGamepadMapping. - if (lua_type(L, 1) == LUA_TSTRING) - guid = luax_checkstring(L, 1); - else - { - Joystick *stick = luax_checkjoystick(L, 1); - guid = stick->getGUID(); - } - - const char *gpbindstr = luaL_checkstring(L, 2); - Joystick::GamepadInput gpinput; - - if (Joystick::getConstant(gpbindstr, gpinput.axis)) - gpinput.type = Joystick::INPUT_TYPE_AXIS; - else if (Joystick::getConstant(gpbindstr, gpinput.button)) - gpinput.type = Joystick::INPUT_TYPE_BUTTON; - else - return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); - - Joystick::JoystickInput jinput; - jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; - - luax_catchexcept(L, [&](){ jinput = instance()->getGamepadMapping(guid, gpinput); }); - - if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM) - return 0; - - const char *inputtypestr; - if (!Joystick::getConstant(jinput.type, inputtypestr)) - return luaL_error(L, "Unknown joystick input type."); - - lua_pushstring(L, inputtypestr); - - const char *hatstr; - switch (jinput.type) - { - case Joystick::INPUT_TYPE_AXIS: - lua_pushinteger(L, jinput.axis + 1); - return 2; - case Joystick::INPUT_TYPE_BUTTON: - lua_pushinteger(L, jinput.button + 1); - return 2; - case Joystick::INPUT_TYPE_HAT: - lua_pushinteger(L, jinput.hat.index + 1); - if (Joystick::getConstant(jinput.hat.value, hatstr)) - { - lua_pushstring(L, hatstr); - return 3; - } - else - return luaL_error(L, "Unknown joystick hat."); - default: - break; // ? - } - - return 1; -} - int w_loadGamepadMappings(lua_State *L) { bool isfile = true; @@ -229,7 +166,6 @@ static const luaL_Reg functions[] = { "getJoysticks", w_getJoysticks }, { "getJoystickCount", w_getJoystickCount }, { "setGamepadMapping", w_setGamepadMapping }, - { "getGamepadMapping", w_getGamepadMapping }, { "loadGamepadMappings", w_loadGamepadMappings }, { "saveGamepadMappings", w_saveGamepadMappings }, { 0, 0 } diff --git a/src/modules/joystick/wrap_JoystickModule.h b/src/modules/joystick/wrap_JoystickModule.h index 5827b8856..a6e34b6ed 100644 --- a/src/modules/joystick/wrap_JoystickModule.h +++ b/src/modules/joystick/wrap_JoystickModule.h @@ -32,7 +32,6 @@ namespace joystick { int w_getIndex(lua_State *L); -int w_getGamepadMapping(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_joystick(lua_State *L); } // joystick