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

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-09-30 10:25:14 -03:00
parent bdc6eb3b29
commit 8068b0f1d4
3 changed files with 85 additions and 42 deletions
+4 -5
View File
@@ -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; ScreenshotCallback callback = nullptr;
Reference *ref; void *data = nullptr;
}; };
struct RenderTarget struct RenderTarget
+3 -3
View File
@@ -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();
} }
+78 -34
View File
@@ -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;
const char *filename = luaL_checkstring(L, lua_upvalueindex(1));
const char *ext = luaL_checkstring(L, lua_upvalueindex(2));
image::FormatHandler::EncodedFormat format; image::FormatHandler::EncodedFormat format;
if (!image::ImageData::getConstant(ext, format)) };
return 0;
try static void screenshotFileCallback(const Graphics::ScreenshotInfo *info, love::image::ImageData *i, void * /*gd*/)
{
if (info == nullptr)
return;
ScreenshotFileInfo *fileinfo = (ScreenshotFileInfo *) info->data;
if (i != nullptr && fileinfo != nullptr)
{ {
id->encode(format, filename, true); try
} {
catch (love::Exception &e) i->encode(fileinfo->format, fileinfo->filename.c_str(), true);
{ }
printf("Screenshot encoding or saving failed: %s", e.what()); catch (love::Exception &e)
// Do nothing... {
printf("Screenshot encoding or saving failed: %s", e.what());
// Do nothing...
}
} }
return 0; 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)
{
Proxy p;
p.type = &love::image::ImageData::type;
p.object = i;
if (i != nullptr)
channel->push(Variant(p.type, &p));
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); ScreenshotFileInfo *fileinfo = new ScreenshotFileInfo;
luax_pushstring(L, ext); fileinfo->filename = filename;
lua_pushcclosure(L, screenshotSaveToFile, 2); fileinfo->format = format;
lua_replace(L, 1);
info.data = fileinfo;
info.callback = screenshotFileCallback;
} }
else if (luax_istype(L, 1, love::thread::Channel::type))
luaL_checktype(L, 1, LUA_TFUNCTION); {
auto *channel = love::thread::luax_checkchannel(L, 1);
Graphics::ScreenshotInfo info; channel->retain();
info.callback = screenshotCallback; info.data = channel;
info.callback = screenshotChannelCallback;
lua_pushvalue(L, 1); }
info.ref = luax_refif(L, LUA_TFUNCTION); else
lua_pop(L, 1); 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;