mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-23 19:20:56 +00:00
Notify about saved screenshot
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.
This commit is contained in:
parent
f7a6be053d
commit
5103120eef
@ -218,6 +218,14 @@ namespace
|
||||
if (Settings::Manager::getInt("async num threads", "Physics") == 0)
|
||||
profiler.removeUserStatsLine(" -Async");
|
||||
}
|
||||
|
||||
struct ScheduleNonDialogMessageBox
|
||||
{
|
||||
void operator()(std::string message) const
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->scheduleMessageBox(std::move(message), MWGui::ShowInDialogueMode_Never);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void OMW::Engine::executeLocalScripts()
|
||||
@ -676,7 +684,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||
mWorkQueue,
|
||||
new SceneUtil::WriteScreenshotToFileOperation(
|
||||
mCfgMgr.getScreenshotPath().string(),
|
||||
Settings::Manager::getString("screenshot format", "General")
|
||||
Settings::Manager::getString("screenshot format", "General"),
|
||||
ScheduleNonDialogMessageBox {}
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -228,6 +228,8 @@ namespace MWBase
|
||||
virtual void exitCurrentGuiMode() = 0;
|
||||
|
||||
virtual void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0;
|
||||
/// Puts message into a queue to show on the next update. Thread safe alternative for messageBox.
|
||||
virtual void scheduleMessageBox(std::string message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0;
|
||||
virtual void staticMessageBox(const std::string& message) = 0;
|
||||
virtual void removeStaticMessageBox() = 0;
|
||||
virtual void interactiveMessageBox (const std::string& message,
|
||||
|
@ -749,6 +749,11 @@ namespace MWGui
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::scheduleMessageBox(std::string message, enum MWGui::ShowInDialogueMode showInDialogueMode)
|
||||
{
|
||||
mScheduledMessageBoxes.lock()->emplace_back(std::move(message), showInDialogueMode);
|
||||
}
|
||||
|
||||
void WindowManager::staticMessageBox(const std::string& message)
|
||||
{
|
||||
mMessageBoxManager->createMessageBox(message, true);
|
||||
@ -803,6 +808,8 @@ namespace MWGui
|
||||
|
||||
void WindowManager::update (float frameDuration)
|
||||
{
|
||||
handleScheduledMessageBoxes();
|
||||
|
||||
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
|
||||
MWBase::StateManager::State_NoGame;
|
||||
|
||||
@ -2204,4 +2211,12 @@ namespace MWGui
|
||||
{
|
||||
return mVersionDescription;
|
||||
}
|
||||
|
||||
void WindowManager::handleScheduledMessageBoxes()
|
||||
{
|
||||
const auto scheduledMessageBoxes = mScheduledMessageBoxes.lock();
|
||||
for (const ScheduledMessageBox& v : *scheduledMessageBoxes)
|
||||
messageBox(v.mMessage, v.mShowInDialogueMode);
|
||||
scheduledMessageBoxes->clear();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
**/
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
@ -16,6 +17,7 @@
|
||||
#include <components/sdlutil/events.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
#include <components/misc/guarded.hpp>
|
||||
|
||||
#include "mapwindow.hpp"
|
||||
#include "statswatcher.hpp"
|
||||
@ -264,6 +266,7 @@ namespace MWGui
|
||||
void exitCurrentGuiMode() override;
|
||||
|
||||
void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) override;
|
||||
void scheduleMessageBox (std::string message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) override;
|
||||
void staticMessageBox(const std::string& message) override;
|
||||
void removeStaticMessageBox() override;
|
||||
void interactiveMessageBox (const std::string& message,
|
||||
@ -524,6 +527,17 @@ namespace MWGui
|
||||
|
||||
float mScalingFactor;
|
||||
|
||||
struct ScheduledMessageBox
|
||||
{
|
||||
std::string mMessage;
|
||||
MWGui::ShowInDialogueMode mShowInDialogueMode;
|
||||
|
||||
ScheduledMessageBox(std::string&& message, MWGui::ShowInDialogueMode showInDialogueMode)
|
||||
: mMessage(std::move(message)), mShowInDialogueMode(showInDialogueMode) {}
|
||||
};
|
||||
|
||||
Misc::ScopeGuarded<std::vector<ScheduledMessageBox>> mScheduledMessageBoxes;
|
||||
|
||||
/**
|
||||
* Called when MyGUI tries to retrieve a tag's value. Tags must be denoted in #{tag} notation and will be replaced upon setting a user visible text/property.
|
||||
* Supported syntax:
|
||||
@ -555,6 +569,8 @@ namespace MWGui
|
||||
void updatePinnedWindows();
|
||||
|
||||
void enableScene(bool enable);
|
||||
|
||||
void handleScheduledMessageBoxes();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -51,59 +51,74 @@ namespace
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
void writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
|
||||
const osg::Image& image)
|
||||
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 << screenshotPath << "/screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << "." << screenshotFormat;
|
||||
stream << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << "." << screenshotFormat;
|
||||
|
||||
} while (boost::filesystem::exists(stream.str()));
|
||||
lastFileName = stream.str();
|
||||
lastFilePath = screenshotPath + "/" + lastFileName;
|
||||
|
||||
} while (boost::filesystem::exists(lastFilePath));
|
||||
|
||||
boost::filesystem::ofstream outStream;
|
||||
outStream.open(boost::filesystem::path(stream.str()), std::ios::binary);
|
||||
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;
|
||||
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)
|
||||
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
|
||||
{
|
||||
writeScreenshotToFile(mScreenshotPath, mScreenshotFormat, image);
|
||||
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,
|
||||
|
@ -15,19 +15,21 @@ namespace SceneUtil
|
||||
{
|
||||
class WorkQueue;
|
||||
|
||||
void writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
|
||||
const osg::Image& image);
|
||||
std::string writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
|
||||
const osg::Image& image);
|
||||
|
||||
class WriteScreenshotToFileOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation
|
||||
{
|
||||
public:
|
||||
WriteScreenshotToFileOperation(const std::string& screenshotPath, const std::string& screenshotFormat);
|
||||
WriteScreenshotToFileOperation(const std::string& screenshotPath, const std::string& screenshotFormat,
|
||||
std::function<void (std::string)> callback);
|
||||
|
||||
void operator()(const osg::Image& image, const unsigned int context_id) override;
|
||||
|
||||
private:
|
||||
const std::string mScreenshotPath;
|
||||
const std::string mScreenshotFormat;
|
||||
const std::function<void (std::string)> mCallback;
|
||||
};
|
||||
|
||||
class AsyncScreenCaptureOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation
|
||||
|
Loading…
x
Reference in New Issue
Block a user