Fixes #1172: Added basic loading/saving progress bar

The progress is not particularly accurate. It simply uses the current / total number of records written/read as indication. Cell records are currently the largest by far, but there is a good chance that could be optimized using a change tracking system.
actorid
scrawl 11 years ago
parent 4555f6ddf6
commit 27a05027f4

@ -5,6 +5,11 @@
#include <stdint.h>
namespace Loading
{
class Listener;
}
namespace ESM
{
class ESMReader;
@ -60,7 +65,7 @@ namespace MWBase
virtual int countSavedGameRecords() const = 0;
virtual void write (ESM::ESMWriter& writer) const = 0;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
};

@ -11,6 +11,11 @@
#include "../mwdialogue/topic.hpp"
#include "../mwdialogue/quest.hpp"
namespace Loading
{
class Listener;
}
namespace ESM
{
class ESMReader;
@ -80,7 +85,7 @@ namespace MWBase
virtual int countSavedGameRecords() const = 0;
virtual void write (ESM::ESMWriter& writer) const = 0;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
};

@ -303,7 +303,7 @@ namespace MWBase
/// Clear all savegame-specific data
virtual void clear() = 0;
virtual void write (ESM::ESMWriter& writer) = 0;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
};
}

@ -108,7 +108,7 @@ namespace MWBase
virtual int countSavedGameRecords() const = 0;
virtual void write (ESM::ESMWriter& writer) const = 0;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap) = 0;

@ -609,7 +609,7 @@ namespace MWDialogue
return 1; // known topics
}
void DialogueManager::write (ESM::ESMWriter& writer) const
void DialogueManager::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
ESM::DialogueState state;
@ -621,6 +621,7 @@ namespace MWDialogue
writer.startRecord (ESM::REC_DIAS);
state.save (writer);
writer.endRecord (ESM::REC_DIAS);
progress.increaseProgress();
}
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)

@ -83,7 +83,7 @@ namespace MWDialogue
virtual int countSavedGameRecords() const;
virtual void write (ESM::ESMWriter& writer) const;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
};

@ -167,7 +167,7 @@ namespace MWDialogue
return count;
}
void Journal::write (ESM::ESMWriter& writer) const
void Journal::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter)
{
@ -178,6 +178,7 @@ namespace MWDialogue
writer.startRecord (ESM::REC_QUES);
state.save (writer);
writer.endRecord (ESM::REC_QUES);
progress.increaseProgress();
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
{
@ -188,6 +189,7 @@ namespace MWDialogue
writer.startRecord (ESM::REC_JOUR);
entry.save (writer);
writer.endRecord (ESM::REC_JOUR);
progress.increaseProgress();
}
}
@ -199,6 +201,7 @@ namespace MWDialogue
writer.startRecord (ESM::REC_JOUR);
entry.save (writer);
writer.endRecord (ESM::REC_JOUR);
progress.increaseProgress();
}
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
@ -214,6 +217,7 @@ namespace MWDialogue
writer.startRecord (ESM::REC_JOUR);
entry.save (writer);
writer.endRecord (ESM::REC_JOUR);
progress.increaseProgress();
}
}
}

@ -64,7 +64,7 @@ namespace MWDialogue
virtual int countSavedGameRecords() const;
virtual void write (ESM::ESMWriter& writer) const;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
};

@ -25,7 +25,7 @@ namespace MWGui
virtual void setProgressRange (size_t range);
virtual void setProgress (size_t value);
virtual void increaseProgress (size_t increase);
virtual void increaseProgress (size_t increase=1);
virtual void setVisible(bool visible);

@ -595,7 +595,7 @@ namespace MWGui
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
}
void MapWindow::write(ESM::ESMWriter &writer)
void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress)
{
ESM::GlobalMap map;
mGlobalMapRender->write(map);
@ -605,6 +605,7 @@ namespace MWGui
writer.startRecord(ESM::REC_GMAP);
map.save(writer);
writer.endRecord(ESM::REC_GMAP);
progress.increaseProgress();
}
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)

@ -108,7 +108,7 @@ namespace MWGui
/// Clear all savegame-specific data
void clear();
void write (ESM::ESMWriter& writer);
void write (ESM::ESMWriter& writer, Loading::Listener& progress);
void readRecord (ESM::ESMReader& reader, int32_t type);
private:

@ -1407,9 +1407,9 @@ namespace MWGui
mMap->clear();
}
void WindowManager::write(ESM::ESMWriter &writer)
void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress)
{
mMap->write(writer);
mMap->write(writer, progress);
}
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)

@ -291,7 +291,7 @@ namespace MWGui
/// Clear all savegame-specific data
virtual void clear();
virtual void write (ESM::ESMWriter& writer);
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress);
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
private:

@ -97,7 +97,7 @@ namespace MWScript
return mScripts.size();
}
void GlobalScripts::write (ESM::ESMWriter& writer) const
void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
for (std::map<std::string, std::pair<bool, Locals> >::const_iterator iter (mScripts.begin());
iter!=mScripts.end(); ++iter)
@ -113,6 +113,7 @@ namespace MWScript
writer.startRecord (ESM::REC_GSCR);
script.save (writer);
writer.endRecord (ESM::REC_GSCR);
progress.increaseProgress();
}
}

@ -14,6 +14,11 @@ namespace ESM
class ESMReader;
}
namespace Loading
{
class Listener;
}
namespace MWWorld
{
struct ESMStore;
@ -46,7 +51,7 @@ namespace MWScript
int countSavedGameRecords() const;
void write (ESM::ESMWriter& writer) const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);
///< Records for variables that do not exist are dropped silently.

@ -196,26 +196,35 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
writer.setRecordCount (
1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+1 // global map
);
int recordCount = 1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+1; // global map
writer.setRecordCount (recordCount);
writer.save (stream);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
listener.setProgressRange(recordCount);
listener.setLabel("#{sNotifyMessage4}");
Loading::ScopedLoad load(&listener);
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
listener.increaseProgress();
MWBase::Environment::get().getJournal()->write (writer, listener);
MWBase::Environment::get().getDialogueManager()->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().getJournal()->write (writer);
MWBase::Environment::get().getDialogueManager()->write (writer);
MWBase::Environment::get().getWorld()->write (writer);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer);
MWBase::Environment::get().getWindowManager()->write(writer);
// Ensure we have written the number of records that was estimated
assert (writer.getRecordCount() == recordCount+1); // 1 extra for TES3 record
writer.close();
@ -261,6 +270,15 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
// FIXME: +1 is actually not needed, but older savegames had an off-by-one error with the record count
// So we leave this in for now so that these old savegames still work
listener.setProgressRange(reader.getRecordCount()+1);
listener.setLabel("#{sLoadingMessage14}");
Loading::ScopedLoad load(&listener);
while (reader.hasMoreRecs())
{
ESM::NAME n = reader.getRecName();
@ -318,6 +336,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
/// \todo log error
reader.skipRecord();
}
listener.increaseProgress();
}
mCharacterManager.setCurrentCharacter(character);

@ -277,17 +277,23 @@ int MWWorld::Cells::countSavedGameRecords() const
return count;
}
void MWWorld::Cells::write (ESM::ESMWriter& writer) const
void MWWorld::Cells::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
for (std::map<std::pair<int, int>, CellStore>::iterator iter (mExteriors.begin());
iter!=mExteriors.end(); ++iter)
if (iter->second.hasState())
{
writeCell (writer, iter->second);
progress.increaseProgress(); // Assumes that each cell writes one record
}
for (std::map<std::string, CellStore>::iterator iter (mInteriors.begin());
iter!=mInteriors.end(); ++iter)
if (iter->second.hasState())
{
writeCell (writer, iter->second);
progress.increaseProgress(); // Assumes that each cell writes one record
}
}
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type,

@ -15,6 +15,11 @@ namespace ESM
struct Cell;
}
namespace Loading
{
class Listener;
}
namespace MWWorld
{
class ESMStore;
@ -69,7 +74,7 @@ namespace MWWorld
int countSavedGameRecords() const;
void write (ESM::ESMWriter& writer) const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
bool readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap);

@ -153,17 +153,17 @@ void ESMStore::setUp()
+mWeapons.getDynamicSize();
}
void ESMStore::write (ESM::ESMWriter& writer) const
void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
mPotions.write (writer);
mArmors.write (writer);
mBooks.write (writer);
mClasses.write (writer);
mClothes.write (writer);
mEnchants.write (writer);
mSpells.write (writer);
mWeapons.write (writer);
mNpcs.write (writer);
mPotions.write (writer, progress);
mArmors.write (writer, progress);
mBooks.write (writer, progress);
mClasses.write (writer, progress);
mClothes.write (writer, progress);
mEnchants.write (writer, progress);
mSpells.write (writer, progress);
mWeapons.write (writer, progress);
mNpcs.write (writer, progress);
}
bool ESMStore::readRecord (ESM::ESMReader& reader, int32_t type)

@ -212,7 +212,7 @@ namespace MWWorld
int countSavedGameRecords() const;
void write (ESM::ESMWriter& writer) const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);
///< \return Known type?

@ -77,7 +77,7 @@ namespace MWWorld
return mVariables.size();
}
void Globals::write (ESM::ESMWriter& writer) const
void Globals::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
for (Collection::const_iterator iter (mVariables.begin()); iter!=mVariables.end(); ++iter)
{
@ -85,6 +85,7 @@ namespace MWWorld
writer.writeHNString ("NAME", iter->first);
iter->second.write (writer, ESM::Variant::Format_Global);
writer.endRecord (ESM::REC_GLOB);
progress.increaseProgress();
}
}

@ -16,6 +16,11 @@ namespace ESM
class ESMReader;
}
namespace Loading
{
class Listener;
}
namespace MWWorld
{
class ESMStore;
@ -46,7 +51,7 @@ namespace MWWorld
int countSavedGameRecords() const;
void write (ESM::ESMWriter& writer) const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);
///< Records for variables that do not exist are dropped silently.

@ -215,7 +215,7 @@ namespace MWWorld
mTeleported = false;
}
void Player::write (ESM::ESMWriter& writer) const
void Player::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
ESM::Player player;
@ -245,6 +245,8 @@ namespace MWWorld
writer.startRecord (ESM::REC_PLAY);
player.save (writer);
writer.endRecord (ESM::REC_PLAY);
progress.increaseProgress();
}
bool Player::readRecord (ESM::ESMReader& reader, int32_t type)

@ -21,6 +21,11 @@ namespace MWBase
class Ptr;
}
namespace Loading
{
class Listener;
}
namespace MWWorld
{
class CellStore;
@ -95,7 +100,7 @@ namespace MWWorld
void clear();
void write (ESM::ESMWriter& writer) const;
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);

@ -8,6 +8,8 @@
#include <components/esm/esmwriter.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include "recordcmp.hpp"
namespace MWWorld
@ -313,7 +315,7 @@ namespace MWWorld
return erase(item.mId);
}
void write (ESM::ESMWriter& writer) const
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
for (typename Dynamic::const_iterator iter (mDynamic.begin()); iter!=mDynamic.end();
++iter)
@ -322,6 +324,7 @@ namespace MWWorld
writer.writeHNString ("NAME", iter->second.mId);
iter->second.save (writer);
writer.endRecord (T::sRecordId);
progress.increaseProgress();
}
}

@ -686,7 +686,7 @@ bool WeatherManager::isDark() const
return exterior && (mHour < mSunriseTime || mHour > mNightStart - 1);
}
void WeatherManager::write(ESM::ESMWriter& writer)
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
{
ESM::WeatherState state;
state.mHour = mHour;
@ -701,6 +701,7 @@ void WeatherManager::write(ESM::ESMWriter& writer)
writer.startRecord(ESM::REC_WTHR);
state.save(writer);
writer.endRecord(ESM::REC_WTHR);
progress.increaseProgress();
}
bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type)

@ -18,6 +18,11 @@ namespace MWRender
class RenderingManager;
}
namespace Loading
{
class Listener;
}
namespace MWWorld
{
class Fallback;
@ -158,7 +163,7 @@ namespace MWWorld
/// @see World::isDark
bool isDark() const;
void write(ESM::ESMWriter& writer);
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
bool readRecord(ESM::ESMReader& reader, int32_t type);

@ -268,19 +268,20 @@ namespace MWWorld
int World::countSavedGameRecords() const
{
return
mStore.countSavedGameRecords()
mCells.countSavedGameRecords()
+mStore.countSavedGameRecords()
+mGlobalVariables.countSavedGameRecords()
+1 // player record
+mCells.countSavedGameRecords();
+1; // weather record
}
void World::write (ESM::ESMWriter& writer) const
void World::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
{
mStore.write (writer);
mGlobalVariables.write (writer);
mCells.write (writer);
mPlayer->write (writer);
mWeatherManager->write (writer);
mCells.write (writer, progress);
mStore.write (writer, progress);
mGlobalVariables.write (writer, progress);
mPlayer->write (writer, progress);
mWeatherManager->write (writer, progress);
}
void World::readRecord (ESM::ESMReader& reader, int32_t type,

@ -194,7 +194,7 @@ namespace MWWorld
virtual int countSavedGameRecords() const;
virtual void write (ESM::ESMWriter& writer) const;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap);

@ -31,6 +31,7 @@ public:
*************************************************************************/
int getVer() const { return mHeader.mData.version; }
int getRecordCount() const { return mHeader.mData.records; }
float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; }
const std::string getAuthor() const { return mHeader.mData.author.toString(); }
const std::string getDesc() const { return mHeader.mData.desc.toString(); }

@ -29,7 +29,12 @@ class ESMWriter
void setEncoder(ToUTF8::Utf8Encoder *encoding);
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
// Set the record count for writing it in the file header
void setRecordCount (int count);
// Counts how many records we have actually written.
// It is a good idea to compare this with the value you wrote into the header (setRecordCount)
// It should be the record count you set + 1 (1 additional record for the TES3 header)
int getRecordCount() { return mRecordCount; }
void setFormat (int format);
void clearMaster();

@ -28,7 +28,7 @@ namespace ESM
int type; // 0=esp, 1=esm, 32=ess (unused)
NAME32 author; // Author's name
NAME256 desc; // File description
int records; // Number of records? Not used.
int records; // Number of records
};
// Defines another files (esm or esp) that this file depends upon.

@ -17,7 +17,7 @@ namespace Loading
virtual void setProgressRange (size_t range) = 0;
virtual void setProgress (size_t value) = 0;
virtual void increaseProgress (size_t increase) = 0;
virtual void increaseProgress (size_t increase = 1) = 0;
/// Indicate the scene is now ready to be shown
virtual void removeWallpaper() = 0;

Loading…
Cancel
Save