Browse Source

Add variant of love.graphics.captureScreenshot which takes a Channel argument.

--HG--
branch : minor
Alex Szpakowski 7 years ago
parent
commit
8068b0f1d4

+ 4 - 5
src/modules/graphics/Graphics.h

@@ -52,8 +52,6 @@
 namespace love
 namespace love
 {
 {
 
 
-class Reference;
-
 namespace graphics
 namespace graphics
 {
 {
 
 
@@ -297,12 +295,13 @@ public:
 		Graphics *gfx;
 		Graphics *gfx;
 	};
 	};
 
 
-	typedef void (*ScreenshotCallback)(love::image::ImageData *i, Reference *ref, void *ud);
+	struct ScreenshotInfo;
+	typedef void (*ScreenshotCallback)(const ScreenshotInfo *info, love::image::ImageData *i, void *ud);
 
 
 	struct ScreenshotInfo
 	struct ScreenshotInfo
 	{
 	{
-		ScreenshotCallback callback;
-		Reference *ref;
+		ScreenshotCallback callback = nullptr;
+		void *data = nullptr;
 	};
 	};
 
 
 	struct RenderTarget
 	struct RenderTarget

+ 3 - 3
src/modules/graphics/opengl/Graphics.cpp

@@ -978,17 +978,17 @@ void Graphics::present(void *screenshotCallbackData)
 			catch (love::Exception &)
 			catch (love::Exception &)
 			{
 			{
 				delete[] screenshot;
 				delete[] screenshot;
-				info.callback(nullptr, info.ref, nullptr);
+				info.callback(&info, nullptr, nullptr);
 				for (int j = i + 1; j < (int) pendingScreenshotCallbacks.size(); j++)
 				for (int j = i + 1; j < (int) pendingScreenshotCallbacks.size(); j++)
 				{
 				{
 					const auto &ninfo = pendingScreenshotCallbacks[j];
 					const auto &ninfo = pendingScreenshotCallbacks[j];
-					ninfo.callback(nullptr, ninfo.ref, nullptr);
+					ninfo.callback(&ninfo, nullptr, nullptr);
 				}
 				}
 				pendingScreenshotCallbacks.clear();
 				pendingScreenshotCallbacks.clear();
 				throw;
 				throw;
 			}
 			}
 
 
-			info.callback(img, info.ref, screenshotCallbackData);
+			info.callback(&info, img, screenshotCallbackData);
 			img->release();
 			img->release();
 		}
 		}
 
 

+ 76 - 32
src/modules/graphics/wrap_Graphics.cpp

@@ -30,6 +30,7 @@
 #include "image/wrap_Image.h"
 #include "image/wrap_Image.h"
 #include "common/Reference.h"
 #include "common/Reference.h"
 #include "math/wrap_Transform.h"
 #include "math/wrap_Transform.h"
+#include "thread/wrap_Channel.h"
 
 
 #include "opengl/Graphics.h"
 #include "opengl/Graphics.h"
 
 
@@ -426,11 +427,19 @@ int w_getCanvas(lua_State *L)
 	}
 	}
 }
 }
 
 
-static void screenshotCallback(love::image::ImageData *i, Reference *ref, void *gd)
+static void screenshotFunctionCallback(const Graphics::ScreenshotInfo *info, love::image::ImageData *i, void *gd)
 {
 {
-	if (i != nullptr)
+	if (info == nullptr)
+		return;
+
+	lua_State *L = (lua_State *) gd;
+	Reference *ref = (Reference *) info->data;
+
+	if (i != nullptr && L != nullptr)
 	{
 	{
-		lua_State *L = (lua_State *) gd;
+		if (ref == nullptr)
+			luaL_error(L, "Internal error in screenshot callback.");
+
 		ref->push(L);
 		ref->push(L);
 		delete ref;
 		delete ref;
 		luax_pushtype(L, i);
 		luax_pushtype(L, i);
@@ -440,33 +449,66 @@ static void screenshotCallback(love::image::ImageData *i, Reference *ref, void *
 		delete ref;
 		delete ref;
 }
 }
 
 
-static int screenshotSaveToFile(lua_State *L)
+struct ScreenshotFileInfo
 {
 {
-	image::ImageData *id = image::luax_checkimagedata(L, 1);
+	std::string filename;
+	image::FormatHandler::EncodedFormat format;
+};
 
 
-	const char *filename = luaL_checkstring(L, lua_upvalueindex(1));
-	const char *ext = luaL_checkstring(L, lua_upvalueindex(2));
+static void screenshotFileCallback(const Graphics::ScreenshotInfo *info, love::image::ImageData *i, void * /*gd*/)
+{
+	if (info == nullptr)
+		return;
 
 
-	image::FormatHandler::EncodedFormat format;
-	if (!image::ImageData::getConstant(ext, format))
-		return 0;
+	ScreenshotFileInfo *fileinfo = (ScreenshotFileInfo *) info->data;
 
 
-	try
+	if (i != nullptr && fileinfo != nullptr)
 	{
 	{
-		id->encode(format, filename, true);
+		try
+		{
+			i->encode(fileinfo->format, fileinfo->filename.c_str(), true);
+		}
+		catch (love::Exception &e)
+		{
+			printf("Screenshot encoding or saving failed: %s", e.what());
+			// Do nothing...
+		}
 	}
 	}
-	catch (love::Exception &e)
+
+	delete fileinfo;
+}
+
+static void screenshotChannelCallback(const Graphics::ScreenshotInfo *info, love::image::ImageData *i, void * /*gd*/)
+{
+	if (info == nullptr)
+		return;
+
+	auto *channel = (love::thread::Channel *) info->data;
+
+	if (channel != nullptr)
 	{
 	{
-		printf("Screenshot encoding or saving failed: %s", e.what());
-		// Do nothing...
-	}
+		Proxy p;
+		p.type = &love::image::ImageData::type;
+		p.object = i;
+		if (i != nullptr)
+			channel->push(Variant(p.type, &p));
 
 
-	return 0;
+		channel->release();
+	}
 }
 }
 
 
 int w_captureScreenshot(lua_State *L)
 int w_captureScreenshot(lua_State *L)
 {
 {
-	if (lua_isstring(L, 1))
+	Graphics::ScreenshotInfo info;
+
+	if (lua_isfunction(L, 1))
+	{
+		lua_pushvalue(L, 1);
+		info.data = luax_refif(L, LUA_TFUNCTION);
+		lua_pop(L, 1);
+		info.callback = screenshotFunctionCallback;
+	}
+	else if (lua_isstring(L, 1))
 	{
 	{
 		std::string filename = luax_checkstring(L, 1);
 		std::string filename = luax_checkstring(L, 1);
 		std::string ext;
 		std::string ext;
@@ -482,24 +524,26 @@ int w_captureScreenshot(lua_State *L)
 		if (!image::ImageData::getConstant(ext.c_str(), format))
 		if (!image::ImageData::getConstant(ext.c_str(), format))
 			return luaL_error(L, "Invalid encoded image format: %s", ext.c_str());
 			return luaL_error(L, "Invalid encoded image format: %s", ext.c_str());
 
 
-		lua_pushvalue(L, 1);
-		luax_pushstring(L, ext);
-		lua_pushcclosure(L, screenshotSaveToFile, 2);
-		lua_replace(L, 1);
-	}
-
-	luaL_checktype(L, 1, LUA_TFUNCTION);
-
-	Graphics::ScreenshotInfo info;
-	info.callback = screenshotCallback;
+		ScreenshotFileInfo *fileinfo = new ScreenshotFileInfo;
+		fileinfo->filename = filename;
+		fileinfo->format = format;
 
 
-	lua_pushvalue(L, 1);
-	info.ref = luax_refif(L, LUA_TFUNCTION);
-	lua_pop(L, 1);
+		info.data = fileinfo;
+		info.callback = screenshotFileCallback;
+	}
+	else if (luax_istype(L, 1, love::thread::Channel::type))
+	{
+		auto *channel = love::thread::luax_checkchannel(L, 1);
+		channel->retain();
+		info.data = channel;
+		info.callback = screenshotChannelCallback;
+	}
+	else
+		return luax_typerror(L, 1, "function, string, or Channel");
 
 
 	luax_catchexcept(L,
 	luax_catchexcept(L,
 		[&]() { instance()->captureScreenshot(info); },
 		[&]() { instance()->captureScreenshot(info); },
-		[&](bool except) { if (except) delete info.ref; }
+		[&](bool except) { if (except) info.callback(&info, nullptr, nullptr); }
 	);
 	);
 
 
 	return 0;
 	return 0;