Browse Source

Merge default into minor

--HG--
branch : minor
Alex Szpakowski 9 years ago
parent
commit
ef61573cd3

+ 3 - 0
CMakeLists.txt

@@ -199,6 +199,9 @@ Please see http://bitbucket.org/rude/megasource
 		${VORBISFILE_LIBRARY}
 		${VORBISFILE_LIBRARY}
 		${LOVE_LUA_LIBRARY}
 		${LOVE_LUA_LIBRARY}
 	)
 	)
+	
+	# Work-around for gcc bug 1568899.
+	set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES} gcc_s gcc)
 
 
 	if(LOVE_MPG123)
 	if(LOVE_MPG123)
 		find_package(MPG123 REQUIRED)
 		find_package(MPG123 REQUIRED)

+ 7 - 0
bitbucket-pipelines.yml

@@ -0,0 +1,7 @@
+image: mfcula/love-cmake:v1
+pipelines:
+  default:
+    - step:
+        script:
+          - cmake -G"Ninja" -H. -Bout
+          - ninja -C out

+ 0 - 8
src/common/math.h

@@ -68,14 +68,6 @@ struct Vertex
 	unsigned char r, g, b, a;
 	unsigned char r, g, b, a;
 };
 };
 
 
-struct Triangle
-{
-	Triangle(const Vertex &x, const Vertex &y, const Vertex &z)
-		: a(x), b(y), c(z)
-	{}
-	Vertex a, b, c;
-};
-
 inline int nextP2(int x)
 inline int nextP2(int x)
 {
 {
 	x += (x == 0);
 	x += (x == 0);

+ 5 - 0
src/modules/filesystem/wrap_Filesystem.cpp

@@ -218,6 +218,11 @@ FileData *luax_getfiledata(lua_State *L, int idx)
 	return data;
 	return data;
 }
 }
 
 
+bool luax_cangetfiledata(lua_State *L, int idx)
+{
+	return lua_isstring(L, idx) || luax_istype(L, idx, FILESYSTEM_FILE_ID) || luax_istype(L, idx, FILESYSTEM_FILE_DATA_ID);
+}
+
 int w_newFileData(lua_State *L)
 int w_newFileData(lua_State *L)
 {
 {
 	// Single argument: treat as filepath or File.
 	// Single argument: treat as filepath or File.

+ 1 - 0
src/modules/filesystem/wrap_Filesystem.h

@@ -39,6 +39,7 @@ namespace filesystem
  * May trigger a Lua error.
  * May trigger a Lua error.
  **/
  **/
 FileData *luax_getfiledata(lua_State *L, int idx);
 FileData *luax_getfiledata(lua_State *L, int idx);
+bool luax_cangetfiledata(lua_State *L, int idx);
 File *luax_getfile(lua_State *L, int idx);
 File *luax_getfile(lua_State *L, int idx);
 
 
 bool hack_setupWriteDirectory();
 bool hack_setupWriteDirectory();

+ 8 - 6
src/modules/graphics/opengl/Canvas.cpp

@@ -501,13 +501,15 @@ void Canvas::startGrab()
 			gl.setFramebufferSRGB(false);
 			gl.setFramebufferSRGB(false);
 	}
 	}
 
 
-	if (attachedCanvases.size() == 0)
-		return;
-
-	// Make sure the FBO is only using a single draw buffer.
-	glDrawBuffer(GL_COLOR_ATTACHMENT0);
+	if (attachedCanvases.size() > 0)
+	{
+		// Make sure the FBO is only using a single draw buffer.
+		// GLES3 only has glDrawBuffers, so we avoid using glDrawBuffer.
+		const GLenum buffers[] = {GL_COLOR_ATTACHMENT0};
+		glDrawBuffers(1, buffers);
 
 
-	attachedCanvases.clear();
+		attachedCanvases.clear();
+	}
 }
 }
 
 
 void Canvas::stopGrab(bool switchingToOtherCanvas)
 void Canvas::stopGrab(bool switchingToOtherCanvas)

+ 6 - 2
src/modules/graphics/opengl/wrap_Graphics.lua

@@ -352,13 +352,17 @@ function love.graphics.newVideo(file, loadaudio)
 	local video = love.graphics._newVideo(file)
 	local video = love.graphics._newVideo(file)
 	local source, success
 	local source, success
 
 
-	if loadaudio ~= false then
+	if loadaudio ~= false and love.audio then
 		success, source = pcall(love.audio.newSource, video:getStream():getFilename(), "stream")
 		success, source = pcall(love.audio.newSource, video:getStream():getFilename(), "stream")
 	end
 	end
 	if success then
 	if success then
 		video:setSource(source)
 		video:setSource(source)
 	elseif loadaudio == true then
 	elseif loadaudio == true then
-		error("Video had no audio track", 2)
+		if love.audio then
+			error("Video had no audio track", 2)
+		else
+			error("love.audio was not loaded", 2)
+		end
 	else
 	else
 		video:getStream():setSync()
 		video:getStream():setSync()
 	end
 	end

+ 16 - 11
src/modules/image/wrap_Image.cpp

@@ -77,19 +77,24 @@ int w_newImageData(lua_State *L)
 		t->release();
 		t->release();
 		return 1;
 		return 1;
 	}
 	}
+	else if (filesystem::luax_cangetfiledata(L, 1)) // Case 2: File(Data).
+	{
+		filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1);
 
 
-	// Case 2: File(Data).
-	love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1);
-
-	ImageData *t = nullptr;
-	luax_catchexcept(L,
-		[&]() { t = instance()->newImageData(data); },
-		[&](bool) { data->release(); }
-	);
+		ImageData *t = nullptr;
+		luax_catchexcept(L,
+			[&]() { t = instance()->newImageData(data); },
+			[&](bool) { data->release(); }
+		);
 
 
-	luax_pushtype(L, IMAGE_IMAGE_DATA_ID, t);
-	t->release();
-	return 1;
+		luax_pushtype(L, IMAGE_IMAGE_DATA_ID, t);
+		t->release();
+		return 1;
+	}
+	else
+	{
+		return luax_typerror(L, 1, "value");
+	}
 }
 }
 
 
 int w_newCompressedData(lua_State *L)
 int w_newCompressedData(lua_State *L)

+ 16 - 19
src/modules/math/MathModule.cpp

@@ -32,8 +32,7 @@
 #include <iostream>
 #include <iostream>
 
 
 using std::list;
 using std::list;
-using std::vector;
-using love::Vertex;
+using love::Vector;
 
 
 namespace
 namespace
 {
 {
@@ -117,14 +116,14 @@ love::uint8 *hexToBytes(const char *src, size_t srclen, size_t &dstlen)
 }
 }
 
 
 // check if an angle is oriented counter clockwise
 // check if an angle is oriented counter clockwise
-inline bool is_oriented_ccw(const Vertex &a, const Vertex &b, const Vertex &c)
+inline bool is_oriented_ccw(const Vector &a, const Vector &b, const Vector &c)
 {
 {
 	// return det(b-a, c-a) >= 0
 	// return det(b-a, c-a) >= 0
 	return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) >= 0;
 	return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) >= 0;
 }
 }
 
 
 // check if a and b are on the same side of the line c->d
 // check if a and b are on the same side of the line c->d
-bool on_same_side(const Vertex &a, const Vertex &b, const Vertex &c, const Vertex &d)
+bool on_same_side(const Vector &a, const Vector &b, const Vector &c, const Vector &d)
 {
 {
 	float px = d.x - c.x, py = d.y - c.y;
 	float px = d.x - c.x, py = d.y - c.y;
 	// return det(p, a-c) * det(p, b-c) >= 0
 	// return det(p, a-c) * det(p, b-c) >= 0
@@ -134,18 +133,16 @@ bool on_same_side(const Vertex &a, const Vertex &b, const Vertex &c, const Verte
 }
 }
 
 
 // checks is p is contained in the triangle abc
 // checks is p is contained in the triangle abc
-inline bool point_in_triangle(const Vertex &p, const Vertex &a, const Vertex &b, const Vertex &c)
+inline bool point_in_triangle(const Vector &p, const Vector &a, const Vector &b, const Vector &c)
 {
 {
 	return on_same_side(p,a, b,c) && on_same_side(p,b, a,c) && on_same_side(p,c, a,b);
 	return on_same_side(p,a, b,c) && on_same_side(p,b, a,c) && on_same_side(p,c, a,b);
 }
 }
 
 
 // checks if any vertex in `vertices' is in the triangle abc.
 // checks if any vertex in `vertices' is in the triangle abc.
-bool any_point_in_triangle(const list<const Vertex *> &vertices, const Vertex &a, const Vertex &b, const Vertex &c)
+bool any_point_in_triangle(const std::list<const Vector *> &vertices, const Vector &a, const Vector &b, const Vector &c)
 {
 {
-	list<const Vertex *>::const_iterator it, end = vertices.end();
-	for (it = vertices.begin(); it != end; ++it)
+	for (const Vector *p : vertices)
 	{
 	{
-		const Vertex *p = *it;
 		if ((p != &a) && (p != &b) && (p != &c) && point_in_triangle(*p, a,b,c)) // oh god...
 		if ((p != &a) && (p != &b) && (p != &c) && point_in_triangle(*p, a,b,c)) // oh god...
 			return true;
 			return true;
 	}
 	}
@@ -153,7 +150,7 @@ bool any_point_in_triangle(const list<const Vertex *> &vertices, const Vertex &a
 	return false;
 	return false;
 }
 }
 
 
-inline bool is_ear(const Vertex &a, const Vertex &b, const Vertex &c, const list<const Vertex *> &vertices)
+inline bool is_ear(const Vector &a, const Vector &b, const Vector &c, const std::list<const Vector *> &vertices)
 {
 {
 	return is_oriented_ccw(a,b,c) && !any_point_in_triangle(vertices, a,b,c);
 	return is_oriented_ccw(a,b,c) && !any_point_in_triangle(vertices, a,b,c);
 }
 }
@@ -165,20 +162,20 @@ namespace love
 namespace math
 namespace math
 {
 {
 
 
-vector<Triangle> triangulate(const vector<Vertex> &polygon)
+std::vector<Triangle> triangulate(const std::vector<love::Vector> &polygon)
 {
 {
 	if (polygon.size() < 3)
 	if (polygon.size() < 3)
 		throw love::Exception("Not a polygon");
 		throw love::Exception("Not a polygon");
 	else if (polygon.size() == 3)
 	else if (polygon.size() == 3)
-		return vector<Triangle>(1, Triangle(polygon[0], polygon[1], polygon[2]));
+		return std::vector<Triangle>(1, Triangle(polygon[0], polygon[1], polygon[2]));
 
 
 	// collect list of connections and record leftmost item to check if the polygon
 	// collect list of connections and record leftmost item to check if the polygon
 	// has the expected winding
 	// has the expected winding
-	vector<size_t> next_idx(polygon.size()), prev_idx(polygon.size());
+	std::vector<size_t> next_idx(polygon.size()), prev_idx(polygon.size());
 	size_t idx_lm = 0;
 	size_t idx_lm = 0;
 	for (size_t i = 0; i < polygon.size(); ++i)
 	for (size_t i = 0; i < polygon.size(); ++i)
 	{
 	{
-		const Vertex &lm = polygon[idx_lm], &p = polygon[i];
+		const love::Vector &lm = polygon[idx_lm], &p = polygon[i];
 		if (p.x < lm.x || (p.x == lm.x && p.y < lm.y))
 		if (p.x < lm.x || (p.x == lm.x && p.y < lm.y))
 			idx_lm = i;
 			idx_lm = i;
 		next_idx[i] = i+1;
 		next_idx[i] = i+1;
@@ -192,7 +189,7 @@ vector<Triangle> triangulate(const vector<Vertex> &polygon)
 		next_idx.swap(prev_idx);
 		next_idx.swap(prev_idx);
 
 
 	// collect list of concave polygons
 	// collect list of concave polygons
-	list<const Vertex *> concave_vertices;
+	std::list<const love::Vector *> concave_vertices;
 	for (size_t i = 0; i < polygon.size(); ++i)
 	for (size_t i = 0; i < polygon.size(); ++i)
 	{
 	{
 		if (!is_oriented_ccw(polygon[prev_idx[i]], polygon[i], polygon[next_idx[i]]))
 		if (!is_oriented_ccw(polygon[prev_idx[i]], polygon[i], polygon[next_idx[i]]))
@@ -200,14 +197,14 @@ vector<Triangle> triangulate(const vector<Vertex> &polygon)
 	}
 	}
 
 
 	// triangulation according to kong
 	// triangulation according to kong
-	vector<Triangle> triangles;
+	std::vector<Triangle> triangles;
 	size_t n_vertices = polygon.size();
 	size_t n_vertices = polygon.size();
 	size_t current = 1, skipped = 0, next, prev;
 	size_t current = 1, skipped = 0, next, prev;
 	while (n_vertices > 3)
 	while (n_vertices > 3)
 	{
 	{
 		next = next_idx[current];
 		next = next_idx[current];
 		prev = prev_idx[current];
 		prev = prev_idx[current];
-		const Vertex &a = polygon[prev], &b = polygon[current], &c = polygon[next];
+		const Vector &a = polygon[prev], &b = polygon[current], &c = polygon[next];
 		if (is_ear(a,b,c, concave_vertices))
 		if (is_ear(a,b,c, concave_vertices))
 		{
 		{
 			triangles.push_back(Triangle(a,b,c));
 			triangles.push_back(Triangle(a,b,c));
@@ -230,7 +227,7 @@ vector<Triangle> triangulate(const vector<Vertex> &polygon)
 	return triangles;
 	return triangles;
 }
 }
 
 
-bool isConvex(const std::vector<Vertex> &polygon)
+bool isConvex(const std::vector<love::Vector> &polygon)
 {
 {
 	if (polygon.size() < 3)
 	if (polygon.size() < 3)
 		return false;
 		return false;
@@ -372,7 +369,7 @@ RandomGenerator *Math::newRandomGenerator()
 	return new RandomGenerator();
 	return new RandomGenerator();
 }
 }
 
 
-BezierCurve *Math::newBezierCurve(const vector<Vector> &points)
+BezierCurve *Math::newBezierCurve(const std::vector<Vector> &points)
 {
 {
 	return new BezierCurve(points);
 	return new BezierCurve(points);
 }
 }

+ 10 - 2
src/modules/math/MathModule.h

@@ -46,6 +46,14 @@ namespace math
 
 
 class BezierCurve;
 class BezierCurve;
 
 
+struct Triangle
+{
+	Triangle(const Vector &x, const Vector &y, const Vector &z)
+		: a(x), b(y), c(z)
+	{}
+	Vector a, b, c;
+};
+
 enum EncodeFormat
 enum EncodeFormat
 {
 {
 	ENCODE_BASE64,
 	ENCODE_BASE64,
@@ -59,7 +67,7 @@ enum EncodeFormat
  * @param polygon Polygon to triangulate. Must not intersect itself.
  * @param polygon Polygon to triangulate. Must not intersect itself.
  * @return List of triangles the polygon is composed of.
  * @return List of triangles the polygon is composed of.
  **/
  **/
-std::vector<Triangle> triangulate(const std::vector<Vertex> &polygon);
+std::vector<Triangle> triangulate(const std::vector<love::Vector> &polygon);
 
 
 /**
 /**
  * Checks whether a polygon is convex.
  * Checks whether a polygon is convex.
@@ -67,7 +75,7 @@ std::vector<Triangle> triangulate(const std::vector<Vertex> &polygon);
  * @param polygon Polygon to test.
  * @param polygon Polygon to test.
  * @return True if the polygon is convex, false otherwise.
  * @return True if the polygon is convex, false otherwise.
  **/
  **/
-bool isConvex(const std::vector<Vertex> &polygon);
+bool isConvex(const std::vector<love::Vector> &polygon);
 
 
 /**
 /**
  * Converts a value from the sRGB (gamma) colorspace to linear RGB.
  * Converts a value from the sRGB (gamma) colorspace to linear RGB.

+ 6 - 6
src/modules/math/wrap_Math.cpp

@@ -120,7 +120,7 @@ int w_newBezierCurve(lua_State *L)
 
 
 int w_triangulate(lua_State *L)
 int w_triangulate(lua_State *L)
 {
 {
-	std::vector<Vertex> vertices;
+	std::vector<love::Vector> vertices;
 	if (lua_istable(L, 1))
 	if (lua_istable(L, 1))
 	{
 	{
 		int top = (int) luax_objlen(L, 1);
 		int top = (int) luax_objlen(L, 1);
@@ -130,7 +130,7 @@ int w_triangulate(lua_State *L)
 			lua_rawgeti(L, 1, i);
 			lua_rawgeti(L, 1, i);
 			lua_rawgeti(L, 1, i+1);
 			lua_rawgeti(L, 1, i+1);
 
 
-			Vertex v;
+			Vector v;
 			v.x = (float) luaL_checknumber(L, -2);
 			v.x = (float) luaL_checknumber(L, -2);
 			v.y = (float) luaL_checknumber(L, -1);
 			v.y = (float) luaL_checknumber(L, -1);
 			vertices.push_back(v);
 			vertices.push_back(v);
@@ -144,7 +144,7 @@ int w_triangulate(lua_State *L)
 		vertices.reserve(top / 2);
 		vertices.reserve(top / 2);
 		for (int i = 1; i <= top; i += 2)
 		for (int i = 1; i <= top; i += 2)
 		{
 		{
-			Vertex v;
+			Vector v;
 			v.x = (float) luaL_checknumber(L, i);
 			v.x = (float) luaL_checknumber(L, i);
 			v.y = (float) luaL_checknumber(L, i+1);
 			v.y = (float) luaL_checknumber(L, i+1);
 			vertices.push_back(v);
 			vertices.push_back(v);
@@ -190,7 +190,7 @@ int w_triangulate(lua_State *L)
 
 
 int w_isConvex(lua_State *L)
 int w_isConvex(lua_State *L)
 {
 {
-	std::vector<Vertex> vertices;
+	std::vector<love::Vector> vertices;
 	if (lua_istable(L, 1))
 	if (lua_istable(L, 1))
 	{
 	{
 		int top = (int) luax_objlen(L, 1);
 		int top = (int) luax_objlen(L, 1);
@@ -200,7 +200,7 @@ int w_isConvex(lua_State *L)
 			lua_rawgeti(L, 1, i);
 			lua_rawgeti(L, 1, i);
 			lua_rawgeti(L, 1, i+1);
 			lua_rawgeti(L, 1, i+1);
 
 
-			Vertex v;
+			love::Vector v;
 			v.x = (float) luaL_checknumber(L, -2);
 			v.x = (float) luaL_checknumber(L, -2);
 			v.y = (float) luaL_checknumber(L, -1);
 			v.y = (float) luaL_checknumber(L, -1);
 			vertices.push_back(v);
 			vertices.push_back(v);
@@ -214,7 +214,7 @@ int w_isConvex(lua_State *L)
 		vertices.reserve(top / 2);
 		vertices.reserve(top / 2);
 		for (int i = 1; i <= top; i += 2)
 		for (int i = 1; i <= top; i += 2)
 		{
 		{
-			Vertex v;
+			love::Vector v;
 			v.x = (float) luaL_checknumber(L, i);
 			v.x = (float) luaL_checknumber(L, i);
 			v.y = (float) luaL_checknumber(L, i+1);
 			v.y = (float) luaL_checknumber(L, i+1);
 			vertices.push_back(v);
 			vertices.push_back(v);

+ 15 - 0
src/modules/physics/box2d/Physics.cpp

@@ -228,11 +228,21 @@ RevoluteJoint *Physics::newRevoluteJoint(Body *body1, Body *body2, float xA, flo
 	return new RevoluteJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	return new RevoluteJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 }
 }
 
 
+RevoluteJoint *Physics::newRevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle)
+{
+	return new RevoluteJoint(body1, body2, xA, yA, xB, yB, collideConnected, referenceAngle);
+}
+
 PrismaticJoint *Physics::newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected)
 PrismaticJoint *Physics::newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected)
 {
 {
 	return new PrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	return new PrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 }
 }
 
 
+PrismaticJoint *Physics::newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected, float referenceAngle)
+{
+	return new PrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected, referenceAngle);
+}
+
 PulleyJoint *Physics::newPulleyJoint(Body *body1, Body *body2, b2Vec2 groundAnchor1, b2Vec2 groundAnchor2, b2Vec2 anchor1, b2Vec2 anchor2, float ratio, bool collideConnected)
 PulleyJoint *Physics::newPulleyJoint(Body *body1, Body *body2, b2Vec2 groundAnchor1, b2Vec2 groundAnchor2, b2Vec2 anchor1, b2Vec2 anchor2, float ratio, bool collideConnected)
 {
 {
 	return new PulleyJoint(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio, collideConnected);
 	return new PulleyJoint(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio, collideConnected);
@@ -253,6 +263,11 @@ WeldJoint *Physics::newWeldJoint(Body *body1, Body *body2, float xA, float yA, f
 	return new WeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	return new WeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 }
 }
 
 
+WeldJoint *Physics::newWeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle)
+{
+	return new WeldJoint(body1, body2, xA, yA, xB, yB, collideConnected, referenceAngle);
+}
+
 WheelJoint *Physics::newWheelJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected)
 WheelJoint *Physics::newWheelJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected)
 {
 {
 	return new WheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	return new WheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);

+ 9 - 0
src/modules/physics/box2d/Physics.h

@@ -176,9 +176,12 @@ public:
 	 * @param xB Anchor for body 2 along the x-axis. (World coordinates)
 	 * @param xB Anchor for body 2 along the x-axis. (World coordinates)
 	 * @param yB Anchor for body 2 along the y-axis. (World coordinates)
 	 * @param yB Anchor for body 2 along the y-axis. (World coordinates)
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
+	 * @param referenceAngle The reference angle.
 	 **/
 	 **/
 	RevoluteJoint *newRevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 	RevoluteJoint *newRevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 
 
+	RevoluteJoint *newRevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle);
+
 	/**
 	/**
 	 * Creates a new PrismaticJoint connecting body1 with body2.
 	 * Creates a new PrismaticJoint connecting body1 with body2.
 	 * @param xA World-anchor for body1 along the x-axis.
 	 * @param xA World-anchor for body1 along the x-axis.
@@ -188,9 +191,12 @@ public:
 	 * @param ax The x-component of the world-axis.
 	 * @param ax The x-component of the world-axis.
 	 * @param ay The y-component of the world-axis.
 	 * @param ay The y-component of the world-axis.
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
+	 * @param referenceAngle The reference angle.
 	 **/
 	 **/
 	PrismaticJoint *newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected);
 	PrismaticJoint *newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected);
 
 
+	PrismaticJoint *newPrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected, float referenceAngle);
+
 	/**
 	/**
 	 * Creates a new PulleyJoint connecting body1 with body2.
 	 * Creates a new PulleyJoint connecting body1 with body2.
 	 * @param groundAnchor1 World ground-anchor for body1.
 	 * @param groundAnchor1 World ground-anchor for body1.
@@ -228,9 +234,12 @@ public:
 	 * @param xB Anchor for body 2 along the x-axis. (World coordinates)
 	 * @param xB Anchor for body 2 along the x-axis. (World coordinates)
 	 * @param yB Anchor for body 2 along the y-axis. (World coordinates)
 	 * @param yB Anchor for body 2 along the y-axis. (World coordinates)
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
 	 * @param collideConnected Whether the connected bodies should collide with each other. Defaults to false.
+	 * @param referenceAngle The reference angle.
 	 **/
 	 **/
 	WeldJoint *newWeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 	WeldJoint *newWeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 
 
+	WeldJoint *newWeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle);
+
 	/**
 	/**
 	 * Creates a new WheelJoint connecting body1 with body2.
 	 * Creates a new WheelJoint connecting body1 with body2.
 	 * @param xA Anchor for body 1 along the x-axis. (World coordinates)
 	 * @param xA Anchor for body 1 along the x-axis. (World coordinates)

+ 24 - 5
src/modules/physics/box2d/PrismaticJoint.cpp

@@ -37,18 +37,32 @@ PrismaticJoint::PrismaticJoint(Body *body1, Body *body2, float xA, float yA, flo
 	, joint(NULL)
 	, joint(NULL)
 {
 {
 	b2PrismaticJointDef def;
 	b2PrismaticJointDef def;
+	init(def, body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
+	joint = (b2PrismaticJoint *)createJoint(&def);
+}
+
+PrismaticJoint::PrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected, float referenceAngle)
+	: Joint(body1, body2)
+	, joint(NULL)
+{
+	b2PrismaticJointDef def;
+	init(def, body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
+	def.referenceAngle = referenceAngle;
+	joint = (b2PrismaticJoint *)createJoint(&def);
+}
+
+PrismaticJoint::~PrismaticJoint()
+{
+}
 
 
+void PrismaticJoint::init(b2PrismaticJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected)
+{
 	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)), b2Vec2(ax,ay));
 	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)), b2Vec2(ax,ay));
 	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
 	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
 	def.lowerTranslation = 0.0f;
 	def.lowerTranslation = 0.0f;
 	def.upperTranslation = 100.0f;
 	def.upperTranslation = 100.0f;
 	def.enableLimit = true;
 	def.enableLimit = true;
 	def.collideConnected = collideConnected;
 	def.collideConnected = collideConnected;
-	joint = (b2PrismaticJoint *)createJoint(&def);
-}
-
-PrismaticJoint::~PrismaticJoint()
-{
 }
 }
 
 
 float PrismaticJoint::getJointTranslation() const
 float PrismaticJoint::getJointTranslation() const
@@ -147,6 +161,11 @@ int PrismaticJoint::getAxis(lua_State *L)
 	return 2;
 	return 2;
 }
 }
 
 
+float PrismaticJoint::getReferenceAngle() const
+{
+	return joint->GetReferenceAngle();
+}
+
 } // box2d
 } // box2d
 } // physics
 } // physics
 } // love
 } // love

+ 9 - 0
src/modules/physics/box2d/PrismaticJoint.h

@@ -44,6 +44,8 @@ public:
 	 **/
 	 **/
 	PrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected);
 	PrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected);
 
 
+	PrismaticJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected, float referenceAngle);
+
 	virtual ~PrismaticJoint();
 	virtual ~PrismaticJoint();
 
 
 	/**
 	/**
@@ -141,10 +143,17 @@ public:
 	 **/
 	 **/
 	int getAxis(lua_State *L);
 	int getAxis(lua_State *L);
 
 
+	/**
+	 * Gets the reference angle.
+	 **/
+	float getReferenceAngle() const;
+
 private:
 private:
 
 
 	// The Box2D prismatic joint object.
 	// The Box2D prismatic joint object.
 	b2PrismaticJoint *joint;
 	b2PrismaticJoint *joint;
+
+	void init(b2PrismaticJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, float ax, float ay, bool collideConnected);
 };
 };
 
 
 } // box2d
 } // box2d

+ 23 - 3
src/modules/physics/box2d/RevoluteJoint.cpp

@@ -39,9 +39,17 @@ RevoluteJoint::RevoluteJoint(Body *body1, Body *body2, float xA, float yA, float
 	, joint(NULL)
 	, joint(NULL)
 {
 {
 	b2RevoluteJointDef def;
 	b2RevoluteJointDef def;
-	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)));
-	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
-	def.collideConnected = collideConnected;
+	init(def, body1, body2, xA, yA, xB, yB, collideConnected);
+	joint = (b2RevoluteJoint *)createJoint(&def);
+}
+
+RevoluteJoint::RevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle)
+	: Joint(body1, body2)
+	, joint(NULL)
+{
+	b2RevoluteJointDef def;
+	init(def, body1, body2, xA, yA, xB, yB, collideConnected);
+	def.referenceAngle = referenceAngle;
 	joint = (b2RevoluteJoint *)createJoint(&def);
 	joint = (b2RevoluteJoint *)createJoint(&def);
 }
 }
 
 
@@ -49,6 +57,13 @@ RevoluteJoint::~RevoluteJoint()
 {
 {
 }
 }
 
 
+void RevoluteJoint::init(b2RevoluteJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected)
+{
+	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)));
+	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
+	def.collideConnected = collideConnected;
+}
+
 float RevoluteJoint::getJointAngle() const
 float RevoluteJoint::getJointAngle() const
 {
 {
 	return joint->GetJointAngle();
 	return joint->GetJointAngle();
@@ -136,6 +151,11 @@ int RevoluteJoint::getLimits(lua_State *L)
 	return 2;
 	return 2;
 }
 }
 
 
+float RevoluteJoint::getReferenceAngle() const
+{
+	return joint->GetReferenceAngle();
+}
+
 } // box2d
 } // box2d
 } // physics
 } // physics
 } // love
 } // love

+ 9 - 0
src/modules/physics/box2d/RevoluteJoint.h

@@ -44,6 +44,8 @@ public:
 	 **/
 	 **/
 	RevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 	RevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 
 
+	RevoluteJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle);
+
 	virtual ~RevoluteJoint();
 	virtual ~RevoluteJoint();
 
 
 	/**
 	/**
@@ -134,10 +136,17 @@ public:
 	 **/
 	 **/
 	int getLimits(lua_State *L);
 	int getLimits(lua_State *L);
 
 
+	/**
+	 * Gets the reference angle.
+	 **/
+	float getReferenceAngle() const;
+
 private:
 private:
 
 
 	// The Box2D revolute joint object.
 	// The Box2D revolute joint object.
 	b2RevoluteJoint *joint;
 	b2RevoluteJoint *joint;
+
+	void init(b2RevoluteJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 };
 };
 
 
 } // box2d
 } // box2d

+ 23 - 3
src/modules/physics/box2d/WeldJoint.cpp

@@ -39,9 +39,17 @@ WeldJoint::WeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, flo
 	, joint(NULL)
 	, joint(NULL)
 {
 {
 	b2WeldJointDef def;
 	b2WeldJointDef def;
-	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)));
-	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
-	def.collideConnected = collideConnected;
+	init(def, body1, body2, xA, yA, xB, yB, collideConnected);
+	joint = (b2WeldJoint *)createJoint(&def);
+}
+
+WeldJoint::WeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle)
+	: Joint(body1, body2)
+	, joint(NULL)
+{
+	b2WeldJointDef def;
+	init(def, body1, body2, xA, yA, xB, yB, collideConnected);
+	def.referenceAngle = referenceAngle;
 	joint = (b2WeldJoint *)createJoint(&def);
 	joint = (b2WeldJoint *)createJoint(&def);
 }
 }
 
 
@@ -49,6 +57,13 @@ WeldJoint::~WeldJoint()
 {
 {
 }
 }
 
 
+void WeldJoint::init(b2WeldJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected)
+{
+	def.Initialize(body1->body, body2->body, Physics::scaleDown(b2Vec2(xA,yA)));
+	def.localAnchorB = body2->body->GetLocalPoint(Physics::scaleDown(b2Vec2(xB, yB)));
+	def.collideConnected = collideConnected;
+}
+
 void WeldJoint::setFrequency(float hz)
 void WeldJoint::setFrequency(float hz)
 {
 {
 	joint->SetFrequency(hz);
 	joint->SetFrequency(hz);
@@ -69,6 +84,11 @@ float WeldJoint::getDampingRatio() const
 	return joint->GetDampingRatio();
 	return joint->GetDampingRatio();
 }
 }
 
 
+float WeldJoint::getReferenceAngle() const
+{
+	return joint->GetReferenceAngle();
+}
+
 } // box2d
 } // box2d
 } // physics
 } // physics
 } // love
 } // love

+ 9 - 0
src/modules/physics/box2d/WeldJoint.h

@@ -43,6 +43,8 @@ public:
 	 **/
 	 **/
 	WeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 	WeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 
 
+	WeldJoint(Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected, float referenceAngle);
+
 	virtual ~WeldJoint();
 	virtual ~WeldJoint();
 
 
 	/**
 	/**
@@ -67,10 +69,17 @@ public:
 	 **/
 	 **/
 	float getDampingRatio() const;
 	float getDampingRatio() const;
 
 
+	/**
+	 * Gets the reference angle.
+	 **/
+	float getReferenceAngle() const;
+
 private:
 private:
 
 
 	// The Box2D weld joint object.
 	// The Box2D weld joint object.
 	b2WeldJoint *joint;
 	b2WeldJoint *joint;
+
+	void init(b2WeldJointDef &def, Body *body1, Body *body2, float xA, float yA, float xB, float yB, bool collideConnected);
 };
 };
 
 
 } // box2d
 } // box2d

+ 9 - 3
src/modules/physics/box2d/wrap_Physics.cpp

@@ -219,11 +219,13 @@ int w_newRevoluteJoint(lua_State *L)
 	float yA = (float)luaL_checknumber(L, 4);
 	float yA = (float)luaL_checknumber(L, 4);
 	float xB, yB;
 	float xB, yB;
 	bool collideConnected;
 	bool collideConnected;
+	float referenceAngle = 0.0f;
 	if (lua_gettop(L) >= 6)
 	if (lua_gettop(L) >= 6)
 	{
 	{
 		xB = (float)luaL_checknumber(L, 5);
 		xB = (float)luaL_checknumber(L, 5);
 		yB = (float)luaL_checknumber(L, 6);
 		yB = (float)luaL_checknumber(L, 6);
 		collideConnected = luax_optboolean(L, 7, false);
 		collideConnected = luax_optboolean(L, 7, false);
+		referenceAngle = (float)luaL_optnumber(L, 8, referenceAngle);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -233,7 +235,7 @@ int w_newRevoluteJoint(lua_State *L)
 	}
 	}
 	RevoluteJoint *j;
 	RevoluteJoint *j;
 	luax_catchexcept(L, [&]() {
 	luax_catchexcept(L, [&]() {
-		j = instance()->newRevoluteJoint(body1, body2, xA, yA, xB, yB, collideConnected);
+		j = instance()->newRevoluteJoint(body1, body2, xA, yA, xB, yB, collideConnected, referenceAngle);
 	});
 	});
 	luax_pushtype(L, PHYSICS_REVOLUTE_JOINT_ID, j);
 	luax_pushtype(L, PHYSICS_REVOLUTE_JOINT_ID, j);
 	j->release();
 	j->release();
@@ -248,6 +250,7 @@ int w_newPrismaticJoint(lua_State *L)
 	float yA = (float)luaL_checknumber(L, 4);
 	float yA = (float)luaL_checknumber(L, 4);
 	float xB, yB, ax, ay;
 	float xB, yB, ax, ay;
 	bool collideConnected;
 	bool collideConnected;
+	float referenceAngle = 0.0f;
 	if (lua_gettop(L) >= 8)
 	if (lua_gettop(L) >= 8)
 	{
 	{
 		xB = (float)luaL_checknumber(L, 5);
 		xB = (float)luaL_checknumber(L, 5);
@@ -255,6 +258,7 @@ int w_newPrismaticJoint(lua_State *L)
 		ax = (float)luaL_checknumber(L, 7);
 		ax = (float)luaL_checknumber(L, 7);
 		ay = (float)luaL_checknumber(L, 8);
 		ay = (float)luaL_checknumber(L, 8);
 		collideConnected = luax_optboolean(L, 9, false);
 		collideConnected = luax_optboolean(L, 9, false);
+		referenceAngle = (float)luaL_optnumber(L, 10, referenceAngle);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -266,7 +270,7 @@ int w_newPrismaticJoint(lua_State *L)
 	}
 	}
 	PrismaticJoint *j;
 	PrismaticJoint *j;
 	luax_catchexcept(L, [&]() {
 	luax_catchexcept(L, [&]() {
-		j = instance()->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
+		j = instance()->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected, referenceAngle);
 	});
 	});
 	luax_pushtype(L, PHYSICS_PRISMATIC_JOINT_ID, j);
 	luax_pushtype(L, PHYSICS_PRISMATIC_JOINT_ID, j);
 	j->release();
 	j->release();
@@ -350,11 +354,13 @@ int w_newWeldJoint(lua_State *L)
 	float yA = (float)luaL_checknumber(L, 4);
 	float yA = (float)luaL_checknumber(L, 4);
 	float xB, yB;
 	float xB, yB;
 	bool collideConnected;
 	bool collideConnected;
+	float referenceAngle = 0.0f;
 	if (lua_gettop(L) >= 6)
 	if (lua_gettop(L) >= 6)
 	{
 	{
 		xB = (float)luaL_checknumber(L, 5);
 		xB = (float)luaL_checknumber(L, 5);
 		yB = (float)luaL_checknumber(L, 6);
 		yB = (float)luaL_checknumber(L, 6);
 		collideConnected = luax_optboolean(L, 7, false);
 		collideConnected = luax_optboolean(L, 7, false);
+		referenceAngle = (float)luaL_optnumber(L, 8, referenceAngle);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -364,7 +370,7 @@ int w_newWeldJoint(lua_State *L)
 	}
 	}
 	WeldJoint *j;
 	WeldJoint *j;
 	luax_catchexcept(L, [&]() {
 	luax_catchexcept(L, [&]() {
-		j = instance()->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
+		j = instance()->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected, referenceAngle);
 	});
 	});
 	luax_pushtype(L, PHYSICS_WELD_JOINT_ID, j);
 	luax_pushtype(L, PHYSICS_WELD_JOINT_ID, j);
 	j->release();
 	j->release();

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

@@ -171,6 +171,13 @@ int w_PrismaticJoint_getAxis(lua_State *L)
 	return t->getAxis(L);
 	return t->getAxis(L);
 }
 }
 
 
+int w_PrismaticJoint_getReferenceAngle(lua_State *L)
+{
+	PrismaticJoint *t = luax_checkprismaticjoint(L, 1);
+	lua_pushnumber(L, t->getReferenceAngle());
+	return 1;
+}
+
 static const luaL_Reg w_PrismaticJoint_functions[] =
 static const luaL_Reg w_PrismaticJoint_functions[] =
 {
 {
 	{ "getJointTranslation", w_PrismaticJoint_getJointTranslation },
 	{ "getJointTranslation", w_PrismaticJoint_getJointTranslation },
@@ -191,6 +198,7 @@ static const luaL_Reg w_PrismaticJoint_functions[] =
 	{ "getUpperLimit", w_PrismaticJoint_getUpperLimit },
 	{ "getUpperLimit", w_PrismaticJoint_getUpperLimit },
 	{ "getLimits", w_PrismaticJoint_getLimits },
 	{ "getLimits", w_PrismaticJoint_getLimits },
 	{ "getAxis", w_PrismaticJoint_getAxis },
 	{ "getAxis", w_PrismaticJoint_getAxis },
+	{ "getReferenceAngle", w_PrismaticJoint_getReferenceAngle },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

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

@@ -164,6 +164,13 @@ int w_RevoluteJoint_getLimits(lua_State *L)
 	return t->getLimits(L);
 	return t->getLimits(L);
 }
 }
 
 
+int w_RevoluteJoint_getReferenceAngle(lua_State *L)
+{
+	RevoluteJoint *t = luax_checkrevolutejoint(L, 1);
+	lua_pushnumber(L, t->getReferenceAngle());
+	return 1;
+}
+
 static const luaL_Reg w_RevoluteJoint_functions[] =
 static const luaL_Reg w_RevoluteJoint_functions[] =
 {
 {
 	{ "getJointAngle", w_RevoluteJoint_getJointAngle },
 	{ "getJointAngle", w_RevoluteJoint_getJointAngle },
@@ -183,6 +190,7 @@ static const luaL_Reg w_RevoluteJoint_functions[] =
 	{ "getLowerLimit", w_RevoluteJoint_getLowerLimit },
 	{ "getLowerLimit", w_RevoluteJoint_getLowerLimit },
 	{ "getUpperLimit", w_RevoluteJoint_getUpperLimit },
 	{ "getUpperLimit", w_RevoluteJoint_getUpperLimit },
 	{ "getLimits", w_RevoluteJoint_getLimits },
 	{ "getLimits", w_RevoluteJoint_getLimits },
+	{ "getReferenceAngle", w_RevoluteJoint_getReferenceAngle },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 

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

@@ -65,12 +65,20 @@ int w_WeldJoint_getDampingRatio(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_WeldJoint_getReferenceAngle(lua_State *L)
+{
+	WeldJoint *t = luax_checkweldjoint(L, 1);
+	lua_pushnumber(L, t->getReferenceAngle());
+	return 1;
+}
+
 static const luaL_Reg w_WeldJoint_functions[] =
 static const luaL_Reg w_WeldJoint_functions[] =
 {
 {
 	{ "setFrequency", w_WeldJoint_setFrequency },
 	{ "setFrequency", w_WeldJoint_setFrequency },
 	{ "getFrequency", w_WeldJoint_getFrequency },
 	{ "getFrequency", w_WeldJoint_getFrequency },
 	{ "setDampingRatio", w_WeldJoint_setDampingRatio },
 	{ "setDampingRatio", w_WeldJoint_setDampingRatio },
 	{ "getDampingRatio", w_WeldJoint_getDampingRatio },
 	{ "getDampingRatio", w_WeldJoint_getDampingRatio },
+	{ "getReferenceAngle", w_WeldJoint_getReferenceAngle },
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };