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 28033132f..389bedc9a 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -1223,7 +1223,17 @@ static int l_screenshot(lua::State* L) { if (engine->isHeadless()) { return 0; } - auto image = engine->getWindow().takeScreenshot(); + 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)); }