diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 4f184f81c4..86075ce8d6 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -125,6 +125,7 @@ CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage(Document& doc int CSMDoc::WriteDialogueCollectionStage::setup() { + mInfosByTopic = mInfos.getInfosByTopic(); return mTopics.getSize(); } @@ -145,14 +146,17 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages // Test, if we need to save anything associated info records. bool infoModified = false; - const auto infos = mInfos.getTopicInfos(topic.get().mId); + const auto topicInfos = mInfosByTopic.find(topic.get().mId); - for (const auto& record : infos) + if (topicInfos != mInfosByTopic.end()) { - if (record->isModified() || record->mState == CSMWorld::RecordBase::State_Deleted) + for (const auto& record : topicInfos->second) { - infoModified = true; - break; + if (record->isModified() || record->mState == CSMWorld::RecordBase::State_Deleted) + { + infoModified = true; + break; + } } } @@ -173,31 +177,36 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages } // write modified selected info records - for (auto iter = infos.begin(); iter != infos.end(); ++iter) + if (topicInfos != mInfosByTopic.end()) { - const CSMWorld::Record& record = **iter; + const std::vector*>& infos = topicInfos->second; - if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted) + for (auto iter = infos.begin(); iter != infos.end(); ++iter) { - ESM::DialInfo info = record.get(); - info.mId = record.get().mOriginalId; + const CSMWorld::Record& record = **iter; - info.mPrev = ESM::RefId::sEmpty; - if (iter != infos.begin()) + if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted) { - const auto prev = std::prev(iter); - info.mPrev = (*prev)->get().mOriginalId; + ESM::DialInfo info = record.get(); + info.mId = record.get().mOriginalId; + + info.mPrev = ESM::RefId::sEmpty; + if (iter != infos.begin()) + { + const auto prev = std::prev(iter); + info.mPrev = (*prev)->get().mOriginalId; + } + + const auto next = std::next(iter); + + info.mNext = ESM::RefId::sEmpty; + if (next != infos.end()) + info.mNext = (*next)->get().mOriginalId; + + writer.startRecord(info.sRecordId); + info.save(writer, record.mState == CSMWorld::RecordBase::State_Deleted); + writer.endRecord(info.sRecordId); } - - const auto next = std::next(iter); - - info.mNext = ESM::RefId::sEmpty; - if (next != infos.end()) - info.mNext = (*next)->get().mOriginalId; - - writer.startRecord(info.sRecordId); - info.save(writer, record.mState == CSMWorld::RecordBase::State_Deleted); - writer.endRecord(info.sRecordId); } } } diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 6fb938768f..dd76c5585f 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -4,8 +4,10 @@ #include "stage.hpp" #include +#include #include "../world/idcollection.hpp" +#include "../world/infocollection.hpp" #include "../world/record.hpp" #include "../world/scope.hpp" @@ -118,6 +120,7 @@ namespace CSMDoc SavingState& mState; const CSMWorld::IdCollection& mTopics; CSMWorld::InfoCollection& mInfos; + CSMWorld::InfosRecordPtrByTopic mInfosByTopic; public: WriteDialogueCollectionStage(Document& document, SavingState& state, bool journal); diff --git a/apps/opencs/model/tools/journalcheck.cpp b/apps/opencs/model/tools/journalcheck.cpp index 5a477ed5a9..1f34073a4a 100644 --- a/apps/opencs/model/tools/journalcheck.cpp +++ b/apps/opencs/model/tools/journalcheck.cpp @@ -32,7 +32,7 @@ CSMTools::JournalCheckStage::JournalCheckStage( int CSMTools::JournalCheckStage::setup() { mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue(); - + mInfosByTopic = mJournalInfos.getInfosByTopic(); return mJournals.getSize(); } @@ -50,38 +50,39 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages) int totalInfoCount = 0; std::set questIndices; - for (const CSMWorld::Record* record : mJournalInfos.getTopicInfos(journal.mId)) + if (const auto infos = mInfosByTopic.find(journal.mId); infos != mInfosByTopic.end()) { - if (record->isDeleted()) - continue; - - const CSMWorld::Info& journalInfo = record->get(); - - totalInfoCount += 1; - - if (journalInfo.mQuestStatus == ESM::DialInfo::QS_Name) + for (const CSMWorld::Record* record : infos->second) { - statusNamedCount += 1; - } + if (record->isDeleted()) + continue; - // Skip "Base" records (setting!) - if (mIgnoreBaseRecords && record->mState == CSMWorld::RecordBase::State_BaseOnly) - continue; + const CSMWorld::Info& journalInfo = record->get(); - if (journalInfo.mResponse.empty()) - { - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId); - messages.add(id, "Missing journal entry text", "", CSMDoc::Message::Severity_Warning); - } + totalInfoCount += 1; - std::pair::iterator, bool> result = questIndices.insert(journalInfo.mData.mJournalIndex); + if (journalInfo.mQuestStatus == ESM::DialInfo::QS_Name) + { + statusNamedCount += 1; + } - // Duplicate index - if (!result.second) - { - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId); - messages.add(id, "Duplicated quest index " + std::to_string(journalInfo.mData.mJournalIndex), "", - CSMDoc::Message::Severity_Error); + // Skip "Base" records (setting!) + if (mIgnoreBaseRecords && record->mState == CSMWorld::RecordBase::State_BaseOnly) + continue; + + if (journalInfo.mResponse.empty()) + { + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId); + messages.add(id, "Missing journal entry text", "", CSMDoc::Message::Severity_Warning); + } + + // Duplicate index + if (!questIndices.insert(journalInfo.mData.mJournalIndex).second) + { + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId); + messages.add(id, "Duplicated quest index " + std::to_string(journalInfo.mData.mJournalIndex), "", + CSMDoc::Message::Severity_Error); + } } } diff --git a/apps/opencs/model/tools/journalcheck.hpp b/apps/opencs/model/tools/journalcheck.hpp index fabd3d0c8e..a3bee1492a 100644 --- a/apps/opencs/model/tools/journalcheck.hpp +++ b/apps/opencs/model/tools/journalcheck.hpp @@ -2,6 +2,7 @@ #define CSM_TOOLS_JOURNALCHECK_H #include "../world/idcollection.hpp" +#include "../world/infocollection.hpp" #include "../doc/stage.hpp" @@ -39,6 +40,7 @@ namespace CSMTools const CSMWorld::IdCollection& mJournals; const CSMWorld::InfoCollection& mJournalInfos; bool mIgnoreBaseRecords; + CSMWorld::InfosRecordPtrByTopic mInfosByTopic; }; } diff --git a/apps/opencs/model/world/infocollection.cpp b/apps/opencs/model/world/infocollection.cpp index b06f7d05f8..34949877b4 100644 --- a/apps/opencs/model/world/infocollection.cpp +++ b/apps/opencs/model/world/infocollection.cpp @@ -82,11 +82,10 @@ void CSMWorld::InfoCollection::load( } } -std::vector*> CSMWorld::InfoCollection::getTopicInfos(const ESM::RefId& topic) const +CSMWorld::InfosRecordPtrByTopic CSMWorld::InfoCollection::getInfosByTopic() const { - std::vector*> result; + InfosRecordPtrByTopic result; for (const std::unique_ptr>& record : getRecords()) - if (record->mBase.mTopicId == topic) - result.push_back(record.get()); + result[record->mBase.mTopicId].push_back(record.get()); return result; } diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index c1b1edcabd..2ae69fd0ac 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -7,7 +7,6 @@ #include "collection.hpp" #include "info.hpp" -#include "record.hpp" namespace ESM { @@ -18,6 +17,7 @@ namespace ESM namespace CSMWorld { using InfosByTopic = std::unordered_map>; + using InfosRecordPtrByTopic = std::unordered_map*>>; class InfoCollection : public Collection> { @@ -27,7 +27,7 @@ namespace CSMWorld public: void load(ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue, InfosByTopic& infosByTopic); - std::vector*> getTopicInfos(const ESM::RefId& topic) const; + InfosRecordPtrByTopic getInfosByTopic() const; }; }