Commits

Alex Szpakowski committed 5e72234 Merge

Merged default into minor

Comments (0)

Files changed (21)

 
   * Added Shader:getExternVariable.
   * Added several new canvas texture formats.
-  * Added love.graphics.hasCanvasFormat.
-  * Added an optional duration argument to Joystick:setVibration.
+  * Added love.graphics.getCanvasFormats.
+  * Added love.graphics.getCompressedImageFormats.
+  * Added ParticleSystem:setQuads.
+  * Added SpriteBatch:flush.
+  * Added optional duration argument to Joystick:setVibration.
   * Added love.joystick.loadGamepadMappings and love.joystick.saveGamepadMappings.
   * Added Joint:setUserData and Joint:getUserData.
   * Added Body:getWorld.
   * Added love.window.getDisplayName.
+  * Added love.window.minimize.
+
+  * Deprecated SpriteBatch:bind and SpriteBatch:unbind.
+  * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'.
+  * Deprecated the 'hdrcanvas' graphics feature enum in favor of getCanvasFormats.
+  * Deprecated the 'dxt' and 'bc5' graphics feature enums in favor of getCompressedImageFormats.
 
   * Fixed shader:getWarnings returning unnecessary information.
   * Fixed love.filesystem.setIdentity breaking in some situations when called multiple times.
   * Fixed Image:refresh generating mipmaps multiple times if mipmap filtering is enabled.
   * Fixed Mesh:setDrawRange when the Mesh has a vertex map set.
   * Fixed internal detection of the 'position' and 'effect' shader functions.
+  * Fixed Texture memory leak when Meshes are garbage collected.
 
   * Renamed all cases of FSAA to MSAA. The FSAA names still exist for backward-compatibility.
 

src/modules/graphics/Graphics.cpp

 	{ "multicanvas", Graphics::SUPPORT_MULTI_CANVAS },
 	{ "dxt", Graphics::SUPPORT_DXT },
 	{ "bc5", Graphics::SUPPORT_BC5 },
-	{ "instancing", Graphics::SUPPORT_INSTANCING },
 	{ "srgb", Graphics::SUPPORT_SRGB },
 };
 

src/modules/graphics/Graphics.h

 		SUPPORT_MULTI_CANVAS,
 		SUPPORT_DXT,
 		SUPPORT_BC5,
-		SUPPORT_INSTANCING,
 		SUPPORT_SRGB,
 		SUPPORT_MAX_ENUM
 	};

src/modules/graphics/opengl/Graphics.cpp

 	return limit;
 }
 
+bool Graphics::isSupported(Support feature) const
+{
+	switch (feature)
+	{
+	case SUPPORT_HDR_CANVAS:
+		return Canvas::isFormatSupported(Canvas::FORMAT_HDR);
+	case SUPPORT_MULTI_CANVAS:
+		return Canvas::isMultiCanvasSupported();
+	case SUPPORT_DXT:
+		return Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_DXT5);
+	case SUPPORT_BC5:
+		return Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_BC5);
+	case SUPPORT_SRGB:
+		// sRGB support for the screen is guaranteed if it's supported as a
+		// Canvas format.
+		return Canvas::isFormatSupported(Canvas::FORMAT_SRGB);
+	default:
+		return false;
+	}
+}
+
 void Graphics::push()
 {
 	if (userMatrices == matrixLimit)

src/modules/graphics/opengl/Graphics.h

 	 **/
 	double getSystemLimit(SystemLimit limittype) const;
 
+	/**
+	 * Gets whether a graphics feature is supported on this system.
+	 **/
+	bool isSupported(Support feature) const;
+
 	void push();
 	void pop();
 	void rotate(float r);

src/modules/graphics/opengl/wrap_Graphics.cpp

 int w_isSupported(lua_State *L)
 {
 	bool supported = true;
-	size_t len = lua_gettop(L);
-	Graphics::Support support;
-	for (unsigned int i = 1; i <= len; i++)
+
+	for (int i = 1; i <= lua_gettop(L); i++)
 	{
 		const char *str = luaL_checkstring(L, i);
-		if (!Graphics::getConstant(str, support))
+		Graphics::Support feature;
+		if (!Graphics::getConstant(str, feature))
 			return luaL_error(L, "Invalid graphics feature: %s", str);
 
-		switch (support)
+		if (!instance->isSupported(feature))
 		{
-		case Graphics::SUPPORT_HDR_CANVAS:
-			if (!Canvas::isFormatSupported(Canvas::FORMAT_HDR))
-				supported = false;
+			supported = false;
 			break;
-		case Graphics::SUPPORT_MULTI_CANVAS:
-			if (!Canvas::isMultiCanvasSupported())
-				supported = false;
-			break;
-		case Graphics::SUPPORT_DXT:
-			if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_DXT5))
-				supported = false;
-			break;
-		case Graphics::SUPPORT_BC5:
-			if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_BC5))
-				supported = false;
-			break;
-		case Graphics::SUPPORT_INSTANCING:
-			if (!GLEE_ARB_draw_instanced)
-				supported = false;
-			break;
-		case Graphics::SUPPORT_SRGB:
-			if (!Canvas::isFormatSupported(Canvas::FORMAT_SRGB))
-				supported = false;
-			break;
-		default:
-			supported = false;
 		}
-		if (!supported)
-			break;
 	}
-	lua_pushboolean(L, supported);
+
+	luax_pushboolean(L, supported);
 	return 1;
 }
 
-int w_hasCanvasFormat(lua_State *L)
+int w_getCanvasFormats(lua_State *L)
 {
-	const char *str = luaL_checkstring(L, 1);
-	Canvas::Format format;
+	lua_createtable(L, 0, (int) Canvas::FORMAT_MAX_ENUM);
 
-	if (!Canvas::getConstant(str, format))
-		return luaL_error(L, "Invalid canvas format: %s", str);
+	for (int i = 0; i < (int) Canvas::FORMAT_MAX_ENUM; i++)
+	{
+		Canvas::Format format = (Canvas::Format) i;
+		const char *name = nullptr;
 
-	luax_pushboolean(L, Canvas::isFormatSupported(format));
+		if (!Canvas::getConstant(format, name))
+			continue;
+
+		luax_pushboolean(L, Canvas::isFormatSupported(format));
+		lua_setfield(L, -2, name);
+	}
+
+	return 1;
+}
+
+int w_getCompressedImageFormats(lua_State *L)
+{
+	lua_createtable(L, 0, (int) image::CompressedData::FORMAT_MAX_ENUM);
+
+	for (int i = 0; i < (int) image::CompressedData::FORMAT_MAX_ENUM; i++)
+	{
+		image::CompressedData::Format format = (image::CompressedData::Format) i;
+		const char *name = nullptr;
+
+		if (format == image::CompressedData::FORMAT_UNKNOWN)
+			continue;
+
+		if (!image::CompressedData::getConstant(format, name))
+			continue;
+
+		luax_pushboolean(L, Image::hasCompressedTextureSupport(format));
+		lua_setfield(L, -2, name);
+	}
+
 	return 1;
 }
 
 	{ "getShader", w_getShader },
 
 	{ "isSupported", w_isSupported },
-	{ "hasCanvasFormat", w_hasCanvasFormat },
+	{ "getCanvasFormats", w_getCanvasFormats },
+	{ "getCompressedImageFormats", w_getCompressedImageFormats },
 	{ "getRendererInfo", w_getRendererInfo },
 	{ "getSystemLimit", w_getSystemLimit },
 

src/modules/graphics/opengl/wrap_Graphics.h

 int w_setShader(lua_State *L);
 int w_getShader(lua_State *L);
 int w_isSupported(lua_State *L);
-int w_hasCanvasFormat(lua_State *L);
+int w_getCanvasFormats(lua_State *L);
+int w_getCompressedImageFormats(lua_State *L);
 int w_getRendererInfo(lua_State *L);
 int w_getSystemLimit(lua_State *L);
 int w_draw(lua_State *L);

src/modules/physics/box2d/Body.cpp

 	return 1;
 }
 
+int Body::getContactList(lua_State *L) const
+{
+	lua_newtable(L);
+	const b2ContactEdge *ce = body->GetContactList();
+	int i = 1;
+	do
+	{
+		if (!ce)
+			break;
+
+		Contact *contact = (Contact *) Memoizer::find(ce->contact);
+		if (!contact)
+			contact = new Contact(ce->contact);
+		else
+			contact->retain();
+		
+		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
+		lua_rawseti(L, -2, i);
+		i++;
+	}
+	while ((ce = ce->next));
+	return 1;
+}
+
 b2Vec2 Body::getVector(lua_State *L)
 {
 	love::luax_assert_argc(L, 2, 2);

src/modules/physics/box2d/Body.h

 	int getFixtureList(lua_State *L) const;
 
 	/**
+	 * Get an array of all active Contacts attached to this Body.
+	 * This list changes during World:update and you may miss some collisions
+	 * if you don't use the collision callbacks.
+	 **/
+	int getContactList(lua_State *L) const;
+
+	/**
 	 * Destroy this body.
 	 **/
 	void destroy();

src/modules/physics/box2d/Contact.cpp

 	childB = contact->GetChildIndexB();
 }
 
+void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB)
+{
+	fixtureA = (Fixture *) Memoizer::find(contact->GetFixtureA());
+	fixtureB = (Fixture *) Memoizer::find(contact->GetFixtureB());
+
+	if (!fixtureA || !fixtureB)
+		throw love::Exception("A fixture has escaped Memoizer!");
+}
+
 } // box2d
 } // physics
 } // love

src/modules/physics/box2d/Contact.h

 
 	void getChildren(int &childA, int &childB);
 
+	/**
+	 * Gets the Fixtures associated with this Contact.
+	 **/
+	void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB);
+
 private:
 
 	// The Box2D contact.

src/modules/physics/box2d/World.cpp

 {
 	// Fixtures should be memoized, if we created them
 	Fixture *a = (Fixture *)Memoizer::find(fixtureA);
-	if (!a)
-		throw love::Exception("A fixture has escaped Memoizer!");
 	Fixture *b = (Fixture *)Memoizer::find(fixtureB);
-	if (!b)
+	if (!a || !b)
 		throw love::Exception("A fixture has escaped Memoizer!");
 	return filter.process(a, b);
 }

src/modules/physics/box2d/wrap_Body.cpp

 	return n;
 }
 
+int w_Body_getContactList(lua_State *L)
+{
+	Body *t = luax_checkbody(L, 1);
+	lua_remove(L, 1);
+	int n = 0;
+	luax_catchexcept(L, [&](){ n = t->getContactList(L); });
+	return n;
+}
+
 int w_Body_destroy(lua_State *L)
 {
 	Body *t = luax_checkbody(L, 1);
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "getWorld", w_Body_getWorld },
 	{ "getFixtureList", w_Body_getFixtureList },
+	{ "getContactList", w_Body_getContactList },
 	{ "destroy", w_Body_destroy },
 	{ "setUserData", w_Body_setUserData },
 	{ "getUserData", w_Body_getUserData },

src/modules/physics/box2d/wrap_Body.h

 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_getWorld(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
+int w_Body_getContactList(lua_State *L);
 int w_Body_destroy(lua_State *L);
 int w_Body_setUserData(lua_State *L);
 int w_Body_getUserData(lua_State *L);

src/modules/physics/box2d/wrap_Contact.cpp

  **/
 
 #include "wrap_Contact.h"
+#include "Fixture.h"
 
 namespace love
 {
 	return 2;
 }
 
+int w_Contact_getFixtures(lua_State *L)
+{
+	Contact *t = luax_checkcontact(L, 1);
+	Fixture *a = nullptr;
+	Fixture *b = nullptr;
+	luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
+
+	a->retain();
+	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
+	b->retain();
+	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
+	return 2;
+}
+
 extern "C" int luaopen_contact(lua_State *L)
 {
 	static const luaL_Reg functions[] =
 		{ "setTangentSpeed", w_Contact_setTangentSpeed },
 		{ "getTangentSpeed", w_Contact_getTangentSpeed },
 		{ "getChildren", w_Contact_getChildren },
+		{ "getFixtures", w_Contact_getFixtures },
 		{ 0, 0 }
 	};
 

src/modules/physics/box2d/wrap_Contact.h

 int w_Contact_setTangentSpeed(lua_State *L);
 int w_Contact_getTangentSpeed(lua_State *L);
 int w_Contact_getChildren(lua_State *L);
+int w_Contact_getFixtures(lua_State *L);
 extern "C" int luaopen_contact(lua_State *L);
 
 } // box2d

src/modules/window/Window.h

 	virtual bool setIcon(love::image::ImageData *imgd) = 0;
 	virtual love::image::ImageData *getIcon() = 0;
 
+	virtual void minimize() = 0;
+
 	// default no-op implementation
 	virtual void swapBuffers();
 

src/modules/window/sdl/Window.cpp

 	return curMode.icon;
 }
 
+void Window::minimize()
+{
+	if (window != nullptr)
+		SDL_MinimizeWindow(window);
+}
+
 void Window::swapBuffers()
 {
 	SDL_GL_SwapWindow(window);

src/modules/window/sdl/Window.h

 	bool setIcon(love::image::ImageData *imgd);
 	love::image::ImageData *getIcon();
 
+	void minimize();
+
 	void swapBuffers();
 
 	bool hasFocus() const;

src/modules/window/wrap_Window.cpp

 	return 1;
 }
 
+int w_minimize(lua_State* /*L*/)
+{
+	instance->minimize();
+	return 0;
+}
+
 static const luaL_Reg functions[] =
 {
 	{ "getDisplayCount", w_getDisplayCount },
 	{ "hasMouseFocus", w_hasMouseFocus },
 	{ "isVisible", w_isVisible },
 	{ "getPixelScale", w_getPixelScale },
+	{ "minimize", w_minimize },
 	{ 0, 0 }
 };
 

src/modules/window/wrap_Window.h

 int w_hasMouseFocus(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_getPixelScale(lua_State *L);
+int w_minimize(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_window(lua_State *L);
 
 } // window