Skip to content

Commit

Permalink
Merge branch 'ltexerasure' into 'master'
Browse files Browse the repository at this point in the history
Fix LTEX overriding and allow deletion

See merge request OpenMW/openmw!4152
  • Loading branch information
psi29a committed Jun 7, 2024
2 parents 24d8acc + 330f5de commit a80f5c1
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 83 deletions.
4 changes: 2 additions & 2 deletions apps/opencs/view/render/terrainstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ namespace CSVRender
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(
ESM::RefId::stringRefId(CSMWorld::LandTexture::createUniqueRecordId(plugin, index)));
if (row == -1)
return nullptr;

return &mData.getLandTextures().getRecord(row).get();
return &mData.getLandTextures().getRecord(row).get().mTexture;
}

void TerrainStorage::setAlteredHeight(int inCellX, int inCellY, float height)
Expand Down
2 changes: 1 addition & 1 deletion apps/opencs/view/render/terrainstorage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace CSVRender
std::array<float, ESM::Land::LAND_SIZE * ESM::Land::LAND_SIZE> mAlteredHeight;

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;

Expand Down
3 changes: 1 addition & 2 deletions apps/openmw/mwrender/terrainstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ namespace MWRender
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();
return esmStore.get<ESM::LandTexture>().search(index, plugin);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/openmw/mwrender/terrainstorage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace MWRender
~TerrainStorage();

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;

Expand Down
5 changes: 0 additions & 5 deletions apps/openmw/mwworld/esmstore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,6 @@ namespace MWWorld
if (listener != nullptr)
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
while (esm.hasMoreRecs())
{
Expand Down
74 changes: 21 additions & 53 deletions apps/openmw/mwworld/store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,83 +379,51 @@ namespace MWWorld

// LandTexture
//=========================================================================
Store<ESM::LandTexture>::Store() {}
const ESM::LandTexture* Store<ESM::LandTexture>::search(size_t index, size_t plugin) const
{
assert(plugin < mStatic.size());
const LandTextureList& ltexl = mStatic[plugin];
Store<ESM::LandTexture>::Store() = default;

if (index >= ltexl.size())
return nullptr;
return &ltexl[index];
}
const ESM::LandTexture* Store<ESM::LandTexture>::find(size_t index, size_t plugin) const
const std::string* Store<ESM::LandTexture>::search(std::uint32_t index, int plugin) const
{
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);
auto mapping = mMappings.find(PluginIndex{ plugin, index });
if (mapping == mMappings.end())
return nullptr;
auto texture = mStatic.find(mapping->second);
if (texture == mStatic.end())
return nullptr;
return &texture->second;
}

size_t Store<ESM::LandTexture>::getSize() const
{
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)
{
const int plugin = esm.getIndex();

ESM::LandTexture lt;
bool isDeleted = false;

lt.load(esm, isDeleted);

// Replace texture for records with given ID and index from all plugins.
for (unsigned int i = 0; i < mStatic.size(); i++)
if (!isDeleted)
{
ESM::LandTexture* tex = const_cast<ESM::LandTexture*>(search(lt.mIndex, i));
if (tex)
{
if (tex->mId == lt.mId)
tex->mTexture = lt.mTexture;
}
mStatic[lt.mId] = std::move(lt.mTexture);
mMappings.emplace(PluginIndex{ plugin, lt.mIndex }, lt.mId);
}

LandTextureList& ltexl = mStatic.back();
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
{
assert(plugin < mStatic.size());
return mStatic[plugin].begin();
return RecordId(lt.mId, isDeleted);
}
Store<ESM::LandTexture>::iterator Store<ESM::LandTexture>::end(size_t plugin) const

bool Store<ESM::LandTexture>::eraseStatic(const ESM::RefId& id)
{
assert(plugin < mStatic.size());
return mStatic[plugin].end();
mStatic.erase(id);
return true;
}

// Land
//=========================================================================
Store<ESM::Land>::~Store() {}
Store<ESM::Land>::~Store() = default;
size_t Store<ESM::Land>::getSize() const
{
return mStatic.size();
Expand Down
18 changes: 5 additions & 13 deletions apps/openmw/mwworld/store.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,29 +255,21 @@ namespace MWWorld
template <>
class Store<ESM::LandTexture> : public DynamicStore
{
// For multiple ESM/ESP files we need one list per file.
typedef std::vector<ESM::LandTexture> LandTextureList;
std::vector<LandTextureList> mStatic;
using PluginIndex = std::pair<int, std::uint32_t>; // This is essentially a FormId
std::unordered_map<ESM::RefId, std::string> mStatic;
std::map<PluginIndex, ESM::RefId> mMappings;

public:
Store();

typedef std::vector<ESM::LandTexture>::const_iterator iterator;

// Must be threadsafe! Called from terrain background loading threads.
// 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 ESM::LandTexture* find(size_t index, size_t plugin) const;

void resize(std::size_t num);
const std::string* search(std::uint32_t index, int plugin) const;

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;

iterator begin(size_t plugin) const;
iterator end(size_t plugin) const;
};

template <>
Expand Down
6 changes: 5 additions & 1 deletion apps/openmw_test_suite/mwworld/test_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,11 @@ namespace

const RecordType* result = nullptr;
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>)
result = esmStore.get<RecordType>().search(index);
else
Expand Down
3 changes: 1 addition & 2 deletions components/esm3/loadltex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ namespace ESM
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string_view getRecordType() { return "LandTexture"; }

// mId is merely a user friendly name for the texture in the editor.
std::string mTexture;
RefId mId;
int32_t mIndex;
uint32_t mIndex;

void load(ESMReader& esm, bool& isDeleted);
void save(ESMWriter& esm, bool isDeleted = false) const;
Expand Down
4 changes: 2 additions & 2 deletions components/esmterrain/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,9 @@ namespace ESMTerrain
if (id.first != 0)
{
// 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)
texture = ltex->mTexture;
texture = *ltex;
else
{
Log(Debug::Warning) << "Warning: Unable to find land texture index " << id.first - 1 << " in plugin "
Expand Down
2 changes: 1 addition & 1 deletion components/esmterrain/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace ESMTerrain

// 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 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
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override = 0;

Expand Down

0 comments on commit a80f5c1

Please sign in to comment.