Replaced Joystick:saveGamepadMapping with love.joystick.saveGamepadMappings, which saves all gamepad mappings from both recently-used joysticks and recently-modified mappings. saveGamepadMappings returns a string of newline-separated mappings and takes an optional filename argument which writes it to a file.

This commit is contained in:
Alex Szpakowski
2014-06-05 00:25:34 -03:00
parent 10e0d4b900
commit ddb9997ead
6 changed files with 60 additions and 45 deletions
+4 -3
View File
@@ -88,15 +88,16 @@ public:
/** /**
* Loads a newline-separated list of virtual Gamepad mapping strings for * Loads a newline-separated list of virtual Gamepad mapping strings for
* multiple joysticks at a time. The mapping strings must have been * multiple joysticks at a time. The mapping strings must have been
* generated with saveGamepadMapping, via Steam, or some other tool which * generated with saveGamepadMappings, via Steam, or some other tool which
* generates SDL GameController mappings. * generates SDL GameController mappings.
**/ **/
virtual void loadGamepadMappings(const std::string &mappings) = 0; virtual void loadGamepadMappings(const std::string &mappings) = 0;
/** /**
* Gets the virtual Gamepad mapping string for the specified joystick GUID. * Gets a newline-separated list of virtual Gamepad mapping strings for
* all used or modified Joysticks which are identified as Gamepads.
**/ **/
virtual std::string saveGamepadMapping(const std::string &pguid) = 0; virtual std::string saveGamepadMappings() = 0;
}; // JoystickModule }; // JoystickModule
+25 -14
View File
@@ -161,6 +161,9 @@ love::joystick::Joystick *JoystickModule::addJoystick(int deviceindex)
} }
} }
if (joystick->isGamepad())
recentGamepadGUIDs[joystick->getGUID()] = true;
activeSticks.push_back(joystick); activeSticks.push_back(joystick);
return joystick; return joystick;
} }
@@ -257,6 +260,9 @@ bool JoystickModule::setGamepadMapping(const std::string &guid, Joystick::Gamepa
// 1 == added, 0 == updated, -1 == error. // 1 == added, 0 == updated, -1 == error.
int status = SDL_GameControllerAddMapping(mapstr.c_str()); int status = SDL_GameControllerAddMapping(mapstr.c_str());
if (status != -1)
recentGamepadGUIDs[guid] = true;
// FIXME: massive hack until missing APIs are added to SDL 2: // FIXME: massive hack until missing APIs are added to SDL 2:
// https://bugzilla.libsdl.org/show_bug.cgi?id=1975 // https://bugzilla.libsdl.org/show_bug.cgi?id=1975
if (status == 1) if (status == 1)
@@ -498,10 +504,11 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings)
if (SDL_GameControllerAddMapping(mapping.c_str()) != -1) if (SDL_GameControllerAddMapping(mapping.c_str()) != -1)
{ {
success = true; success = true;
std::string guid = mapping.substr(0, mapping.find_first_of(','));
recentGamepadGUIDs[guid] = true;
// FIXME: massive hack until missing APIs are added to SDL 2: // FIXME: massive hack until missing APIs are added to SDL 2:
// https://bugzilla.libsdl.org/show_bug.cgi?id=1975 // https://bugzilla.libsdl.org/show_bug.cgi?id=1975
std::string guid = mapping.substr(0, mapping.find_first_of(','));
checkGamepads(guid); checkGamepads(guid);
} }
} }
@@ -510,26 +517,30 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings)
throw love::Exception("Invalid gamepad mappings."); throw love::Exception("Invalid gamepad mappings.");
} }
std::string JoystickModule::saveGamepadMapping(const std::string &pguid) std::string JoystickModule::saveGamepadMappings()
{ {
SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(pguid.c_str()); std::string mappings;
std::string mapping; for (const auto &g : recentGamepadGUIDs)
char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid); {
SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(g.first.c_str());
if (sdlmapping == nullptr) char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid);
throw love::Exception("The specified Joystick GUID string has no gamepad mapping."); if (sdlmapping == nullptr)
continue;
mapping = sdlmapping; std::string mapping = sdlmapping;
SDL_free(sdlmapping); SDL_free(sdlmapping);
if (mapping.find_last_of(',') != mapping.size() - 1) if (mapping.find_last_of(',') != mapping.length() - 1)
mapping += ","; mapping += ",";
// Matches SDL_GameControllerAddMappingsFromRW. // Matches SDL_GameControllerAddMappingsFromRW.
mapping += "platform:" + std::string(SDL_GetPlatform()) + ","; mapping += "platform:" + std::string(SDL_GetPlatform()) + ",\n";
mappings += mapping;
}
return mapping; return mappings;
} }
} // sdl } // sdl
+6 -1
View File
@@ -28,6 +28,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <list> #include <list>
#include <map>
namespace love namespace love
{ {
@@ -57,7 +58,7 @@ public:
bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput); bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput);
Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput); Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput);
void loadGamepadMappings(const std::string &mappings); void loadGamepadMappings(const std::string &mappings);
std::string saveGamepadMapping(const std::string &pguid); std::string saveGamepadMappings();
private: private:
@@ -76,6 +77,10 @@ private:
// Persistent list of all Joysticks which have been connected at some point. // Persistent list of all Joysticks which have been connected at some point.
std::list<Joystick *> joysticks; std::list<Joystick *> joysticks;
// Persistent map indicating GUIDs for Gamepads which have been connected or
// modified at some point.
std::map<std::string, bool> recentGamepadGUIDs;
}; // JoystickModule }; // JoystickModule
} // sdl } // sdl
+1 -2
View File
@@ -119,7 +119,7 @@ int w_Joystick_getHat(lua_State *L)
Joystick::Hat h = j->getHat(hatindex); Joystick::Hat h = j->getHat(hatindex);
const char *direction = ""; const char *direction = "";
love::joystick::Joystick::getConstant(h, direction); Joystick::getConstant(h, direction);
lua_pushstring(L, direction); lua_pushstring(L, direction);
return 1; return 1;
@@ -249,7 +249,6 @@ static const luaL_Reg functions[] =
// From wrap_JoystickModule. // From wrap_JoystickModule.
{ "getConnectedIndex", w_getIndex }, { "getConnectedIndex", w_getIndex },
{ "getGamepadMapping", w_getGamepadMapping }, { "getGamepadMapping", w_getGamepadMapping },
{ "saveGamepadMapping", w_saveGamepadMapping },
{ 0, 0 }, { 0, 0 },
}; };
+23 -24
View File
@@ -39,7 +39,7 @@ int w_getJoysticks(lua_State *L)
for (int i = 0; i < stickcount; i++) for (int i = 0; i < stickcount; i++)
{ {
love::joystick::Joystick *stick = instance->getJoystick(i); Joystick *stick = instance->getJoystick(i);
stick->retain(); stick->retain();
luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick); luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick);
lua_rawseti(L, -2, i + 1); lua_rawseti(L, -2, i + 1);
@@ -50,7 +50,7 @@ int w_getJoysticks(lua_State *L)
int w_getIndex(lua_State *L) int w_getIndex(lua_State *L)
{ {
love::joystick::Joystick *j = luax_checkjoystick(L, 1); Joystick *j = luax_checkjoystick(L, 1);
int index = instance->getIndex(j); int index = instance->getIndex(j);
if (index >= 0) if (index >= 0)
lua_pushinteger(L, index + 1); lua_pushinteger(L, index + 1);
@@ -75,9 +75,9 @@ int w_setGamepadMapping(lua_State *L)
const char *gpbindstr = luaL_checkstring(L, 2); const char *gpbindstr = luaL_checkstring(L, 2);
Joystick::GamepadInput gpinput; Joystick::GamepadInput gpinput;
if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.axis)) if (Joystick::getConstant(gpbindstr, gpinput.axis))
gpinput.type = Joystick::INPUT_TYPE_AXIS; gpinput.type = Joystick::INPUT_TYPE_AXIS;
else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button)) else if (Joystick::getConstant(gpbindstr, gpinput.button))
gpinput.type = Joystick::INPUT_TYPE_BUTTON; gpinput.type = Joystick::INPUT_TYPE_BUTTON;
else else
return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr);
@@ -85,7 +85,7 @@ int w_setGamepadMapping(lua_State *L)
const char *jinputtypestr = luaL_checkstring(L, 3); const char *jinputtypestr = luaL_checkstring(L, 3);
Joystick::JoystickInput jinput; Joystick::JoystickInput jinput;
if (!love::joystick::Joystick::getConstant(jinputtypestr, jinput.type)) if (!Joystick::getConstant(jinputtypestr, jinput.type))
return luaL_error(L, "Invalid joystick input type: %s", jinputtypestr); return luaL_error(L, "Invalid joystick input type: %s", jinputtypestr);
const char *hatstr; const char *hatstr;
@@ -101,7 +101,7 @@ int w_setGamepadMapping(lua_State *L)
// Hats need both a hat index and a hat value. // Hats need both a hat index and a hat value.
jinput.hat.index = luaL_checkint(L, 4) - 1; jinput.hat.index = luaL_checkint(L, 4) - 1;
hatstr = luaL_checkstring(L, 5); hatstr = luaL_checkstring(L, 5);
if (!love::joystick::Joystick::getConstant(hatstr, jinput.hat.value)) if (!Joystick::getConstant(hatstr, jinput.hat.value))
return luaL_error(L, "Invalid joystick hat: %s", hatstr); return luaL_error(L, "Invalid joystick hat: %s", hatstr);
break; break;
default: default:
@@ -125,16 +125,16 @@ int w_getGamepadMapping(lua_State *L)
guid = luax_checkstring(L, 1); guid = luax_checkstring(L, 1);
else else
{ {
love::joystick::Joystick *stick = luax_checkjoystick(L, 1); Joystick *stick = luax_checkjoystick(L, 1);
guid = stick->getGUID(); guid = stick->getGUID();
} }
const char *gpbindstr = luaL_checkstring(L, 2); const char *gpbindstr = luaL_checkstring(L, 2);
Joystick::GamepadInput gpinput; Joystick::GamepadInput gpinput;
if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.axis)) if (Joystick::getConstant(gpbindstr, gpinput.axis))
gpinput.type = Joystick::INPUT_TYPE_AXIS; gpinput.type = Joystick::INPUT_TYPE_AXIS;
else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button)) else if (Joystick::getConstant(gpbindstr, gpinput.button))
gpinput.type = Joystick::INPUT_TYPE_BUTTON; gpinput.type = Joystick::INPUT_TYPE_BUTTON;
else else
return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr);
@@ -148,7 +148,7 @@ int w_getGamepadMapping(lua_State *L)
return 0; return 0;
const char *inputtypestr; const char *inputtypestr;
if (!love::joystick::Joystick::getConstant(jinput.type, inputtypestr)) if (!Joystick::getConstant(jinput.type, inputtypestr))
return luaL_error(L, "Unknown joystick input type."); return luaL_error(L, "Unknown joystick input type.");
lua_pushstring(L, inputtypestr); lua_pushstring(L, inputtypestr);
@@ -164,7 +164,7 @@ int w_getGamepadMapping(lua_State *L)
return 2; return 2;
case Joystick::INPUT_TYPE_HAT: case Joystick::INPUT_TYPE_HAT:
lua_pushinteger(L, jinput.hat.index + 1); lua_pushinteger(L, jinput.hat.index + 1);
if (love::joystick::Joystick::getConstant(jinput.hat.value, hatstr)) if (Joystick::getConstant(jinput.hat.value, hatstr))
{ {
lua_pushstring(L, hatstr); lua_pushstring(L, hatstr);
return 3; return 3;
@@ -201,23 +201,22 @@ int w_loadGamepadMappings(lua_State *L)
return 0; return 0;
} }
int w_saveGamepadMapping(lua_State *L) int w_saveGamepadMappings(lua_State *L)
{ {
std::string guid, mapping; lua_settop(L, 1);
std::string mappings = instance->saveGamepadMappings();
// Accept either a GUID string or a Joystick object. This way we can re-use // Optionally write the mappings string to a file.
// the function for Joystick:getGamepadMapping. if (!lua_isnoneornil(L, 1))
if (lua_type(L, 1) == LUA_TSTRING)
guid = luax_checkstring(L, 1);
else
{ {
love::joystick::Joystick *stick = luax_checkjoystick(L, 1); luax_pushstring(L, mappings);
guid = stick->getGUID(); int idxs[] = {1, 2};
luax_convobj(L, idxs, 2, "filesystem", "write");
lua_pop(L, 1); // Pop the return value.
} }
luax_catchexcept(L, [&](){ mapping = instance->saveGamepadMapping(guid); }); // Return the actual string even if we also wrote it to a file.
luax_pushstring(L, mappings);
luax_pushstring(L, mapping);
return 1; return 1;
} }
@@ -229,7 +228,7 @@ static const luaL_Reg functions[] =
{ "setGamepadMapping", w_setGamepadMapping }, { "setGamepadMapping", w_setGamepadMapping },
{ "getGamepadMapping", w_getGamepadMapping }, { "getGamepadMapping", w_getGamepadMapping },
{ "loadGamepadMappings", w_loadGamepadMappings }, { "loadGamepadMappings", w_loadGamepadMappings },
{ "saveGamepadMapping", w_saveGamepadMapping }, { "saveGamepadMappings", w_saveGamepadMappings },
{ 0, 0 } { 0, 0 }
}; };
+1 -1
View File
@@ -37,7 +37,7 @@ int w_getJoystickCount(lua_State *L);
int w_setGamepadMapping(lua_State *L); int w_setGamepadMapping(lua_State *L);
int w_getGamepadMapping(lua_State *L); int w_getGamepadMapping(lua_State *L);
int w_loadGamepadMappings(lua_State *L); int w_loadGamepadMappings(lua_State *L);
int w_saveGamepadMapping(lua_State *L); int w_saveGamepadMappings(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_joystick(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_joystick(lua_State *L);
} // joystick } // joystick