diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index b41eea8f8..2c066ff6c 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -340,6 +341,15 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import { ImportResults results; + // Map existing textures to ids + std::map reverseLookupMap; + for (int i = 0; i < idCollection()->getSize(); ++i) + { + auto& record = static_cast&>(idCollection()->getRecord(i)); + if (record.isModified()) + reverseLookupMap.emplace(record.get().mTexture, idCollection()->getId(i)); + } + for (const std::string& id : ids) { int plugin, index; @@ -354,8 +364,16 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import continue; } - // Try a direct mapping to the current plugin first. Otherwise iterate until one is found. - // Iteration is deterministic to avoid duplicates. + // Look for a pre-existing record + auto& record = static_cast&>(idCollection()->getRecord(oldRow)); + auto searchIt = reverseLookupMap.find(record.get().mTexture); + if (searchIt != reverseLookupMap.end()) + { + results.recordMapping.push_back(std::make_pair(id, searchIt->second)); + continue; + } + + // Iterate until an unused index or found, or the index has completely wrapped around. int startIndex = index; do { std::string newId = LandTexture::createUniqueRecordId(0, index); @@ -370,21 +388,8 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import break; } - // Id is taken, check if same handle and texture. Note that mId is the handle. - const LandTexture& oldLtex = dynamic_cast&>(idCollection()->getRecord(oldRow)).get(); - const LandTexture& newLtex = dynamic_cast&>(idCollection()->getRecord(newRow)).get(); - if (oldLtex.mId == newLtex.mId && oldLtex.mTexture == newLtex.mTexture) - { - // It's a match - results.recordMapping.push_back(std::make_pair(id, newId)); - break; - } - - // Determine next index. Spread out the indices to reduce conflicts. - size_t MaxIndex = std::numeric_limits::max() - 1; - size_t Prime = (1 << 13) - 1; // A mersenne prime - - index = (index + Prime) % MaxIndex; + const size_t MaxIndex = std::numeric_limits::max() - 1; + index = (index + 1) % MaxIndex; } while (index != startIndex); }