diff --git a/doc/en/scripting/builtins/libgui.md b/doc/en/scripting/builtins/libgui.md index a7ddbeaec..3dc10612b 100644 --- a/doc/en/scripting/builtins/libgui.md +++ b/doc/en/scripting/builtins/libgui.md @@ -61,6 +61,12 @@ gui.set_active_frame( -- Used for custom projection (e.g., in 3D) [optional] cursorLocator: function() -> number, number ) + +-- Creates a screenshot of a frame as a Canvas object if the frame ID is specified, or the entire window if nil. +gui.screenshot( + -- ID of the frame created via gui.create_frame + [optional] frameId: str +) -> Canvas | nil ``` ## Markup diff --git a/doc/ru/scripting/builtins/libgui.md b/doc/ru/scripting/builtins/libgui.md index ea1221415..51ac7307f 100644 --- a/doc/ru/scripting/builtins/libgui.md +++ b/doc/ru/scripting/builtins/libgui.md @@ -69,6 +69,12 @@ gui.set_active_frame( -- Используется для пользовательской проекции (например в 3D) [опционально] cursorLocator: function() -> number, number ) + +-- Создаёт снимок фрейма в виде объекта Canvas если указан id фрейма, или всего окна, в случае nil. +gui.screenshot( + -- id фрейма, созданного через gui.create_frame + [опционально] frameId: str +) -> Canvas | nil ``` ## Разметка diff --git a/src/graphics/core/Framebuffer.cpp b/src/graphics/core/Framebuffer.cpp index 1dc677096..a10da01ad 100644 --- a/src/graphics/core/Framebuffer.cpp +++ b/src/graphics/core/Framebuffer.cpp @@ -117,6 +117,13 @@ std::shared_ptr Framebuffer::getSharedTexture() const { return texture; } +std::unique_ptr Framebuffer::readData() const { + if (!texture) { + return nullptr; + } + return texture->readData(); +} + uint Framebuffer::getWidth() const { return width; } diff --git a/src/graphics/core/Framebuffer.hpp b/src/graphics/core/Framebuffer.hpp index 5f9dc3491..00c1422a7 100644 --- a/src/graphics/core/Framebuffer.hpp +++ b/src/graphics/core/Framebuffer.hpp @@ -6,6 +6,7 @@ #include class Texture; +class ImageData; class Framebuffer : public Bindable { uint fbo; @@ -36,6 +37,8 @@ public: std::shared_ptr getSharedTexture() const; + std::unique_ptr readData() const; + /// @brief Get framebuffer width uint getWidth() const; /// @brief Get framebuffer height diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 944c32fb5..a5f3010ff 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -378,6 +378,14 @@ std::shared_ptr GUI::getActiveFrame() const { return activeFrame; } +std::shared_ptr GUI::getFrame(const std::string& id) { + const auto& found = frames.find(id); + if (found == frames.end()) { + return nullptr; + } + return found->second; +} + void GUI::remove(UINode* node) noexcept { container->remove(node); } diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp index 97fc0ed37..997b67bea 100644 --- a/src/graphics/ui/GUI.hpp +++ b/src/graphics/ui/GUI.hpp @@ -137,6 +137,8 @@ namespace gui { std::shared_ptr getActiveFrame() const; + std::shared_ptr getFrame(const std::string& id); + /// @brief Remove node from the main container void remove(UINode* node) noexcept; diff --git a/src/graphics/ui/elements/Frame.cpp b/src/graphics/ui/elements/Frame.cpp index 0387f5c1e..fe3562b4f 100644 --- a/src/graphics/ui/elements/Frame.cpp +++ b/src/graphics/ui/elements/Frame.cpp @@ -66,3 +66,10 @@ const std::string& gui::Frame::getOutputTexture() const { const std::string& gui::Frame::getFrameId() const { return frameId; } + +std::unique_ptr gui::Frame::takeScreenshot() const { + if (fbo == nullptr) { + return nullptr; + } + return fbo->readData(); +} diff --git a/src/graphics/ui/elements/Frame.hpp b/src/graphics/ui/elements/Frame.hpp index 1baa7bc91..f7513324b 100644 --- a/src/graphics/ui/elements/Frame.hpp +++ b/src/graphics/ui/elements/Frame.hpp @@ -4,6 +4,7 @@ class Framebuffer; class UiDocument; +class ImageData; namespace gui { class Frame final : public Container { @@ -18,6 +19,8 @@ namespace gui { const std::string& getOutputTexture() const; const std::string& getFrameId() const; + + std::unique_ptr takeScreenshot() const; private: std::string frameId; std::unique_ptr fbo; diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 81e5fc4f7..389bedc9a 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -25,6 +25,7 @@ #include "items/Inventories.hpp" #include "util/stringutil.hpp" #include "world/Level.hpp" +#include "window/Window.hpp" #include "../usertypes/lua_type_canvas.hpp" using namespace gui; @@ -1218,7 +1219,26 @@ static int l_get_active_frame(lua::State* L) { return lua::pushstring(L, frame->getId()); } +static int l_screenshot(lua::State* L) { + if (engine->isHeadless()) { + return 0; + } + std::unique_ptr image; + if (lua::isstring(L, 1)) { + auto& gui = engine->getGUI(); + auto frame = gui.getFrame(lua::require_string(L, 1)); + if (frame == nullptr) { + return 0; + } + image = frame->takeScreenshot(); + } else { + image = engine->getWindow().takeScreenshot(); + } + return lua::newuserdata(L, nullptr, std::move(image)); +} + const luaL_Reg guilib[] = { + {"screenshot", lua::wrap}, {"get_viewport", lua::wrap}, {"getattr", lua::wrap}, {"setattr", lua::wrap},