mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 06:59:55 +00:00
Merge branch 'ltexerasure' into 'master'
Fix LTEX overriding and allow deletion See merge request OpenMW/openmw!4152
This commit is contained in:
commit
a80f5c109c
11 changed files with 40 additions and 83 deletions
|
@ -42,14 +42,14 @@ namespace CSVRender
|
||||||
land, ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX);
|
land, ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::LandTexture* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
const std::string* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
||||||
{
|
{
|
||||||
const int row = mData.getLandTextures().searchId(
|
const int row = mData.getLandTextures().searchId(
|
||||||
ESM::RefId::stringRefId(CSMWorld::LandTexture::createUniqueRecordId(plugin, index)));
|
ESM::RefId::stringRefId(CSMWorld::LandTexture::createUniqueRecordId(plugin, index)));
|
||||||
if (row == -1)
|
if (row == -1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return &mData.getLandTextures().getRecord(row).get();
|
return &mData.getLandTextures().getRecord(row).get().mTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainStorage::setAlteredHeight(int inCellX, int inCellY, float height)
|
void TerrainStorage::setAlteredHeight(int inCellX, int inCellY, float height)
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace CSVRender
|
||||||
std::array<float, ESM::Land::LAND_SIZE * ESM::Land::LAND_SIZE> mAlteredHeight;
|
std::array<float, ESM::Land::LAND_SIZE * ESM::Land::LAND_SIZE> mAlteredHeight;
|
||||||
|
|
||||||
osg::ref_ptr<const ESMTerrain::LandObject> getLand(ESM::ExteriorCellLocation cellLocation) override;
|
osg::ref_ptr<const ESMTerrain::LandObject> getLand(ESM::ExteriorCellLocation cellLocation) override;
|
||||||
const ESM::LandTexture* getLandTexture(std::uint16_t index, int plugin) override;
|
const std::string* getLandTexture(std::uint16_t index, int plugin) override;
|
||||||
|
|
||||||
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override;
|
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override;
|
||||||
|
|
||||||
|
|
|
@ -105,9 +105,8 @@ namespace MWRender
|
||||||
return mLandManager->getLand(cellLocation);
|
return mLandManager->getLand(cellLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::LandTexture* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
const std::string* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
||||||
{
|
{
|
||||||
assert(plugin >= 0); // Saves don't contain textures
|
|
||||||
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
||||||
return esmStore.get<ESM::LandTexture>().search(index, plugin);
|
return esmStore.get<ESM::LandTexture>().search(index, plugin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace MWRender
|
||||||
~TerrainStorage();
|
~TerrainStorage();
|
||||||
|
|
||||||
osg::ref_ptr<const ESMTerrain::LandObject> getLand(ESM::ExteriorCellLocation cellLocation) override;
|
osg::ref_ptr<const ESMTerrain::LandObject> getLand(ESM::ExteriorCellLocation cellLocation) override;
|
||||||
const ESM::LandTexture* getLandTexture(std::uint16_t index, int plugin) override;
|
const std::string* getLandTexture(std::uint16_t index, int plugin) override;
|
||||||
|
|
||||||
bool hasData(ESM::ExteriorCellLocation cellLocation) override;
|
bool hasData(ESM::ExteriorCellLocation cellLocation) override;
|
||||||
|
|
||||||
|
|
|
@ -391,11 +391,6 @@ namespace MWWorld
|
||||||
if (listener != nullptr)
|
if (listener != nullptr)
|
||||||
listener->setProgressRange(::EsmLoader::fileProgress);
|
listener->setProgressRange(::EsmLoader::fileProgress);
|
||||||
|
|
||||||
// Land texture loading needs to use a separate internal store for each plugin.
|
|
||||||
// We set the number of plugins here so we can properly verify if valid plugin
|
|
||||||
// indices are being passed to the LandTexture Store retrieval methods.
|
|
||||||
getWritable<ESM::LandTexture>().resize(esm.getIndex() + 1);
|
|
||||||
|
|
||||||
// Loop through all records
|
// Loop through all records
|
||||||
while (esm.hasMoreRecs())
|
while (esm.hasMoreRecs())
|
||||||
{
|
{
|
||||||
|
|
|
@ -379,83 +379,51 @@ namespace MWWorld
|
||||||
|
|
||||||
// LandTexture
|
// LandTexture
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
Store<ESM::LandTexture>::Store() {}
|
Store<ESM::LandTexture>::Store() = default;
|
||||||
const ESM::LandTexture* Store<ESM::LandTexture>::search(size_t index, size_t plugin) const
|
|
||||||
{
|
|
||||||
assert(plugin < mStatic.size());
|
|
||||||
const LandTextureList& ltexl = mStatic[plugin];
|
|
||||||
|
|
||||||
if (index >= ltexl.size())
|
const std::string* Store<ESM::LandTexture>::search(std::uint32_t index, int plugin) const
|
||||||
|
{
|
||||||
|
auto mapping = mMappings.find(PluginIndex{ plugin, index });
|
||||||
|
if (mapping == mMappings.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return <exl[index];
|
auto texture = mStatic.find(mapping->second);
|
||||||
}
|
if (texture == mStatic.end())
|
||||||
const ESM::LandTexture* Store<ESM::LandTexture>::find(size_t index, size_t plugin) const
|
return nullptr;
|
||||||
{
|
return &texture->second;
|
||||||
const ESM::LandTexture* ptr = search(index, plugin);
|
|
||||||
if (ptr == nullptr)
|
|
||||||
{
|
|
||||||
const std::string msg = "Land texture with index " + std::to_string(index) + " not found";
|
|
||||||
throw std::runtime_error(msg);
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Store<ESM::LandTexture>::resize(std::size_t num)
|
|
||||||
{
|
|
||||||
mStatic.resize(num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Store<ESM::LandTexture>::getSize() const
|
size_t Store<ESM::LandTexture>::getSize() const
|
||||||
{
|
{
|
||||||
return mStatic.size();
|
return mStatic.size();
|
||||||
}
|
}
|
||||||
size_t Store<ESM::LandTexture>::getSize(size_t plugin) const
|
|
||||||
{
|
|
||||||
assert(plugin < mStatic.size());
|
|
||||||
return mStatic[plugin].size();
|
|
||||||
}
|
|
||||||
RecordId Store<ESM::LandTexture>::load(ESM::ESMReader& esm)
|
RecordId Store<ESM::LandTexture>::load(ESM::ESMReader& esm)
|
||||||
{
|
{
|
||||||
|
const int plugin = esm.getIndex();
|
||||||
|
|
||||||
ESM::LandTexture lt;
|
ESM::LandTexture lt;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
|
||||||
lt.load(esm, isDeleted);
|
lt.load(esm, isDeleted);
|
||||||
|
|
||||||
// Replace texture for records with given ID and index from all plugins.
|
if (!isDeleted)
|
||||||
for (unsigned int i = 0; i < mStatic.size(); i++)
|
|
||||||
{
|
{
|
||||||
ESM::LandTexture* tex = const_cast<ESM::LandTexture*>(search(lt.mIndex, i));
|
mStatic[lt.mId] = std::move(lt.mTexture);
|
||||||
if (tex)
|
mMappings.emplace(PluginIndex{ plugin, lt.mIndex }, lt.mId);
|
||||||
{
|
|
||||||
if (tex->mId == lt.mId)
|
|
||||||
tex->mTexture = lt.mTexture;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LandTextureList& ltexl = mStatic.back();
|
return RecordId(lt.mId, isDeleted);
|
||||||
if (lt.mIndex + 1 > (int)ltexl.size())
|
|
||||||
ltexl.resize(lt.mIndex + 1);
|
|
||||||
|
|
||||||
// Store it
|
|
||||||
auto idx = lt.mIndex;
|
|
||||||
ltexl[idx] = std::move(lt);
|
|
||||||
|
|
||||||
return RecordId(ltexl[idx].mId, isDeleted);
|
|
||||||
}
|
}
|
||||||
Store<ESM::LandTexture>::iterator Store<ESM::LandTexture>::begin(size_t plugin) const
|
|
||||||
|
bool Store<ESM::LandTexture>::eraseStatic(const ESM::RefId& id)
|
||||||
{
|
{
|
||||||
assert(plugin < mStatic.size());
|
mStatic.erase(id);
|
||||||
return mStatic[plugin].begin();
|
return true;
|
||||||
}
|
|
||||||
Store<ESM::LandTexture>::iterator Store<ESM::LandTexture>::end(size_t plugin) const
|
|
||||||
{
|
|
||||||
assert(plugin < mStatic.size());
|
|
||||||
return mStatic[plugin].end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Land
|
// Land
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
Store<ESM::Land>::~Store() {}
|
Store<ESM::Land>::~Store() = default;
|
||||||
size_t Store<ESM::Land>::getSize() const
|
size_t Store<ESM::Land>::getSize() const
|
||||||
{
|
{
|
||||||
return mStatic.size();
|
return mStatic.size();
|
||||||
|
|
|
@ -255,29 +255,21 @@ namespace MWWorld
|
||||||
template <>
|
template <>
|
||||||
class Store<ESM::LandTexture> : public DynamicStore
|
class Store<ESM::LandTexture> : public DynamicStore
|
||||||
{
|
{
|
||||||
// For multiple ESM/ESP files we need one list per file.
|
using PluginIndex = std::pair<int, std::uint32_t>; // This is essentially a FormId
|
||||||
typedef std::vector<ESM::LandTexture> LandTextureList;
|
std::unordered_map<ESM::RefId, std::string> mStatic;
|
||||||
std::vector<LandTextureList> mStatic;
|
std::map<PluginIndex, ESM::RefId> mMappings;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Store();
|
Store();
|
||||||
|
|
||||||
typedef std::vector<ESM::LandTexture>::const_iterator iterator;
|
|
||||||
|
|
||||||
// Must be threadsafe! Called from terrain background loading threads.
|
// Must be threadsafe! Called from terrain background loading threads.
|
||||||
// Not a big deal here, since ESM::LandTexture can never be modified or inserted/erased
|
// Not a big deal here, since ESM::LandTexture can never be modified or inserted/erased
|
||||||
const ESM::LandTexture* search(size_t index, size_t plugin) const;
|
const std::string* search(std::uint32_t index, int plugin) const;
|
||||||
const ESM::LandTexture* find(size_t index, size_t plugin) const;
|
|
||||||
|
|
||||||
void resize(std::size_t num);
|
|
||||||
|
|
||||||
size_t getSize() const override;
|
size_t getSize() const override;
|
||||||
size_t getSize(size_t plugin) const;
|
bool eraseStatic(const ESM::RefId& id) override;
|
||||||
|
|
||||||
RecordId load(ESM::ESMReader& esm) override;
|
RecordId load(ESM::ESMReader& esm) override;
|
||||||
|
|
||||||
iterator begin(size_t plugin) const;
|
|
||||||
iterator end(size_t plugin) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
@ -497,7 +497,11 @@ namespace
|
||||||
|
|
||||||
const RecordType* result = nullptr;
|
const RecordType* result = nullptr;
|
||||||
if constexpr (std::is_same_v<RecordType, ESM::LandTexture>)
|
if constexpr (std::is_same_v<RecordType, ESM::LandTexture>)
|
||||||
result = esmStore.get<RecordType>().search(index, 0);
|
{
|
||||||
|
const std::string* texture = esmStore.get<RecordType>().search(index, 0);
|
||||||
|
ASSERT_NE(texture, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if constexpr (ESM::hasIndex<RecordType>)
|
else if constexpr (ESM::hasIndex<RecordType>)
|
||||||
result = esmStore.get<RecordType>().search(index);
|
result = esmStore.get<RecordType>().search(index);
|
||||||
else
|
else
|
||||||
|
|
|
@ -26,10 +26,9 @@ namespace ESM
|
||||||
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
|
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
|
||||||
static std::string_view getRecordType() { return "LandTexture"; }
|
static std::string_view getRecordType() { return "LandTexture"; }
|
||||||
|
|
||||||
// mId is merely a user friendly name for the texture in the editor.
|
|
||||||
std::string mTexture;
|
std::string mTexture;
|
||||||
RefId mId;
|
RefId mId;
|
||||||
int32_t mIndex;
|
uint32_t mIndex;
|
||||||
|
|
||||||
void load(ESMReader& esm, bool& isDeleted);
|
void load(ESMReader& esm, bool& isDeleted);
|
||||||
void save(ESMWriter& esm, bool isDeleted = false) const;
|
void save(ESMWriter& esm, bool isDeleted = false) const;
|
||||||
|
|
|
@ -372,9 +372,9 @@ namespace ESMTerrain
|
||||||
if (id.first != 0)
|
if (id.first != 0)
|
||||||
{
|
{
|
||||||
// NB: All vtex ids are +1 compared to the ltex ids
|
// NB: All vtex ids are +1 compared to the ltex ids
|
||||||
const ESM::LandTexture* ltex = getLandTexture(id.first - 1, id.second);
|
const std::string* ltex = getLandTexture(id.first - 1, id.second);
|
||||||
if (ltex)
|
if (ltex)
|
||||||
texture = ltex->mTexture;
|
texture = *ltex;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Warning: Unable to find land texture index " << id.first - 1 << " in plugin "
|
Log(Debug::Warning) << "Warning: Unable to find land texture index " << id.first - 1 << " in plugin "
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace ESMTerrain
|
||||||
|
|
||||||
// Not implemented in this class, because we need different Store implementations for game and editor
|
// Not implemented in this class, because we need different Store implementations for game and editor
|
||||||
virtual osg::ref_ptr<const LandObject> getLand(ESM::ExteriorCellLocation cellLocation) = 0;
|
virtual osg::ref_ptr<const LandObject> getLand(ESM::ExteriorCellLocation cellLocation) = 0;
|
||||||
virtual const ESM::LandTexture* getLandTexture(std::uint16_t index, int plugin) = 0;
|
virtual const std::string* getLandTexture(std::uint16_t index, int plugin) = 0;
|
||||||
/// Get bounds of the whole terrain in cell units
|
/// Get bounds of the whole terrain in cell units
|
||||||
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override = 0;
|
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue