diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c3b4e3354..a676b70b9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug #6129: Player avatar not displayed correctly for large window sizes when GUI scaling active Bug #6131: Item selection in the avatar window not working correctly for large window sizes Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player + Bug #6143: Capturing a screenshot makes engine to be a temporary unresponsive Feature #2780: A way to see current OpenMW version in the console Feature #5489: MCP: Telekinesis fix for activators Feature #6017: Separate persistent and temporary cell references when saving diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d03891fdc6..76f02fb683 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -670,6 +670,18 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) throw std::runtime_error("Invalid setting: 'preload num threads' must be >0"); mWorkQueue = new SceneUtil::WorkQueue(numThreads); + mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation( + mWorkQueue, + new SceneUtil::WriteScreenshotToFileOperation( + mCfgMgr.getScreenshotPath().string(), + Settings::Manager::getString("screenshot format", "General") + ) + ); + + mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation); + + mViewer->addEventHandler(mScreenCaptureHandler); + // Create input and UI first to set up a bootstrapping environment for // showing a loading screen and keeping the window responsive while doing so @@ -814,14 +826,6 @@ void OMW::Engine::go() mViewer->setUseConfigureAffinity(false); #endif - mScreenCaptureOperation = new SceneUtil::WriteScreenshotToFileOperation( - mCfgMgr.getScreenshotPath().string(), - Settings::Manager::getString("screenshot format", "General")); - - mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation); - - mViewer->addEventHandler(mScreenCaptureHandler); - mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video")); prepareEngine (settings); diff --git a/components/sceneutil/screencapture.cpp b/components/sceneutil/screencapture.cpp index 660f296b63..c010b390aa 100644 --- a/components/sceneutil/screencapture.cpp +++ b/components/sceneutil/screencapture.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -10,9 +11,43 @@ #include #include -#include -#include +#include #include +#include +#include + +namespace +{ + class ScreenCaptureWorkItem : public SceneUtil::WorkItem + { + public: + ScreenCaptureWorkItem(const osg::ref_ptr& impl, + const osg::Image& image, unsigned int contextId) + : mImpl(impl), + mImage(new osg::Image(image)), + mContextId(contextId) + { + assert(mImpl != nullptr); + } + + void doWork() override + { + try + { + (*mImpl)(*mImage, mContextId); + } + catch (const std::exception& e) + { + Log(Debug::Error) << "ScreenCaptureWorkItem exception: " << e.what(); + } + } + + private: + const osg::ref_ptr mImpl; + const osg::ref_ptr mImage; + const unsigned int mContextId; + }; +} namespace SceneUtil { @@ -70,4 +105,18 @@ namespace SceneUtil << "\", format=\"" << mScreenshotFormat << "\": " << e.what(); } } + + AsyncScreenCaptureOperation::AsyncScreenCaptureOperation(osg::ref_ptr queue, + osg::ref_ptr impl) + : mQueue(std::move(queue)), + mImpl(std::move(impl)) + { + assert(mQueue != nullptr); + assert(mImpl != nullptr); + } + + void AsyncScreenCaptureOperation::operator()(const osg::Image& image, const unsigned int context_id) + { + mQueue->addWorkItem(new ScreenCaptureWorkItem(mImpl, image, context_id)); + } } diff --git a/components/sceneutil/screencapture.hpp b/components/sceneutil/screencapture.hpp index 37ff5e39cc..8087095e4e 100644 --- a/components/sceneutil/screencapture.hpp +++ b/components/sceneutil/screencapture.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H #define OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H +#include #include #include @@ -12,6 +13,8 @@ namespace osg namespace SceneUtil { + class WorkQueue; + void writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat, const osg::Image& image); @@ -20,12 +23,25 @@ namespace SceneUtil public: WriteScreenshotToFileOperation(const std::string& screenshotPath, const std::string& screenshotFormat); - void operator()(const osg::Image& image, const unsigned int /*context_id*/) override; + void operator()(const osg::Image& image, const unsigned int context_id) override; private: const std::string mScreenshotPath; const std::string mScreenshotFormat; }; + + class AsyncScreenCaptureOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation + { + public: + AsyncScreenCaptureOperation(osg::ref_ptr queue, + osg::ref_ptr impl); + + void operator()(const osg::Image& image, const unsigned int context_id) override; + + private: + const osg::ref_ptr mQueue; + const osg::ref_ptr mImpl; + }; } #endif