diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 12fa6e811f..492807eb93 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -291,8 +291,7 @@ int CSMDoc::WriteCellCollectionStage::setup() return mDocument.getData().getCells().getSize(); } -void CSMDoc::WriteCellCollectionStage::writeReferences( - const std::deque& references, bool interior, unsigned int& newRefNum) +void CSMDoc::WriteCellCollectionStage::writeReferences(const std::deque& references, bool interior) { ESM::ESMWriter& writer = mState.getWriter(); @@ -304,6 +303,8 @@ void CSMDoc::WriteCellCollectionStage::writeReferences( { CSMWorld::CellRef refRecord = ref.get(); + const bool isLocal = refRecord.mRefNum.mContentFile == -1; + // -1 is the current file, saved indices are 1-based refRecord.mRefNum.mContentFile++; @@ -316,12 +317,7 @@ void CSMDoc::WriteCellCollectionStage::writeReferences( } ESM::RefId streamId = ESM::RefId::stringRefId(stream.str()); - if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 - || (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly && refRecord.mCell != streamId)) - { - refRecord.mRefNum.mIndex = newRefNum++; - } - else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId + if (!isLocal && (refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId && !interior) { // An empty mOriginalCell is meant to indicate that it is the same as @@ -362,9 +358,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages) CSMWorld::Cell cellRecord = cell.get(); const bool interior = !cellRecord.mId.startsWith("#"); - // count new references and adjust RefNumCount accordingsly - unsigned int newRefNum = cellRecord.mRefNumCounter; - if (references != nullptr) { for (std::deque::const_iterator iter(references->begin()); iter != references->end(); ++iter) @@ -390,9 +383,6 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages) ESM::RefId::stringRefId(CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId("")) != refRecord.mCell)) ++cellRecord.mRefNumCounter; - - if (refRecord.mRefNum.mIndex >= newRefNum) - newRefNum = refRecord.mRefNum.mIndex + 1; } } @@ -415,9 +405,9 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages) // write references if (references != nullptr) { - writeReferences(persistentRefs, interior, newRefNum); + writeReferences(persistentRefs, interior); cellRecord.saveTempMarker(writer, static_cast(references->size()) - persistentRefs.size()); - writeReferences(tempRefs, interior, newRefNum); + writeReferences(tempRefs, interior); } writer.endRecord(cellRecord.sRecordId); diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 5423b8f504..1f86af10a2 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -167,7 +167,7 @@ namespace CSMDoc Document& mDocument; SavingState& mState; - void writeReferences(const std::deque& references, bool interior, unsigned int& newRefNum); + void writeReferences(const std::deque& references, bool interior); public: WriteCellCollectionStage(Document& document, SavingState& state); diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index fa42ee0f09..18fb73330c 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -273,15 +273,6 @@ namespace CSMWorld copy->mState = RecordBase::State_ModifiedOnly; setRecordId(destination, copy->get()); - if constexpr (std::is_same_v) - { - if (type == UniversalId::Type_Reference) - { - CSMWorld::CellRef* ptr = (CSMWorld::CellRef*)©->mModified; - ptr->mRefNum.mIndex = 0; - } - } - if constexpr (std::is_same_v) { copy->mModified.mStringId = copy->mModified.mId.getRefIdString(); diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 124e697de8..b2b6cec245 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -175,6 +175,9 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b ref.mIdNum = mNextId; // FIXME: fragile ref.mId = ESM::RefId::stringRefId(getNewId()); + if (!base && ref.mRefNum.mIndex > mHighestUsedRefNum) + mHighestUsedRefNum = ref.mRefNum.mIndex; + cache.emplace(ref.mRefNum, ref.mIdNum); auto record = std::make_unique>(); @@ -222,6 +225,11 @@ std::string CSMWorld::RefCollection::getNewId() return "ref#" + std::to_string(mNextId++); } +uint32_t CSMWorld::RefCollection::getNextRefNum() +{ + return ++mHighestUsedRefNum; +} + unsigned int CSMWorld::RefCollection::extractIdNum(std::string_view id) const { std::string::size_type separator = id.find_last_of('#'); @@ -283,6 +291,7 @@ void CSMWorld::RefCollection::appendBlankRecord(const ESM::RefId& id, UniversalI record->get().mId = id; record->get().mIdNum = extractIdNum(id.getRefIdString()); + record->get().mRefNum.mIndex = getNextRefNum(); Collection::appendRecord(std::move(record)); } @@ -298,15 +307,13 @@ void CSMWorld::RefCollection::cloneRecord( copy->get().mId = destination; copy->get().mIdNum = extractIdNum(destination.getRefIdString()); + copy->get().mRefNum.mIndex = getNextRefNum(); if (copy->get().mRefNum.hasContentFile()) { mRefIndex.insert(std::make_pair(static_cast*>(copy.get())->get().mIdNum, index)); copy->get().mRefNum.mContentFile = -1; - copy->get().mRefNum.mIndex = index; } - else - copy->get().mRefNum.mIndex = copy->get().mIdNum; insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord() } diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index d3d200e6c2..f70167f922 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -1,6 +1,7 @@ #ifndef CSM_WOLRD_REFCOLLECTION_H #define CSM_WOLRD_REFCOLLECTION_H +#include #include #include #include @@ -40,9 +41,12 @@ namespace CSMWorld std::map mRefIndex; // CellRef index keyed by CSMWorld::CellRef::mIdNum int mNextId; + uint32_t mHighestUsedRefNum = 0; unsigned int extractIdNum(std::string_view id) const; + uint32_t getNextRefNum(); + int getIntIndex(unsigned int id) const; int searchId(unsigned int id) const; diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index e100a69a7c..b8bbc89c7b 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -1277,9 +1277,8 @@ void CSVRender::InstanceMode::cloneSelectedInstances() if (CSVRender::ObjectTag* objectTag = dynamic_cast(tag.get())) { macro.push(new CSMWorld::CloneCommand(referencesTable, objectTag->mObject->getReferenceId(), - "ref#" + std::to_string(referencesTable.rowCount()), CSMWorld::UniversalId::Type_Reference)); + document.getData().getReferences().getNewId(), CSMWorld::UniversalId::Type_Reference)); } - // getWorldspaceWidget().clearSelection(Mask_Reference); } void CSVRender::InstanceMode::dropInstance(CSVRender::Object* object, float dropHeight)