mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Add variant of love.graphics.captureScreenshot which takes a Channel argument.
--HG-- branch : minor
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user