mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 08:39:45 +00:00
Write png image of the global map for save asynchronously
Write global map to the save file last to give more time for async job to finish.
This commit is contained in:
parent
b43eb29465
commit
a4d7b72511
8 changed files with 74 additions and 19 deletions
|
@ -358,6 +358,8 @@ namespace MWBase
|
|||
|
||||
virtual void onDeleteCustomData(const MWWorld::Ptr& ptr) = 0;
|
||||
virtual void forceLootMode(const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
virtual void asyncPrepareSaveMap() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -759,7 +759,7 @@ namespace MWGui
|
|||
, mGlobal(Settings::Manager::getBool("global", "Map"))
|
||||
, mEventBoxGlobal(nullptr)
|
||||
, mEventBoxLocal(nullptr)
|
||||
, mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue))
|
||||
, mGlobalMapRender(std::make_unique<MWRender::GlobalMap>(localMapRender->getRoot(), workQueue))
|
||||
, mEditNoteDialog()
|
||||
{
|
||||
static bool registered = false;
|
||||
|
@ -1028,7 +1028,6 @@ namespace MWGui
|
|||
|
||||
MapWindow::~MapWindow()
|
||||
{
|
||||
delete mGlobalMapRender;
|
||||
}
|
||||
|
||||
void MapWindow::setCellName(const std::string& cellName)
|
||||
|
@ -1357,6 +1356,11 @@ namespace MWGui
|
|||
marker->eventMouseWheel += MyGUI::newDelegate(this, &MapWindow::onMapZoomed);
|
||||
}
|
||||
|
||||
void MapWindow::asyncPrepareSaveMap()
|
||||
{
|
||||
mGlobalMapRender->asyncWritePng();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
EditNoteDialog::EditNoteDialog()
|
||||
|
|
|
@ -260,6 +260,8 @@ namespace MWGui
|
|||
void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
void asyncPrepareSaveMap();
|
||||
|
||||
private:
|
||||
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
|
@ -304,7 +306,7 @@ namespace MWGui
|
|||
MyGUI::Button* mEventBoxLocal;
|
||||
|
||||
float mGlobalMapZoom = 1.0f;
|
||||
MWRender::GlobalMap* mGlobalMapRender;
|
||||
std::unique_ptr<MWRender::GlobalMap> mGlobalMapRender;
|
||||
|
||||
struct MapMarkerType
|
||||
{
|
||||
|
|
|
@ -2263,4 +2263,9 @@ namespace MWGui
|
|||
for(auto* window : mWindows)
|
||||
window->onDeleteCustomData(ptr);
|
||||
}
|
||||
|
||||
void WindowManager::asyncPrepareSaveMap()
|
||||
{
|
||||
mMap->asyncPrepareSaveMap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -392,6 +392,8 @@ namespace MWGui
|
|||
void onDeleteCustomData(const MWWorld::Ptr& ptr) override;
|
||||
void forceLootMode(const MWWorld::Ptr& ptr) override;
|
||||
|
||||
void asyncPrepareSaveMap() override;
|
||||
|
||||
private:
|
||||
unsigned int mOldUpdateMask; unsigned int mOldCullMask;
|
||||
|
||||
|
|
|
@ -93,6 +93,26 @@ namespace
|
|||
MWRender::GlobalMap* mParent;
|
||||
};
|
||||
|
||||
std::vector<char> writePng(const osg::Image& overlayImage)
|
||||
{
|
||||
std::ostringstream ostream;
|
||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||
if (!readerwriter)
|
||||
{
|
||||
Log(Debug::Error) << "Error: Can't write map overlay: no png readerwriter found";
|
||||
return std::vector<char>();
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(overlayImage, ostream);
|
||||
if (!result.success())
|
||||
{
|
||||
Log(Debug::Warning) << "Error: Can't write map overlay: " << result.message() << " code " << result.status();
|
||||
return std::vector<char>();
|
||||
}
|
||||
|
||||
std::string data = ostream.str();
|
||||
return std::vector<char>(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
|
@ -221,6 +241,20 @@ namespace MWRender
|
|||
osg::ref_ptr<osg::Texture2D> mOverlayTexture;
|
||||
};
|
||||
|
||||
struct GlobalMap::WritePng final : public SceneUtil::WorkItem
|
||||
{
|
||||
osg::ref_ptr<const osg::Image> mOverlayImage;
|
||||
std::vector<char> mImageData;
|
||||
|
||||
explicit WritePng(osg::ref_ptr<const osg::Image> overlayImage)
|
||||
: mOverlayImage(std::move(overlayImage)) {}
|
||||
|
||||
void doWork() override
|
||||
{
|
||||
mImageData = writePng(*mOverlayImage);
|
||||
}
|
||||
};
|
||||
|
||||
GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue)
|
||||
: mRoot(root)
|
||||
, mWorkQueue(workQueue)
|
||||
|
@ -400,23 +434,15 @@ namespace MWRender
|
|||
map.mBounds.mMinY = mMinY;
|
||||
map.mBounds.mMaxY = mMaxY;
|
||||
|
||||
std::ostringstream ostream;
|
||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||
if (!readerwriter)
|
||||
if (mWritePng != nullptr)
|
||||
{
|
||||
Log(Debug::Error) << "Error: Can't write map overlay: no png readerwriter found";
|
||||
mWritePng->waitTillDone();
|
||||
map.mImageData = std::move(mWritePng->mImageData);
|
||||
mWritePng = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mOverlayImage, ostream);
|
||||
if (!result.success())
|
||||
{
|
||||
Log(Debug::Warning) << "Error: Can't write map overlay: " << result.message() << " code " << result.status();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string data = ostream.str();
|
||||
map.mImageData = std::vector<char>(data.begin(), data.end());
|
||||
map.mImageData = writePng(*mOverlayImage);
|
||||
}
|
||||
|
||||
struct Box
|
||||
|
@ -606,4 +632,11 @@ namespace MWRender
|
|||
cam->removeChildren(0, cam->getNumChildren());
|
||||
mRoot->removeChild(cam);
|
||||
}
|
||||
|
||||
void GlobalMap::asyncWritePng()
|
||||
{
|
||||
// Use deep copy to avoid any sychronization
|
||||
mWritePng = new WritePng(new osg::Image(*mOverlayImage, osg::CopyOp::DEEP_COPY_ALL));
|
||||
mWorkQueue->addWorkItem(mWritePng, /*front=*/true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,11 @@ namespace MWRender
|
|||
|
||||
void ensureLoaded();
|
||||
|
||||
void asyncWritePng();
|
||||
|
||||
private:
|
||||
struct WritePng;
|
||||
|
||||
/**
|
||||
* Request rendering a 2d quad onto mOverlayTexture.
|
||||
* x, y, width and height are the destination coordinates (top-left coordinate origin)
|
||||
|
@ -121,6 +125,7 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||
osg::ref_ptr<CreateMapWorkItem> mWorkItem;
|
||||
osg::ref_ptr<WritePng> mWritePng;
|
||||
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
|
|
|
@ -190,6 +190,8 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
{
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->asyncPrepareSaveMap();
|
||||
|
||||
if (!character)
|
||||
{
|
||||
MWWorld::ConstPtr player = MWMechanics::getPlayer();
|
||||
|
@ -257,9 +259,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
|
||||
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getMechanicsManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getInputManager()->countSavedGameRecords();
|
||||
+MWBase::Environment::get().getInputManager()->countSavedGameRecords()
|
||||
+MWBase::Environment::get().getWindowManager()->countSavedGameRecords();
|
||||
writer.setRecordCount (recordCount);
|
||||
|
||||
writer.save (stream);
|
||||
|
@ -282,9 +284,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
MWBase::Environment::get().getLuaManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getWorld()->write (writer, listener);
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
|
||||
MWBase::Environment::get().getWindowManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getMechanicsManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getInputManager()->write(writer, listener);
|
||||
MWBase::Environment::get().getWindowManager()->write(writer, listener);
|
||||
|
||||
// Ensure we have written the number of records that was estimated
|
||||
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
|
||||
|
|
Loading…
Reference in a new issue