diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index f78c57ecd6..dbfa4651b7 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -100,84 +100,72 @@ int CSMDoc::WriteDialogueCollectionStage::setup() void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages) { + ESM::ESMWriter& writer = mState.getWriter(); const CSMWorld::Record& topic = mTopics.getRecord (stage); - CSMWorld::RecordBase::State state = topic.mState; - - if (state==CSMWorld::RecordBase::State_Deleted) + if (topic.mState == CSMWorld::RecordBase::State_Deleted) { // if the topic is deleted, we do not need to bother with INFO records. + ESM::Dialogue dialogue = topic.get(); + dialogue.mIsDeleted = true; - /// \todo wrote record with delete flag - + writer.startRecord(dialogue.sRecordId); + dialogue.save(writer); + writer.endRecord(dialogue.sRecordId); return; } // Test, if we need to save anything associated info records. bool infoModified = false; - CSMWorld::InfoCollection::Range range = mInfos.getTopicRange (topic.get().mId); for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter) { - CSMWorld::RecordBase::State state = iter->mState; - - if (state==CSMWorld::RecordBase::State_Modified || - state==CSMWorld::RecordBase::State_ModifiedOnly || - state==CSMWorld::RecordBase::State_Deleted) + if (topic.isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted) { infoModified = true; break; } } - if (state==CSMWorld::RecordBase::State_Modified || - state==CSMWorld::RecordBase::State_ModifiedOnly || - infoModified) + if (topic.isModified() || infoModified) { - mState.getWriter().startRecord (topic.mModified.sRecordId); - mState.getWriter().writeHNCString ("NAME", topic.mModified.mId); - topic.mModified.save (mState.getWriter()); - mState.getWriter().endRecord (topic.mModified.sRecordId); + ESM::Dialogue dialogue = topic.get(); + + writer.startRecord (dialogue.sRecordId); + dialogue.save (writer); + writer.endRecord (dialogue.sRecordId); // write modified selected info records - for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; - ++iter) + for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter) { - CSMWorld::RecordBase::State state = iter->mState; - - if (state==CSMWorld::RecordBase::State_Deleted) - { - /// \todo wrote record with delete flag - } - else if (state==CSMWorld::RecordBase::State_Modified || - state==CSMWorld::RecordBase::State_ModifiedOnly) + if (iter->isModified() || iter->mState == CSMWorld::RecordBase::State_Deleted) { ESM::DialInfo info = iter->get(); info.mId = info.mId.substr (info.mId.find_last_of ('#')+1); + info.mIsDeleted = (iter->mState == CSMWorld::RecordBase::State_Deleted); + info.mPrev = ""; if (iter!=range.first) { CSMWorld::InfoCollection::RecordConstIterator prev = iter; --prev; - info.mPrev = - prev->mModified.mId.substr (prev->mModified.mId.find_last_of ('#')+1); + info.mPrev = prev->get().mId.substr (prev->get().mId.find_last_of ('#')+1); } CSMWorld::InfoCollection::RecordConstIterator next = iter; ++next; + info.mNext = ""; if (next!=range.second) { - info.mNext = - next->mModified.mId.substr (next->mModified.mId.find_last_of ('#')+1); + info.mNext = next->get().mId.substr (next->get().mId.find_last_of ('#')+1); } - mState.getWriter().startRecord (info.sRecordId); - mState.getWriter().writeHNCString ("INAM", info.mId); - info.save (mState.getWriter()); - mState.getWriter().endRecord (info.sRecordId); + writer.startRecord (info.sRecordId); + info.save (writer); + writer.endRecord (info.sRecordId); } } } @@ -269,36 +257,35 @@ int CSMDoc::WriteCellCollectionStage::setup() void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) { - const CSMWorld::Record& cell = - mDocument.getData().getCells().getRecord (stage); + ESM::ESMWriter& writer = mState.getWriter(); + const CSMWorld::Record& cell = mDocument.getData().getCells().getRecord (stage); std::map >::const_iterator references = mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId)); - if (cell.mState==CSMWorld::RecordBase::State_Modified || - cell.mState==CSMWorld::RecordBase::State_ModifiedOnly || + if (cell.isModified() || + cell.mState == CSMWorld::RecordBase::State_Deleted || references!=mState.getSubRecords().end()) { - bool interior = cell.get().mId.substr (0, 1)!="#"; + CSMWorld::Cell cellRecord = cell.get(); + bool interior = cellRecord.mId.substr (0, 1)!="#"; // write cell data - mState.getWriter().startRecord (cell.mModified.sRecordId); - - mState.getWriter().writeHNOCString ("NAME", cell.get().mName); - - ESM::Cell cell2 = cell.get(); + writer.startRecord (cellRecord.sRecordId); if (interior) - cell2.mData.mFlags |= ESM::Cell::Interior; + cellRecord.mData.mFlags |= ESM::Cell::Interior; else { - cell2.mData.mFlags &= ~ESM::Cell::Interior; + cellRecord.mData.mFlags &= ~ESM::Cell::Interior; - std::istringstream stream (cell.get().mId.c_str()); + std::istringstream stream (cellRecord.mId.c_str()); char ignore; - stream >> ignore >> cell2.mData.mX >> cell2.mData.mY; + stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY; } - cell2.save (mState.getWriter()); + + cellRecord.mIsDeleted = (cell.mState == CSMWorld::RecordBase::State_Deleted); + cellRecord.save (writer); // write references if (references!=mState.getSubRecords().end()) @@ -309,24 +296,25 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) const CSMWorld::Record& ref = mDocument.getData().getReferences().getRecord (*iter); - if (ref.mState==CSMWorld::RecordBase::State_Modified || - ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) + if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted) { + CSMWorld::CellRef refRecord = ref.get(); + // recalculate the ref's cell location std::ostringstream stream; if (!interior) { - std::pair index = ref.get().getCellIndex(); + std::pair index = refRecord.getCellIndex(); stream << "#" << index.first << " " << index.second; } // An empty mOriginalCell is meant to indicate that it is the same as // the current cell. It is possible that a moved ref is moved again. - if ((ref.get().mOriginalCell.empty() ? ref.get().mCell : ref.get().mOriginalCell) + if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != stream.str() && !interior) { ESM::MovedCellRef moved; - moved.mRefNum = ref.get().mRefNum; + moved.mRefNum = refRecord.mRefNum; // Need to fill mTarget with the ref's new position. std::istringstream istream (stream.str().c_str()); @@ -334,24 +322,17 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) char ignore; istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; - ref.get().mRefNum.save (mState.getWriter(), false, "MVRF"); - mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8); + refRecord.mRefNum.save (writer, false, "MVRF"); + writer.writeHNT ("CNDT", moved.mTarget, 8); } - ref.get().save (mState.getWriter()); - } - else if (ref.mState==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + refRecord.mIsDeleted = (ref.mState == CSMWorld::RecordBase::State_Deleted); + refRecord.save (writer); } } } - mState.getWriter().endRecord (cell.mModified.sRecordId); - } - else if (cell.mState==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + writer.endRecord (cellRecord.sRecordId); } } @@ -368,11 +349,11 @@ int CSMDoc::WritePathgridCollectionStage::setup() void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& messages) { - const CSMWorld::Record& pathgrid = + ESM::ESMWriter& writer = mState.getWriter(); + const CSMWorld::Record& pathgrid = mDocument.getData().getPathgrids().getRecord (stage); - if (pathgrid.mState==CSMWorld::RecordBase::State_Modified || - pathgrid.mState==CSMWorld::RecordBase::State_ModifiedOnly) + if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted) { CSMWorld::Pathgrid record = pathgrid.get(); @@ -385,15 +366,10 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message else record.mCell = record.mId; - mState.getWriter().startRecord (record.sRecordId); - - record.save (mState.getWriter()); - - mState.getWriter().endRecord (record.sRecordId); - } - else if (pathgrid.mState==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + record.mIsDeleted = (pathgrid.mState == CSMWorld::RecordBase::State_Deleted); + writer.startRecord (record.sRecordId); + record.save (writer); + writer.endRecord (record.sRecordId); } } @@ -410,25 +386,18 @@ int CSMDoc::WriteLandCollectionStage::setup() void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages) { - const CSMWorld::Record& land = + ESM::ESMWriter& writer = mState.getWriter(); + const CSMWorld::Record& land = mDocument.getData().getLand().getRecord (stage); - if (land.mState==CSMWorld::RecordBase::State_Modified || - land.mState==CSMWorld::RecordBase::State_ModifiedOnly) + if (land.isModified() || land.mState == CSMWorld::RecordBase::State_Deleted) { CSMWorld::Land record = land.get(); - mState.getWriter().startRecord (record.mLand->sRecordId); - - record.mLand->save (mState.getWriter()); - if(record.mLand->mLandData) - record.mLand->mLandData->save (mState.getWriter()); - - mState.getWriter().endRecord (record.mLand->sRecordId); - } - else if (land.mState==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + record.mLand->mIsDeleted = (land.mState == CSMWorld::RecordBase::State_Deleted); + writer.startRecord (record.mLand->sRecordId); + record.mLand->save (writer); + writer.endRecord (record.mLand->sRecordId); } } @@ -445,23 +414,18 @@ int CSMDoc::WriteLandTextureCollectionStage::setup() void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages) { - const CSMWorld::Record& landTexture = + ESM::ESMWriter& writer = mState.getWriter(); + const CSMWorld::Record& landTexture = mDocument.getData().getLandTextures().getRecord (stage); - if (landTexture.mState==CSMWorld::RecordBase::State_Modified || - landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly) + if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted) { CSMWorld::LandTexture record = landTexture.get(); + record.mIsDeleted = (landTexture.mState == CSMWorld::RecordBase::State_Deleted); - mState.getWriter().startRecord (record.sRecordId); - - record.save (mState.getWriter()); - - mState.getWriter().endRecord (record.sRecordId); - } - else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + writer.startRecord (record.sRecordId); + record.save (writer); + writer.endRecord (record.sRecordId); } } diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 188f22f961..9dbb5bee33 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -100,26 +100,18 @@ namespace CSMDoc if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope) return; + ESM::ESMWriter& writer = mState.getWriter(); CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState; + CollectionT::ESXRecord record = mCollection.getRecord (stage).get(); - if (state==CSMWorld::RecordBase::State_Modified || - state==CSMWorld::RecordBase::State_ModifiedOnly) + if (state == CSMWorld::RecordBase::State_Modified || + state == CSMWorld::RecordBase::State_ModifiedOnly || + state == CSMWorld::RecordBase::State_Deleted) { - // FIXME: A quick Workaround to support records which should not write - // NAME, including SKIL, MGEF and SCPT. If there are many more - // idcollection records that doesn't use NAME then a more generic - // solution may be required. - uint32_t name = mCollection.getRecord (stage).mModified.sRecordId; - mState.getWriter().startRecord (name); - - if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT) - mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); - mCollection.getRecord (stage).mModified.save (mState.getWriter()); - mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId); - } - else if (state==CSMWorld::RecordBase::State_Deleted) - { - /// \todo write record with delete flag + CSMWorld::setRecordDeleted (record, state == CSMWorld::RecordBase::State_Deleted); + writer.startRecord (record.sRecordId); + record.save (writer); + writer.endRecord (record.sRecordId); } } diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index b0571bbed1..16f5ce51f4 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -43,6 +43,12 @@ namespace CSMWorld template > class Collection : public CollectionBase { + public: + + typedef ESXRecordT ESXRecord; + + private: + std::vector > mRecords; std::map mIndex; std::vector *> mColumns; diff --git a/apps/opencs/model/world/record.cpp b/apps/opencs/model/world/record.cpp index 87f5090fe4..7563c4cfd9 100644 --- a/apps/opencs/model/world/record.cpp +++ b/apps/opencs/model/world/record.cpp @@ -43,3 +43,27 @@ bool CSMWorld::isRecordDeleted(const ESM::Skill &skill) { return false; } + +template<> +void CSMWorld::setRecordDeleted(CSMWorld::Land &land, bool isDeleted) +{ + land.mLand->mIsDeleted = isDeleted; +} + +template<> +void CSMWorld::setRecordDeleted(ESM::GameSetting &setting, bool isDeleted) +{ + // GameSetting doesn't have a Deleted flag +} + +template<> +void CSMWorld::setRecordDeleted(ESM::MagicEffect &effect, bool isDeleted) +{ + // MagicEffect doesn't have a Deleted flag +} + +template<> +void CSMWorld::setRecordDeleted(ESM::Skill &skill, bool isDeleted) +{ + // Skill doesn't have a Deleted flag +} diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index c43a8b6ca2..8e39cd705e 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -177,6 +177,22 @@ namespace CSMWorld bool isRecordDeleted(const ESM::MagicEffect &effect); template<> bool isRecordDeleted(const ESM::Skill &skill); + + // ... and also a separate method for setting the deleted flag of a record + template + void setRecordDeleted(ESXRecordT &record, bool isDeleted = false) + { + record.mIsDeleted = isDeleted; + } + + template<> + void setRecordDeleted(Land &land, bool isDeleted); + template<> + void setRecordDeleted(ESM::GameSetting &setting, bool isDeleted); + template<> + void setRecordDeleted(ESM::MagicEffect &effect, bool isDeleted); + template<> + void setRecordDeleted(ESM::Skill &skill, bool isDeleted); } #endif