Browse Source

Merged rude/love into default

muddmaker 10 years ago
parent
commit
640da48368
37 changed files with 438 additions and 58 deletions
  1. 103 3
      license.txt
  2. 12 12
      platform/macosx/love.xcodeproj/project.pbxproj
  3. 1 1
      src/libraries/ddsparse/ddsparse.cpp
  4. 1 1
      src/libraries/ddsparse/ddsparse.h
  5. 77 23
      src/libraries/enet/enet.cpp
  6. 1 1
      src/modules/font/GlyphData.cpp
  7. 2 2
      src/modules/font/Rasterizer.cpp
  8. 2 2
      src/modules/font/freetype/Font.cpp
  9. 2 2
      src/modules/graphics/opengl/Font.cpp
  10. 17 3
      src/modules/graphics/opengl/Image.cpp
  11. 4 0
      src/modules/image/CompressedData.cpp
  12. 4 0
      src/modules/image/CompressedData.h
  13. 8 2
      src/modules/image/magpie/ddsHandler.cpp
  14. 8 0
      src/modules/joystick/sdl/JoystickModule.cpp
  15. 9 5
      src/modules/joystick/wrap_JoystickModule.cpp
  16. 27 0
      src/modules/physics/box2d/Body.cpp
  17. 5 0
      src/modules/physics/box2d/Body.h
  18. 27 0
      src/modules/physics/box2d/GearJoint.cpp
  19. 3 0
      src/modules/physics/box2d/GearJoint.h
  20. 28 0
      src/modules/physics/box2d/Joint.cpp
  21. 3 1
      src/modules/physics/box2d/Joint.h
  22. 10 0
      src/modules/physics/box2d/wrap_Body.cpp
  23. 1 0
      src/modules/physics/box2d/wrap_Body.h
  24. 1 0
      src/modules/physics/box2d/wrap_DistanceJoint.cpp
  25. 1 0
      src/modules/physics/box2d/wrap_FrictionJoint.cpp
  26. 18 0
      src/modules/physics/box2d/wrap_GearJoint.cpp
  27. 1 0
      src/modules/physics/box2d/wrap_GearJoint.h
  28. 52 0
      src/modules/physics/box2d/wrap_Joint.cpp
  29. 2 0
      src/modules/physics/box2d/wrap_Joint.h
  30. 1 0
      src/modules/physics/box2d/wrap_MotorJoint.cpp
  31. 1 0
      src/modules/physics/box2d/wrap_MouseJoint.cpp
  32. 1 0
      src/modules/physics/box2d/wrap_PrismaticJoint.cpp
  33. 1 0
      src/modules/physics/box2d/wrap_PulleyJoint.cpp
  34. 1 0
      src/modules/physics/box2d/wrap_RevoluteJoint.cpp
  35. 1 0
      src/modules/physics/box2d/wrap_RopeJoint.cpp
  36. 1 0
      src/modules/physics/box2d/wrap_WeldJoint.cpp
  37. 1 0
      src/modules/physics/box2d/wrap_WheelJoint.cpp

+ 103 - 3
license.txt

@@ -1,4 +1,6 @@
-Copyright (c) 2006-2014 LOVE Development Team
+This software uses LÖVE:
+
+LÖVE is Copyright (c) 2006-2014 LOVE Development Team
 
 
 This software is provided 'as-is', without any express or implied
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages
 warranty. In no event will the authors be held liable for any damages
@@ -19,11 +21,109 @@ misrepresented as being the original software.
 3. This notice may not be removed or altered from any source
 3. This notice may not be removed or altered from any source
 distribution.
 distribution.
 
 
+---------
+
+This software uses LuaJIT:
+
+LuaJIT is Copyright (c) 2005-2014 Mike Pall
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+---------
+
+This software uses ENet:
+
+Copyright (c) 2002-2014 Lee Salzman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+---------
+
+This software uses lua-enet:
+
+Copyright (C) 2011 by Leaf Corcoran
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+---------
+
+This software uses UTF8-CPP:
+
+Copyright 2006 Nemanja Trifunovic
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
 
 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
 
 
--------
+---------
 
 
-LÖVE uses the following LGPL libraries:
+This software uses the following LGPL libraries:
 
 
  - libmpg123
  - libmpg123
      Website: http://www.mpg123.de/
      Website: http://www.mpg123.de/

+ 12 - 12
platform/macosx/love.xcodeproj/project.pbxproj

@@ -8,23 +8,23 @@
 
 
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
 		8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
 		8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
-		A9255DD11043183600BA1496 /* FreeType.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E4810420B4A007D418B /* FreeType.framework */; };
-		A9255DD31043183600BA1496 /* Lua.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E5310420B57007D418B /* Lua.framework */; };
-		A9255E031043195A00BA1496 /* Vorbis.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255E021043195A00BA1496 /* Vorbis.framework */; };
-		A9255F431043240F00BA1496 /* IL.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255F421043240F00BA1496 /* IL.framework */; };
-		A9255F58104324E100BA1496 /* Ogg.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255F51104324D700BA1496 /* Ogg.framework */; };
+		A9255DD11043183600BA1496 /* FreeType.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E4810420B4A007D418B /* FreeType.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		A9255DD31043183600BA1496 /* Lua.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E5310420B57007D418B /* Lua.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		A9255E031043195A00BA1496 /* Vorbis.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255E021043195A00BA1496 /* Vorbis.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		A9255F431043240F00BA1496 /* IL.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255F421043240F00BA1496 /* IL.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		A9255F58104324E100BA1496 /* Ogg.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9255F51104324D700BA1496 /* Ogg.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A93E6E5510420B57007D418B /* Lua.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E5310420B57007D418B /* Lua.framework */; };
 		A93E6E5510420B57007D418B /* Lua.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A93E6E5310420B57007D418B /* Lua.framework */; };
 		A93E6EED10420BA8007D418B /* love.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6A3410420AC0007D418B /* love.cpp */; };
 		A93E6EED10420BA8007D418B /* love.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A93E6A3410420AC0007D418B /* love.cpp */; };
-		A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; };
+		A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9DEC1C11046EFA70049C70C /* Love.icns in Resources */ = {isa = PBXBuildFile; fileRef = A9DEC1BF1046EFA60049C70C /* Love.icns */; };
 		A9DEC1C11046EFA70049C70C /* Love.icns in Resources */ = {isa = PBXBuildFile; fileRef = A9DEC1BF1046EFA60049C70C /* Love.icns */; };
 		A9DEC1C21046EFA70049C70C /* LoveDocument.icns in Resources */ = {isa = PBXBuildFile; fileRef = A9DEC1C01046EFA70049C70C /* LoveDocument.icns */; };
 		A9DEC1C21046EFA70049C70C /* LoveDocument.icns in Resources */ = {isa = PBXBuildFile; fileRef = A9DEC1C01046EFA70049C70C /* LoveDocument.icns */; };
-		A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; };
-		A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; };
+		A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
 		FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
-		FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
+		FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		FA9B4A0A16E1579F00074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; };
 		FA9B4A0A16E1579F00074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; };
-		FA9B4A0B16E157B500074F42 /* SDL2.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; };
-		FAAFF04716CB120000CCDE45 /* OpenAL-Soft.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04616CB120000CCDE45 /* OpenAL-Soft.framework */; };
+		FA9B4A0B16E157B500074F42 /* SDL2.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		FAAFF04716CB120000CCDE45 /* OpenAL-Soft.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04616CB120000CCDE45 /* OpenAL-Soft.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		FAC1A449196F5DC600125284 /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = FAC1A448196F5DC600125284 /* license.txt */; };
 		FAC1A449196F5DC600125284 /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = FAC1A448196F5DC600125284 /* license.txt */; };
 		FAC8E8D416F3C468004DADF3 /* OSX.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAC8E8D316F3C468004DADF3 /* OSX.mm */; };
 		FAC8E8D416F3C468004DADF3 /* OSX.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAC8E8D316F3C468004DADF3 /* OSX.mm */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
@@ -201,7 +201,7 @@
 		29B97313FDCFA39411CA2CEA /* Project object */ = {
 		29B97313FDCFA39411CA2CEA /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
-				LastUpgradeCheck = 0510;
+				LastUpgradeCheck = 0610;
 			};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "love" */;
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "love" */;
 			compatibilityVersion = "Xcode 3.2";
 			compatibilityVersion = "Xcode 3.2";

+ 1 - 1
src/libraries/ddsparse/ddsparse.cpp

@@ -116,7 +116,7 @@ static Format parseDX10Format(DXGIFormat fmt)
 		f = FORMAT_BC6H;
 		f = FORMAT_BC6H;
 		break;
 		break;
 	case DXGI_FORMAT_BC6H_SF16:
 	case DXGI_FORMAT_BC6H_SF16:
-		f = FORAMT_BC6Hs;
+		f = FORMAT_BC6Hs;
 		break;
 		break;
 	case DXGI_FORMAT_BC7_TYPELESS:
 	case DXGI_FORMAT_BC7_TYPELESS:
 	case DXGI_FORMAT_BC7_UNORM:
 	case DXGI_FORMAT_BC7_UNORM:

+ 1 - 1
src/libraries/ddsparse/ddsparse.h

@@ -45,7 +45,7 @@ enum Format
 	FORMAT_BC5,
 	FORMAT_BC5,
 	FORMAT_BC5s,
 	FORMAT_BC5s,
 	FORMAT_BC6H,
 	FORMAT_BC6H,
-	FORAMT_BC6Hs,
+	FORMAT_BC6Hs,
 	FORMAT_BC7,
 	FORMAT_BC7,
 	FORMAT_BC7srgb, // sRGB color space.
 	FORMAT_BC7srgb, // sRGB color space.
 	FORMAT_UNKNOWN
 	FORMAT_UNKNOWN

+ 77 - 23
src/libraries/enet/enet.cpp

@@ -1,6 +1,6 @@
 /**
 /**
  *
  *
- * Copyright (C) 2011 by Leaf Corcoran
+ * Copyright (C) 2014 by Leaf Corcoran
  * 
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * of this software and associated documentation files (the "Software"), to deal
@@ -40,9 +40,9 @@ extern "C" {
 
 
 /**
 /**
  * Parse address string, eg:
  * Parse address string, eg:
- * 	*:5959
- * 	127.0.0.1:*
- * 	website.com:8080
+ *	*:5959
+ *	127.0.0.1:*
+ *	website.com:8080
  */
  */
 static void parse_address(lua_State *l, const char *addr_str, ENetAddress *address) {
 static void parse_address(lua_State *l, const char *addr_str, ENetAddress *address) {
 	int host_i = 0, port_i = 0;
 	int host_i = 0, port_i = 0;
@@ -204,11 +204,11 @@ static ENetPacket *read_packet(lua_State *l, int idx, enet_uint8 *channel_id) {
 /**
 /**
  * Create a new host
  * Create a new host
  * Args:
  * Args:
- * 	address (nil for client)
- * 	[peer_count = 64]
- * 	[channel_count = 1]
- * 	[in_bandwidth = 0]
- * 	[out_bandwidth = 0]
+ *	address (nil for client)
+ *	[peer_count = 64]
+ *	[channel_count = 1]
+ *	[in_bandwidth = 0]
+ *	[out_bandwidth = 0]
  */
  */
 static int host_create(lua_State *l) {
 static int host_create(lua_State *l) {
 	ENetHost *host;
 	ENetHost *host;
@@ -236,7 +236,7 @@ static int host_create(lua_State *l) {
 	}
 	}
 
 
 	// printf("host create, peers=%d, channels=%d, in=%d, out=%d\n",
 	// printf("host create, peers=%d, channels=%d, in=%d, out=%d\n",
-	// 		peer_count, channel_count, in_bandwidth, out_bandwidth);
+	//		peer_count, channel_count, in_bandwidth, out_bandwidth);
 	host = enet_host_create(have_address ? &address : NULL, peer_count,
 	host = enet_host_create(have_address ? &address : NULL, peer_count,
 			channel_count, in_bandwidth, out_bandwidth);
 			channel_count, in_bandwidth, out_bandwidth);
 
 
@@ -264,14 +264,17 @@ static int linked_version(lua_State *l) {
 /**
 /**
  * Serice a host
  * Serice a host
  * Args:
  * Args:
- * 	timeout
+ *	timeout
  *
  *
  * Return
  * Return
- * 	nil on no event
- * 	an event table on event
+ *	nil on no event
+ *	an event table on event
  */
  */
 static int host_service(lua_State *l) {
 static int host_service(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	ENetEvent event;
 	ENetEvent event;
 	int timeout = 0, out;
 	int timeout = 0, out;
 
 
@@ -291,6 +294,9 @@ static int host_service(lua_State *l) {
  */
  */
 static int host_check_events(lua_State *l) {
 static int host_check_events(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	ENetEvent event;
 	ENetEvent event;
 	int out = enet_host_check_events(host, &event);
 	int out = enet_host_check_events(host, &event);
 	if (out == 0) return 0;
 	if (out == 0) return 0;
@@ -306,6 +312,9 @@ static int host_check_events(lua_State *l) {
  */
  */
 static int host_compress_with_range_coder(lua_State *l) {
 static int host_compress_with_range_coder(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	int result = enet_host_compress_with_range_coder (host);
 	int result = enet_host_compress_with_range_coder (host);
 	if (result == 0) {
 	if (result == 0) {
@@ -320,12 +329,15 @@ static int host_compress_with_range_coder(lua_State *l) {
 /**
 /**
  * Connect a host to an address
  * Connect a host to an address
  * Args:
  * Args:
- * 	the address
- * 	[channel_count = 1]
- * 	[data = 0]
+ *	the address
+ *	[channel_count = 1]
+ *	[data = 0]
  */
  */
 static int host_connect(lua_State *l) {
 static int host_connect(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	ENetAddress address;
 	ENetAddress address;
 	ENetPeer *peer;
 	ENetPeer *peer;
 
 
@@ -355,12 +367,18 @@ static int host_connect(lua_State *l) {
 
 
 static int host_flush(lua_State *l) {
 static int host_flush(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	enet_host_flush(host);
 	enet_host_flush(host);
 	return 0;
 	return 0;
 }
 }
 
 
 static int host_broadcast(lua_State *l) {
 static int host_broadcast(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	enet_uint8 channel_id;
 	enet_uint8 channel_id;
 	ENetPacket *packet = read_packet(l, 2, &channel_id);
 	ENetPacket *packet = read_packet(l, 2, &channel_id);
@@ -371,6 +389,9 @@ static int host_broadcast(lua_State *l) {
 // Args: limit:number
 // Args: limit:number
 static int host_channel_limit(lua_State *l) {
 static int host_channel_limit(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	int limit = luaL_checkint(l, 2);
 	int limit = luaL_checkint(l, 2);
 	enet_host_channel_limit(host, limit);
 	enet_host_channel_limit(host, limit);
 	return 0;
 	return 0;
@@ -378,14 +399,20 @@ static int host_channel_limit(lua_State *l) {
 
 
 static int host_bandwidth_limit(lua_State *l) {
 static int host_bandwidth_limit(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	enet_uint32 in_bandwidth = luaL_checkint(l, 2);
 	enet_uint32 in_bandwidth = luaL_checkint(l, 2);
 	enet_uint32 out_bandwidth = luaL_checkint(l, 2);
 	enet_uint32 out_bandwidth = luaL_checkint(l, 2);
 	enet_host_bandwidth_limit(host, in_bandwidth, out_bandwidth);
 	enet_host_bandwidth_limit(host, in_bandwidth, out_bandwidth);
 	return 0;
 	return 0;
 }
 }
 
 
-static int host_socket_get_address(lua_State *l) {
+static int host_get_socket_address(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 	ENetAddress address;
 	ENetAddress address;
 	enet_socket_get_address (host->socket, &address);
 	enet_socket_get_address (host->socket, &address);
 
 
@@ -399,6 +426,9 @@ static int host_socket_get_address(lua_State *l) {
 }
 }
 static int host_total_sent_data(lua_State *l) {
 static int host_total_sent_data(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	lua_pushinteger (l, host->totalSentData);
 	lua_pushinteger (l, host->totalSentData);
 
 
@@ -407,6 +437,9 @@ static int host_total_sent_data(lua_State *l) {
 
 
 static int host_total_received_data(lua_State *l) {
 static int host_total_received_data(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	lua_pushinteger (l, host->totalReceivedData);
 	lua_pushinteger (l, host->totalReceivedData);
 
 
@@ -414,6 +447,9 @@ static int host_total_received_data(lua_State *l) {
 }
 }
 static int host_service_time(lua_State *l) {
 static int host_service_time(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	lua_pushinteger (l, host->serviceTime);
 	lua_pushinteger (l, host->serviceTime);
 
 
@@ -422,6 +458,9 @@ static int host_service_time(lua_State *l) {
 
 
 static int host_peer_count(lua_State *l) {
 static int host_peer_count(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	lua_pushinteger (l, host->peerCount);
 	lua_pushinteger (l, host->peerCount);
 
 
@@ -430,6 +469,9 @@ static int host_peer_count(lua_State *l) {
 
 
 static int host_get_peer(lua_State *l) {
 static int host_get_peer(lua_State *l) {
 	ENetHost *host = check_host(l, 1);
 	ENetHost *host = check_host(l, 1);
+	if (!host) {
+		return luaL_error(l, "Tried to index a nil host!");
+	}
 
 
 	int peer_index = luaL_checkint(l, 2) - 1;
 	int peer_index = luaL_checkint(l, 2) - 1;
 
 
@@ -444,8 +486,13 @@ static int host_get_peer(lua_State *l) {
 }
 }
 
 
 static int host_gc(lua_State *l) {
 static int host_gc(lua_State *l) {
-	ENetHost *host = check_host(l, 1);
-	enet_host_destroy(host);
+	// We have to manually grab the userdata so that we can set it to NULL.
+	ENetHost** host = (ENetHost**)luaL_checkudata(l, 1, "enet_host");
+	// We don't want to crash by destroying a non-existant host.
+	if (*host) {
+		enet_host_destroy(*host);
+	}
+	*host = NULL;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -653,9 +700,9 @@ static int peer_receive(lua_State *l) {
 /**
 /**
  * Send a lua string to a peer
  * Send a lua string to a peer
  * Args:
  * Args:
- * 	packet data, string
- * 	channel id
- * 	flags ["reliable", nil]
+ *	packet data, string
+ *	channel id
+ *	flags ["reliable", nil]
  *
  *
  */
  */
 static int peer_send(lua_State *l) {
 static int peer_send(lua_State *l) {
@@ -684,7 +731,14 @@ static const struct luaL_Reg enet_host_funcs [] = {
 	{"broadcast", host_broadcast},
 	{"broadcast", host_broadcast},
 	{"channel_limit", host_channel_limit},
 	{"channel_limit", host_channel_limit},
 	{"bandwidth_limit", host_bandwidth_limit},
 	{"bandwidth_limit", host_bandwidth_limit},
-	{"socket_get_address", host_socket_get_address},
+	// Since ENetSocket isn't part of enet-lua, we should try to keep
+	// naming conventions the same as the rest of the lib.
+	{"get_socket_address", host_get_socket_address},
+	// TODO: Remove the line below in future versions, it's for backward
+	// compatibility only.
+	{"socket_get_address", host_get_socket_address},
+	// We need this function to free up our ports when needed!
+	{"destroy", host_gc},
 
 
 	// additional convenience functions (mostly accessors)
 	// additional convenience functions (mostly accessors)
 	{"total_sent_data", host_total_sent_data},
 	{"total_sent_data", host_total_sent_data},

+ 1 - 1
src/modules/font/GlyphData.cpp

@@ -106,7 +106,7 @@ std::string GlyphData::getGlyphString() const
 	}
 	}
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	// Just in case...
 	// Just in case...

+ 2 - 2
src/modules/font/Rasterizer.cpp

@@ -63,7 +63,7 @@ GlyphData *Rasterizer::getGlyphData(const std::string &text) const
 	}
 	}
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	return getGlyphData(codepoint);
 	return getGlyphData(codepoint);
@@ -89,7 +89,7 @@ bool Rasterizer::hasGlyphs(const std::string &text) const
 	}
 	}
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	return true;
 	return true;

+ 2 - 2
src/modules/font/freetype/Font.cpp

@@ -66,7 +66,7 @@ Rasterizer *Font::newRasterizer(love::image::ImageData *data, const std::string
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
 		delete [] glyphs;
 		delete [] glyphs;
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	Rasterizer *r = newRasterizer(data, glyphs, numglyphs);
 	Rasterizer *r = newRasterizer(data, glyphs, numglyphs);
@@ -90,7 +90,7 @@ GlyphData *Font::newGlyphData(Rasterizer *r, const std::string &text)
 	}
 	}
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	return r->getGlyphData(codepoint);
 	return r->getGlyphData(codepoint);

+ 2 - 2
src/modules/graphics/opengl/Font.cpp

@@ -367,7 +367,7 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing,
 	}
 	}
 	catch (utf8::exception &e)
 	catch (utf8::exception &e)
 	{
 	{
-		throw love::Exception("Decoding error: %s", e.what());
+		throw love::Exception("UTF-8 decoding error: %s", e.what());
 	}
 	}
 
 
 	if (vertexcount <= 0 || glyphinfolist.size() == 0)
 	if (vertexcount <= 0 || glyphinfolist.size() == 0)
@@ -429,7 +429,7 @@ int Font::getWidth(const std::string &str)
 		}
 		}
 		catch(utf8::exception &e)
 		catch(utf8::exception &e)
 		{
 		{
-			throw love::Exception("Decoding error: %s", e.what());
+			throw love::Exception("UTF-8 decoding error: %s", e.what());
 		}
 		}
 
 
 		if (width > max_width)
 		if (width > max_width)

+ 17 - 3
src/modules/graphics/opengl/Image.cpp

@@ -623,6 +623,17 @@ GLenum Image::getCompressedFormat(image::CompressedData::Format cformat) const
 		return GL_COMPRESSED_RG_RGTC2;
 		return GL_COMPRESSED_RG_RGTC2;
 	case image::CompressedData::FORMAT_BC5s:
 	case image::CompressedData::FORMAT_BC5s:
 		return GL_COMPRESSED_SIGNED_RG_RGTC2;
 		return GL_COMPRESSED_SIGNED_RG_RGTC2;
+	case image::CompressedData::FORMAT_BC6H:
+		return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
+	case image::CompressedData::FORMAT_BC6Hs:
+		return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
+	case image::CompressedData::FORMAT_BC7:
+		if (srgb)
+			return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
+		else
+			return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
+	case image::CompressedData::FORMAT_BC7SRGB:
+		return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
 	default:
 	default:
 		if (srgb)
 		if (srgb)
 			return GL_SRGB8_ALPHA8;
 			return GL_SRGB8_ALPHA8;
@@ -672,11 +683,14 @@ bool Image::hasCompressedTextureSupport(image::CompressedData::Format format)
 	case image::CompressedData::FORMAT_BC5:
 	case image::CompressedData::FORMAT_BC5:
 	case image::CompressedData::FORMAT_BC5s:
 	case image::CompressedData::FORMAT_BC5s:
 		return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc);
 		return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc);
+	case image::CompressedData::FORMAT_BC6H:
+	case image::CompressedData::FORMAT_BC6Hs:
+	case image::CompressedData::FORMAT_BC7:
+	case image::CompressedData::FORMAT_BC7SRGB:
+		return GLEE_VERSION_4_2 || GLEE_ARB_texture_compression_bptc;
 	default:
 	default:
-		break;
+		return false;
 	}
 	}
-
-	return false;
 }
 }
 
 
 bool Image::hasSRGBSupport()
 bool Image::hasSRGBSupport()

+ 4 - 0
src/modules/image/CompressedData.cpp

@@ -110,6 +110,10 @@ StringMap<CompressedData::Format, CompressedData::FORMAT_MAX_ENUM>::Entry Compre
 	{"bc4s", CompressedData::FORMAT_BC4s},
 	{"bc4s", CompressedData::FORMAT_BC4s},
 	{"bc5", CompressedData::FORMAT_BC5},
 	{"bc5", CompressedData::FORMAT_BC5},
 	{"bc5s", CompressedData::FORMAT_BC5s},
 	{"bc5s", CompressedData::FORMAT_BC5s},
+	{"bc6h", CompressedData::FORMAT_BC6H},
+	{"bc6hs", CompressedData::FORMAT_BC6Hs},
+	{"bc7", CompressedData::FORMAT_BC7},
+	{"bc7srgb", CompressedData::FORMAT_BC7SRGB},
 };
 };
 
 
 StringMap<CompressedData::Format, CompressedData::FORMAT_MAX_ENUM> CompressedData::formats(CompressedData::formatEntries, sizeof(CompressedData::formatEntries));
 StringMap<CompressedData::Format, CompressedData::FORMAT_MAX_ENUM> CompressedData::formats(CompressedData::formatEntries, sizeof(CompressedData::formatEntries));

+ 4 - 0
src/modules/image/CompressedData.h

@@ -54,6 +54,10 @@ public:
 		FORMAT_BC4s,
 		FORMAT_BC4s,
 		FORMAT_BC5,
 		FORMAT_BC5,
 		FORMAT_BC5s,
 		FORMAT_BC5s,
+		FORMAT_BC6H,
+		FORMAT_BC6Hs,
+		FORMAT_BC7,
+		FORMAT_BC7SRGB,
 		FORMAT_MAX_ENUM
 		FORMAT_MAX_ENUM
 	};
 	};
 
 

+ 8 - 2
src/modules/image/magpie/ddsHandler.cpp

@@ -117,11 +117,17 @@ CompressedData::Format ddsHandler::convertFormat(dds::Format ddsformat)
 		return CompressedData::FORMAT_BC5;
 		return CompressedData::FORMAT_BC5;
 	case dds::FORMAT_BC5s:
 	case dds::FORMAT_BC5s:
 		return CompressedData::FORMAT_BC5s;
 		return CompressedData::FORMAT_BC5s;
+	case dds::FORMAT_BC6H:
+		return CompressedData::FORMAT_BC6H;
+	case dds::FORMAT_BC6Hs:
+		return CompressedData::FORMAT_BC6Hs;
+	case dds::FORMAT_BC7:
+		return CompressedData::FORMAT_BC7;
+	case dds::FORMAT_BC7srgb:
+		return CompressedData::FORMAT_BC7SRGB;
 	default:
 	default:
 		return CompressedData::FORMAT_UNKNOWN;
 		return CompressedData::FORMAT_UNKNOWN;
 	}
 	}
-
-	return CompressedData::FORMAT_UNKNOWN;
 }
 }
 
 
 } // magpie
 } // magpie

+ 8 - 0
src/modules/joystick/sdl/JoystickModule.cpp

@@ -489,6 +489,10 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings)
 		if (mapping.empty())
 		if (mapping.empty())
 			continue;
 			continue;
 
 
+		// Lines starting with "#" are comments.
+		if (mapping[0] == '#')
+			continue;
+
 		// Strip out and compare any "platform:XYZ," in the mapping.
 		// Strip out and compare any "platform:XYZ," in the mapping.
 		size_t pstartpos = mapping.find("platform:");
 		size_t pstartpos = mapping.find("platform:");
 		if (pstartpos != std::string::npos)
 		if (pstartpos != std::string::npos)
@@ -499,7 +503,11 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings)
 			std::string platform = mapping.substr(pstartpos, pendpos - pstartpos);
 			std::string platform = mapping.substr(pstartpos, pendpos - pstartpos);
 
 
 			if (platform.compare(SDL_GetPlatform()) != 0)
 			if (platform.compare(SDL_GetPlatform()) != 0)
+			{
+				// Ignore the mapping but still acknowledge that it is one.
+				success = true;
 				continue;
 				continue;
+			}
 
 
 			pstartpos -= strlen("platform:");
 			pstartpos -= strlen("platform:");
 			mapping.erase(pstartpos, pendpos - pstartpos + 1);
 			mapping.erase(pstartpos, pendpos - pstartpos + 1);

+ 9 - 5
src/modules/joystick/wrap_JoystickModule.cpp

@@ -179,13 +179,17 @@ int w_getGamepadMapping(lua_State *L)
 
 
 int w_loadGamepadMappings(lua_State *L)
 int w_loadGamepadMappings(lua_State *L)
 {
 {
-	lua_pushvalue(L, 1);
-	luax_convobj(L, -1, "filesystem", "isFile");
-	bool isfile = luax_toboolean(L, -1);
-	lua_pop(L, 1);
-
+	bool isfile = true;
 	std::string mappings;
 	std::string mappings;
 
 
+	if (lua_isstring(L, 1))
+	{
+		lua_pushvalue(L, 1);
+		luax_convobj(L, -1, "filesystem", "isFile");
+		isfile = luax_toboolean(L, -1);
+		lua_pop(L, 1);
+	}
+
 	if (isfile)
 	if (isfile)
 	{
 	{
 		love::filesystem::FileData *fd = love::filesystem::luax_getfiledata(L, 1);
 		love::filesystem::FileData *fd = love::filesystem::luax_getfiledata(L, 1);

+ 27 - 0
src/modules/physics/box2d/Body.cpp

@@ -28,6 +28,9 @@
 #include "World.h"
 #include "World.h"
 #include "Physics.h"
 #include "Physics.h"
 
 
+// Needed for luax_pushjoint.
+#include "wrap_Joint.h"
+
 namespace love
 namespace love
 {
 {
 namespace physics
 namespace physics
@@ -440,6 +443,30 @@ int Body::getFixtureList(lua_State *L) const
 	return 1;
 	return 1;
 }
 }
 
 
+int Body::getJointList(lua_State *L) const
+{
+	lua_newtable(L);
+	const b2JointEdge *je = body->GetJointList();
+	int i = 1;
+
+	do
+	{
+		if (!je)
+			break;
+
+		Joint *joint = (Joint *) Memoizer::find(je->joint);
+		if (!joint)
+			throw love::Exception("A joint has escaped Memoizer!");
+
+		luax_pushjoint(L, joint);
+		lua_rawseti(L, -2, i);
+		i++;
+	}
+	while ((je = je->next));
+
+	return 1;
+}
+
 int Body::getContactList(lua_State *L) const
 int Body::getContactList(lua_State *L) const
 {
 {
 	lua_newtable(L);
 	lua_newtable(L);

+ 5 - 0
src/modules/physics/box2d/Body.h

@@ -393,6 +393,11 @@ public:
 	 **/
 	 **/
 	int getFixtureList(lua_State *L) const;
 	int getFixtureList(lua_State *L) const;
 
 
+	/**
+	 * Get an array of all Joints attached to this Body.
+	 **/
+	int getJointList(lua_State *L) const;
+
 	/**
 	/**
 	 * Get an array of all active Contacts attached to this Body.
 	 * Get an array of all active Contacts attached to this Body.
 	 * This list changes during World:update and you may miss some collisions
 	 * This list changes during World:update and you may miss some collisions

+ 27 - 0
src/modules/physics/box2d/GearJoint.cpp

@@ -23,6 +23,7 @@
 // Module
 // Module
 #include "Body.h"
 #include "Body.h"
 #include "World.h"
 #include "World.h"
+#include "common/Memoizer.h"
 
 
 namespace love
 namespace love
 {
 {
@@ -60,6 +61,32 @@ float GearJoint::getRatio() const
 	return joint->GetRatio();
 	return joint->GetRatio();
 }
 }
 
 
+Joint *GearJoint::getJointA() const
+{
+	b2Joint *b2joint = joint->GetJoint1();
+	if (b2joint == nullptr)
+		return nullptr;
+
+	Joint *j = (Joint *) Memoizer::find(b2joint);
+	if (j == nullptr)
+		throw love::Exception("A joint has escaped Memoizer!");
+
+	return j;
+}
+
+Joint *GearJoint::getJointB() const
+{
+	b2Joint *b2joint = joint->GetJoint2();
+	if (b2joint == nullptr)
+		return nullptr;
+
+	Joint *j = (Joint *) Memoizer::find(b2joint);
+	if (j == nullptr)
+		throw love::Exception("A joint has escaped Memoizer!");
+
+	return j;
+}
+
 } // box2d
 } // box2d
 } // physics
 } // physics
 } // love
 } // love

+ 3 - 0
src/modules/physics/box2d/GearJoint.h

@@ -64,6 +64,9 @@ public:
 	 **/
 	 **/
 	float getRatio() const;
 	float getRatio() const;
 
 
+	Joint *getJointA() const;
+	Joint *getJointB() const;
+
 private:
 private:
 	// The Box2D GearJoint object.
 	// The Box2D GearJoint object.
 	b2GearJoint *joint;
 	b2GearJoint *joint;

+ 28 - 0
src/modules/physics/box2d/Joint.cpp

@@ -90,11 +90,39 @@ Joint::Type Joint::getType() const
 		return JOINT_WHEEL;
 		return JOINT_WHEEL;
 	case e_ropeJoint:
 	case e_ropeJoint:
 		return JOINT_ROPE;
 		return JOINT_ROPE;
+	case e_motorJoint:
+		return JOINT_MOTOR;
 	default:
 	default:
 		return JOINT_INVALID;
 		return JOINT_INVALID;
 	}
 	}
 }
 }
 
 
+Body *Joint::getBodyA() const
+{
+	b2Body *b2body = joint->GetBodyA();
+	if (b2body == nullptr)
+		return nullptr;
+
+	Body *body = (Body *) Memoizer::find(b2body);
+	if (body == nullptr)
+		throw love::Exception("A body has escaped Memoizer!");
+
+	return body;
+}
+
+Body *Joint::getBodyB() const
+{
+	b2Body *b2body = joint->GetBodyB();
+	if (b2body == nullptr)
+		return nullptr;
+
+	Body *body = (Body *) Memoizer::find(b2body);
+	if (body == nullptr)
+		throw love::Exception("A body has escaped Memoizer!");
+
+	return body;
+}
+
 bool Joint::isValid() const
 bool Joint::isValid() const
 {
 {
 	return joint != 0;
 	return joint != 0;

+ 3 - 1
src/modules/physics/box2d/Joint.h

@@ -79,12 +79,14 @@ public:
 	 **/
 	 **/
 	bool isValid() const;
 	bool isValid() const;
 
 
-
 	/**
 	/**
 	 * Gets the type of joint.
 	 * Gets the type of joint.
 	 **/
 	 **/
 	Type getType() const;
 	Type getType() const;
 
 
+	Body *getBodyA() const;
+	Body *getBodyB() const;
+
 	/**
 	/**
 	 * Gets the anchor positions of the Joint in world
 	 * Gets the anchor positions of the Joint in world
 	 * coordinates. This is useful for debugdrawing the joint.
 	 * coordinates. This is useful for debugdrawing the joint.

+ 10 - 0
src/modules/physics/box2d/wrap_Body.cpp

@@ -539,6 +539,15 @@ int w_Body_getFixtureList(lua_State *L)
 	return n;
 	return n;
 }
 }
 
 
+int w_Body_getJointList(lua_State *L)
+{
+	Body *t = luax_checkbody(L, 1);
+	lua_remove(L, 1);
+	int n = 0;
+	luax_catchexcept(L, [&](){ n = t->getJointList(L); });
+	return n;
+}
+
 int w_Body_getContactList(lua_State *L)
 int w_Body_getContactList(lua_State *L)
 {
 {
 	Body *t = luax_checkbody(L, 1);
 	Body *t = luax_checkbody(L, 1);
@@ -623,6 +632,7 @@ static const luaL_Reg functions[] =
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "getWorld", w_Body_getWorld },
 	{ "getWorld", w_Body_getWorld },
 	{ "getFixtureList", w_Body_getFixtureList },
 	{ "getFixtureList", w_Body_getFixtureList },
+	{ "getJointList", w_Body_getJointList },
 	{ "getContactList", w_Body_getContactList },
 	{ "getContactList", w_Body_getContactList },
 	{ "destroy", w_Body_destroy },
 	{ "destroy", w_Body_destroy },
 	{ "setUserData", w_Body_setUserData },
 	{ "setUserData", w_Body_setUserData },

+ 1 - 0
src/modules/physics/box2d/wrap_Body.h

@@ -85,6 +85,7 @@ int w_Body_setFixedRotation(lua_State *L);
 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_getWorld(lua_State *L);
 int w_Body_getWorld(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
+int w_Body_getJointList(lua_State *L);
 int w_Body_getContactList(lua_State *L);
 int w_Body_getContactList(lua_State *L);
 int w_Body_destroy(lua_State *L);
 int w_Body_destroy(lua_State *L);
 int w_Body_setUserData(lua_State *L);
 int w_Body_setUserData(lua_State *L);

+ 1 - 0
src/modules/physics/box2d/wrap_DistanceJoint.cpp

@@ -90,6 +90,7 @@ static const luaL_Reg functions[] =
 	{ "getDampingRatio", w_DistanceJoint_getDampingRatio },
 	{ "getDampingRatio", w_DistanceJoint_getDampingRatio },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_FrictionJoint.cpp

@@ -74,6 +74,7 @@ static const luaL_Reg functions[] =
 	{ "getMaxTorque", w_FrictionJoint_getMaxTorque },
 	{ "getMaxTorque", w_FrictionJoint_getMaxTorque },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 18 - 0
src/modules/physics/box2d/wrap_GearJoint.cpp

@@ -51,12 +51,30 @@ int w_GearJoint_getRatio(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_GearJoint_getJoints(lua_State *L)
+{
+	GearJoint *t = luax_checkgearjoint(L, 1);
+	Joint *j1 = nullptr;
+	Joint *j2 = nullptr;
+
+	luax_catchexcept(L, [&]() {
+		j1 = t->getJointA();
+		j2 = t->getJointB();
+	});
+
+	luax_pushjoint(L, j1);
+	luax_pushjoint(L, j2);
+	return 2;
+}
+
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
 	{ "setRatio", w_GearJoint_setRatio },
 	{ "setRatio", w_GearJoint_setRatio },
 	{ "getRatio", w_GearJoint_getRatio },
 	{ "getRatio", w_GearJoint_getRatio },
+	{ "getJoints", w_GearJoint_getJoints },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_GearJoint.h

@@ -36,6 +36,7 @@ namespace box2d
 GearJoint *luax_checkgearjoint(lua_State *L, int idx);
 GearJoint *luax_checkgearjoint(lua_State *L, int idx);
 int w_GearJoint_setRatio(lua_State *L);
 int w_GearJoint_setRatio(lua_State *L);
 int w_GearJoint_getRatio(lua_State *L);
 int w_GearJoint_getRatio(lua_State *L);
+int w_GearJoint_getJoints(lua_State *L);
 extern "C" int luaopen_gearjoint(lua_State *L);
 extern "C" int luaopen_gearjoint(lua_State *L);
 
 
 } // box2d
 } // box2d

+ 52 - 0
src/modules/physics/box2d/wrap_Joint.cpp

@@ -21,6 +21,7 @@
 // LOVE
 // LOVE
 #include "wrap_Joint.h"
 #include "wrap_Joint.h"
 #include "common/StringMap.h"
 #include "common/StringMap.h"
+#include "Body.h"
 
 
 namespace love
 namespace love
 {
 {
@@ -29,6 +30,40 @@ namespace physics
 namespace box2d
 namespace box2d
 {
 {
 
 
+void luax_pushjoint(lua_State *L, Joint *j)
+{
+	if (j == nullptr)
+		return lua_pushnil(L);
+
+	switch (j->getType())
+	{
+	case Joint::JOINT_DISTANCE:
+		return luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j);
+	case Joint::JOINT_REVOLUTE:
+		return luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j);
+	case Joint::JOINT_PRISMATIC:
+		return luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j);
+	case Joint::JOINT_MOUSE:
+		return luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j);
+	case Joint::JOINT_PULLEY:
+		return luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j);
+	case Joint::JOINT_GEAR:
+		return luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j);
+	case Joint::JOINT_FRICTION:
+		return luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j);
+	case Joint::JOINT_WELD:
+		return luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j);
+	case Joint::JOINT_WHEEL:
+		return luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j);
+	case Joint::JOINT_ROPE:
+		return luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j);
+	case Joint::JOINT_MOTOR:
+		return luax_pushtype(L, "MotorJoint", PHYSICS_MOTOR_JOINT_T, j);
+	default:
+		return lua_pushnil(L);
+	}
+}
+
 Joint *luax_checkjoint(lua_State *L, int idx)
 Joint *luax_checkjoint(lua_State *L, int idx)
 {
 {
 	Joint *t = luax_checktype<Joint>(L, idx, "Joint", PHYSICS_JOINT_T);
 	Joint *t = luax_checktype<Joint>(L, idx, "Joint", PHYSICS_JOINT_T);
@@ -46,6 +81,22 @@ int w_Joint_getType(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_Joint_getBodies(lua_State *L)
+{
+	Joint *t = luax_checkjoint(L, 1);
+	Body *b1 = nullptr;
+	Body *b2 = nullptr;
+
+	luax_catchexcept(L, [&]() {
+		b1 = t->getBodyA();
+		b2 = t->getBodyB();
+	});
+
+	luax_pushtype(L, "Body", PHYSICS_BODY_T, b1);
+	luax_pushtype(L, "Body", PHYSICS_BODY_T, b2);
+	return 2;
+}
+
 int w_Joint_getAnchors(lua_State *L)
 int w_Joint_getAnchors(lua_State *L)
 {
 {
 	Joint *t = luax_checkjoint(L, 1);
 	Joint *t = luax_checkjoint(L, 1);
@@ -99,6 +150,7 @@ int w_Joint_destroy(lua_State *L)
 static const luaL_Reg functions[] =
 static const luaL_Reg functions[] =
 {
 {
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 2 - 0
src/modules/physics/box2d/wrap_Joint.h

@@ -32,8 +32,10 @@ namespace physics
 namespace box2d
 namespace box2d
 {
 {
 
 
+void luax_pushjoint(lua_State *L, Joint *j);
 Joint *luax_checkjoint(lua_State *L, int idx);
 Joint *luax_checkjoint(lua_State *L, int idx);
 int w_Joint_getType(lua_State *L);
 int w_Joint_getType(lua_State *L);
+int w_Joint_getBodies(lua_State *L);
 int w_Joint_getAnchors(lua_State *L);
 int w_Joint_getAnchors(lua_State *L);
 int w_Joint_getReactionForce(lua_State *L);
 int w_Joint_getReactionForce(lua_State *L);
 int w_Joint_getReactionTorque(lua_State *L);
 int w_Joint_getReactionTorque(lua_State *L);

+ 1 - 0
src/modules/physics/box2d/wrap_MotorJoint.cpp

@@ -124,6 +124,7 @@ static const luaL_Reg functions[] =
 	{ "getCorrectionFactor", w_MotorJoint_getCorrectionFactor },
 	{ "getCorrectionFactor", w_MotorJoint_getCorrectionFactor },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_MouseJoint.cpp

@@ -108,6 +108,7 @@ static const luaL_Reg functions[] =
 	{ "getDampingRatio", w_MouseJoint_getDampingRatio },
 	{ "getDampingRatio", w_MouseJoint_getDampingRatio },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_PrismaticJoint.cpp

@@ -185,6 +185,7 @@ static const luaL_Reg functions[] =
 	{ "getLimits", w_PrismaticJoint_getLimits },
 	{ "getLimits", w_PrismaticJoint_getLimits },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_PulleyJoint.cpp

@@ -71,6 +71,7 @@ static const luaL_Reg functions[] =
 	{ "getRatio", w_PulleyJoint_getRatio },
 	{ "getRatio", w_PulleyJoint_getRatio },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_RevoluteJoint.cpp

@@ -185,6 +185,7 @@ static const luaL_Reg functions[] =
 	{ "getLimits", w_RevoluteJoint_getLimits },
 	{ "getLimits", w_RevoluteJoint_getLimits },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_RopeJoint.cpp

@@ -47,6 +47,7 @@ static const luaL_Reg functions[] =
 	{ "getMaxLength", w_RopeJoint_getMaxLength },
 	{ "getMaxLength", w_RopeJoint_getMaxLength },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_WeldJoint.cpp

@@ -73,6 +73,7 @@ static const luaL_Reg functions[] =
 	{ "getDampingRatio", w_WeldJoint_getDampingRatio },
 	{ "getDampingRatio", w_WeldJoint_getDampingRatio },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },

+ 1 - 0
src/modules/physics/box2d/wrap_WheelJoint.cpp

@@ -149,6 +149,7 @@ static const luaL_Reg functions[] =
 	{ "getSpringDampingRatio", w_WheelJoint_getSpringDampingRatio },
 	{ "getSpringDampingRatio", w_WheelJoint_getSpringDampingRatio },
 	// From Joint.
 	// From Joint.
 	{ "getType", w_Joint_getType },
 	{ "getType", w_Joint_getType },
+	{ "getBodies", w_Joint_getBodies },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getAnchors", w_Joint_getAnchors },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionForce", w_Joint_getReactionForce },
 	{ "getReactionTorque", w_Joint_getReactionTorque },
 	{ "getReactionTorque", w_Joint_getReactionTorque },