mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 04:26:38 +00:00 
			
		
		
		
	Show message about saved screenshot via schedule message box. Since screenshot saving happens not in the main thread calling messageBox directly is unsafe. WindowManager::scheduleMessageBox delays message box showing until next update in the main thread.
		
			
				
	
	
		
			137 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "screencapture.hpp"
 | |
| 
 | |
| #include <components/debug/debuglog.hpp>
 | |
| #include <components/sceneutil/workqueue.hpp>
 | |
| 
 | |
| #include <osg/ref_ptr>
 | |
| #include <osg/Image>
 | |
| #include <osgDB/ReaderWriter>
 | |
| #include <osgDB/Registry>
 | |
| 
 | |
| #include <boost/filesystem/fstream.hpp>
 | |
| #include <boost/filesystem/operations.hpp>
 | |
| 
 | |
| #include <cassert>
 | |
| #include <iomanip>
 | |
| #include <sstream>
 | |
| #include <string>
 | |
| 
 | |
| namespace
 | |
| {
 | |
|     class ScreenCaptureWorkItem : public SceneUtil::WorkItem
 | |
|     {
 | |
|         public:
 | |
|             ScreenCaptureWorkItem(const osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation>& 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<osgViewer::ScreenCaptureHandler::CaptureOperation> mImpl;
 | |
|             const osg::ref_ptr<const osg::Image> mImage;
 | |
|             const unsigned int mContextId;
 | |
|     };
 | |
| }
 | |
| 
 | |
| namespace SceneUtil
 | |
| {
 | |
|     std::string writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
 | |
|                                       const osg::Image& image)
 | |
|     {
 | |
|         // Count screenshots.
 | |
|         int shotCount = 0;
 | |
| 
 | |
|         // Find the first unused filename with a do-while
 | |
|         std::ostringstream stream;
 | |
|         std::string lastFileName;
 | |
|         std::string lastFilePath;
 | |
|         do
 | |
|         {
 | |
|             // Reset the stream
 | |
|             stream.str("");
 | |
|             stream.clear();
 | |
| 
 | |
|             stream << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << "." << screenshotFormat;
 | |
| 
 | |
|             lastFileName = stream.str();
 | |
|             lastFilePath = screenshotPath + "/" + lastFileName;
 | |
| 
 | |
|         } while (boost::filesystem::exists(lastFilePath));
 | |
| 
 | |
|         boost::filesystem::ofstream outStream;
 | |
|         outStream.open(boost::filesystem::path(std::move(lastFilePath)), std::ios::binary);
 | |
| 
 | |
|         osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension(screenshotFormat);
 | |
|         if (!readerwriter)
 | |
|         {
 | |
|             Log(Debug::Error) << "Error: Can't write screenshot, no '" << screenshotFormat << "' readerwriter found";
 | |
|             return std::string();
 | |
|         }
 | |
| 
 | |
|         osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(image, outStream);
 | |
|         if (!result.success())
 | |
|         {
 | |
|             Log(Debug::Error) << "Error: Can't write screenshot: " << result.message() << " code " << result.status();
 | |
|             return std::string();
 | |
|         }
 | |
| 
 | |
|         return lastFileName;
 | |
|     }
 | |
| 
 | |
|     WriteScreenshotToFileOperation::WriteScreenshotToFileOperation(const std::string& screenshotPath,
 | |
|                                                                    const std::string& screenshotFormat,
 | |
|                                                                    std::function<void (std::string)> callback)
 | |
|         : mScreenshotPath(screenshotPath)
 | |
|         , mScreenshotFormat(screenshotFormat)
 | |
|         , mCallback(callback)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void WriteScreenshotToFileOperation::operator()(const osg::Image& image, const unsigned int /*context_id*/)
 | |
|     {
 | |
|         std::string fileName;
 | |
|         try
 | |
|         {
 | |
|             fileName = writeScreenshotToFile(mScreenshotPath, mScreenshotFormat, image);
 | |
|         }
 | |
|         catch (const std::exception& e)
 | |
|         {
 | |
|             Log(Debug::Error) << "Failed to write screenshot to file with path=\"" << mScreenshotPath
 | |
|                               << "\", format=\"" << mScreenshotFormat << "\": " << e.what();
 | |
|         }
 | |
|         if (fileName.empty())
 | |
|             mCallback("Failed to save screenshot");
 | |
|         else
 | |
|             mCallback(fileName + " has been saved");
 | |
|     }
 | |
| 
 | |
|     AsyncScreenCaptureOperation::AsyncScreenCaptureOperation(osg::ref_ptr<WorkQueue> queue,
 | |
|                                                              osg::ref_ptr<CaptureOperation> 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));
 | |
|     }
 | |
| }
 |