Browse Source

Added a variant of love.graphics.clear which accepts a color table argument for each active canvas, allowing it to clear active canvases to different colors without having to call love.graphics.setCanvas.

Alex Szpakowski 10 years ago
parent
commit
468127eed4

+ 41 - 0
src/modules/graphics/opengl/Graphics.cpp

@@ -424,6 +424,47 @@ void Graphics::clear(Color c)
 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 }
 
 
+void Graphics::clear(const std::vector<Color> &colors)
+{
+	if (colors.size() == 0)
+		return;
+
+	if (states.back().canvases.size() == 0)
+		return clear(colors[0]);
+
+	if (colors.size() != states.back().canvases.size())
+		throw love::Exception("Number of clear colors must match the number of active canvases (%ld)", states.back().canvases.size());
+
+	std::vector<GLenum> bufs;
+
+	for (int i = 0; i < (int) colors.size(); i++)
+	{
+		const GLfloat c[] = {colors[i].r/255.f, colors[i].g/255.f, colors[i].b/255.f, colors[i].a/255.f};
+
+		if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0)
+			glClearBufferfv(GL_COLOR, i, c);
+		else
+		{
+			bufs.push_back(GL_COLOR_ATTACHMENT0 + i);
+			glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
+			glClearColor(c[0], c[1], c[2], c[3]);
+			glClear(GL_COLOR_BUFFER_BIT);
+		}
+	}
+
+	glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	// Revert to the expected draw buffers once we're done, if glClearBuffer
+	// wasn't supported.
+	if (!(GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0))
+	{
+		if (bufs.size() > 1)
+			glDrawBuffers((int) bufs.size(), &bufs[0]);
+		else
+			glDrawBuffer(GL_COLOR_ATTACHMENT0);
+	}
+}
+
 void Graphics::discard(bool color, bool stencil)
 void Graphics::discard(bool color, bool stencil)
 {
 {
 	if (!(GLAD_VERSION_4_3 || GLAD_ARB_invalidate_subdata || GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer))
 	if (!(GLAD_VERSION_4_3 || GLAD_ARB_invalidate_subdata || GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer))

+ 5 - 0
src/modules/graphics/opengl/Graphics.h

@@ -86,6 +86,11 @@ public:
 	 **/
 	 **/
 	void clear(Color c);
 	void clear(Color c);
 
 
+	/**
+	 * Clears each active canvas to a different color.
+	 **/
+	void clear(const std::vector<Color> &colors);
+
 	/**
 	/**
 	 * Discards the contents of the screen.
 	 * Discards the contents of the screen.
 	 **/
 	 **/

+ 25 - 14
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -47,31 +47,42 @@ int w_reset(lua_State *)
 
 
 int w_clear(lua_State *L)
 int w_clear(lua_State *L)
 {
 {
-	Color color;
+	std::vector<Color> colors(1);
 
 
 	if (lua_isnoneornil(L, 1))
 	if (lua_isnoneornil(L, 1))
-		color.set(0, 0, 0, 0);
+		colors[0].set(0, 0, 0, 0);
 	else if (lua_istable(L, 1))
 	else if (lua_istable(L, 1))
 	{
 	{
-		for (int i = 1; i <= 4; i++)
-			lua_rawgeti(L, 1, i);
+		colors.resize((size_t) lua_gettop(L));
+
+		for (int i = 0; i < lua_gettop(L); i++)
+		{
+			for (int j = 1; j <= 4; j++)
+				lua_rawgeti(L, i + 1, j);
 
 
-		color.r = (unsigned char) luaL_checkinteger(L, -4);
-		color.g = (unsigned char) luaL_checkinteger(L, -3);
-		color.b = (unsigned char) luaL_checkinteger(L, -2);
-		color.a = (unsigned char) luaL_optinteger(L, -1, 255);
+			colors[i].r = (unsigned char) luaL_checkinteger(L, -4);
+			colors[i].g = (unsigned char) luaL_checkinteger(L, -3);
+			colors[i].b = (unsigned char) luaL_checkinteger(L, -2);
+			colors[i].a = (unsigned char) luaL_optinteger(L, -1, 255);
 
 
-		lua_pop(L, 4);
+			lua_pop(L, 4);
+		}
 	}
 	}
 	else
 	else
 	{
 	{
-		color.r = (unsigned char) luaL_checkinteger(L, 1);
-		color.g = (unsigned char) luaL_checkinteger(L, 2);
-		color.b = (unsigned char) luaL_checkinteger(L, 3);
-		color.a = (unsigned char) luaL_optinteger(L, 4, 255);
+		colors[0].r = (unsigned char) luaL_checkinteger(L, 1);
+		colors[0].g = (unsigned char) luaL_checkinteger(L, 2);
+		colors[0].b = (unsigned char) luaL_checkinteger(L, 3);
+		colors[0].a = (unsigned char) luaL_optinteger(L, 4, 255);
 	}
 	}
 
 
-	instance()->clear(color);
+	luax_catchexcept(L, [&]() {
+		if (colors.size() == 1)
+			instance()->clear(colors[0]);
+		else
+			instance()->clear(colors);
+	});
+
 	return 0;
 	return 0;
 }
 }