Browse Source

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.

Alex Szpakowski 11 years ago
parent
commit
ddb9997ead

+ 4 - 3
src/modules/joystick/JoystickModule.h

@@ -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
src/modules/joystick/sdl/JoystickModule.cpp

@@ -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;
-	char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid);
+	for (const auto &g : recentGamepadGUIDs)
+	{
+		SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(g.first.c_str());
 
 
-	if (sdlmapping == nullptr)
-		throw love::Exception("The specified Joystick GUID string has no gamepad mapping.");
+		char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid);
+		if (sdlmapping == nullptr)
+			continue;
 
 
-	mapping = sdlmapping;
-	SDL_free(sdlmapping);
+		std::string mapping = sdlmapping;
+		SDL_free(sdlmapping);
 
 
-	if (mapping.find_last_of(',') != mapping.size() - 1)
-		mapping += ",";
+		if (mapping.find_last_of(',') != mapping.length() - 1)
+			mapping += ",";
 
 
-	// Matches SDL_GameControllerAddMappingsFromRW.
-	mapping += "platform:" + std::string(SDL_GetPlatform()) + ",";
+		// Matches SDL_GameControllerAddMappingsFromRW.
+		mapping += "platform:" + std::string(SDL_GetPlatform()) + ",\n";
+		mappings += mapping;
+	}
 
 
-	return mapping;
+	return mappings;
 }
 }
 
 
 } // sdl
 } // sdl

+ 6 - 1
src/modules/joystick/sdl/JoystickModule.h

@@ -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
src/modules/joystick/wrap_Joystick.cpp

@@ -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
src/modules/joystick/wrap_JoystickModule.cpp

@@ -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
-	// the function for Joystick:getGamepadMapping.
-	if (lua_type(L, 1) == LUA_TSTRING)
-		guid = luax_checkstring(L, 1);
-	else
+	// Optionally write the mappings string to a file.
+	if (!lua_isnoneornil(L, 1))
 	{
 	{
-		love::joystick::Joystick *stick = luax_checkjoystick(L, 1);
-		guid = stick->getGUID();
+		luax_pushstring(L, mappings);
+		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); });
-
-	luax_pushstring(L, mapping);
+	// Return the actual string even if we also wrote it to a file.
+	luax_pushstring(L, mappings);
 	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
src/modules/joystick/wrap_JoystickModule.h

@@ -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