2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-05-17 07:21:43 +00:00

refactor: introduce subasset loading

This commit is contained in:
Jan Laupetin
2026-02-05 16:25:00 +00:00
parent 1be411b371
commit aa47ffa629
255 changed files with 1668 additions and 3132 deletions
+193
View File
@@ -0,0 +1,193 @@
#include "AssetPool.h"
#include "GlobalAssetPool.h"
#include <cassert>
#include <format>
AssetPool::Iterator::Iterator(std::unordered_map<std::string, XAssetInfoGeneric*>::iterator i)
: m_iterator(std::move(i))
{
}
bool AssetPool::Iterator::operator!=(const Iterator& rhs) const
{
return m_iterator != rhs.m_iterator;
}
XAssetInfoGeneric* AssetPool::Iterator::operator*() const
{
return m_iterator.operator*().second;
}
void AssetPool::Iterator::operator++()
{
++m_iterator;
}
AssetPool::CIterator::CIterator(std::unordered_map<std::string, XAssetInfoGeneric*>::const_iterator i)
: m_iterator(std::move(i))
{
}
bool AssetPool::CIterator::operator!=(const CIterator& rhs) const
{
return m_iterator != rhs.m_iterator;
}
const XAssetInfoGeneric* AssetPool::CIterator::operator*() const
{
return m_iterator.operator*().second;
}
void AssetPool::CIterator::operator++()
{
++m_iterator;
}
//
// AssetPool
//
XAssetInfoGeneric* AssetPool::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
const auto normalizedName = XAssetInfoGeneric::NormalizeAssetName(xAssetInfo->m_name);
auto* pAssetInfo = xAssetInfo.get();
m_asset_lookup[normalizedName] = pAssetInfo;
m_assets.emplace_back(std::move(xAssetInfo));
return pAssetInfo;
}
XAssetInfoGeneric* AssetPool::GetAsset(const std::string& name)
{
const auto normalizedName = XAssetInfoGeneric::NormalizeAssetName(name);
const auto foundAsset = m_asset_lookup.find(normalizedName);
if (foundAsset == m_asset_lookup.end())
return nullptr;
return foundAsset->second;
}
size_t AssetPool::size() const
{
return m_asset_lookup.size();
}
bool AssetPool::empty() const
{
return m_asset_lookup.empty();
}
AssetPool::Iterator AssetPool::begin()
{
return Iterator(m_asset_lookup.begin());
}
AssetPool::Iterator AssetPool::end()
{
return Iterator(m_asset_lookup.end());
}
AssetPool::CIterator AssetPool::begin() const
{
return CIterator(m_asset_lookup.cbegin());
}
AssetPool::CIterator AssetPool::end() const
{
return CIterator(m_asset_lookup.cend());
}
//
// ZoneAssetPools
//
ZoneAssetPools::ZoneAssetPools(Zone& zone, const zone_priority_t priority)
: m_zone(zone)
{
const auto assetTypeCount = IGame::GetGameById(zone.m_game_id)->GetAssetTypeCount();
const auto* gameGlobalAssetPools = GameGlobalAssetPools::GetGlobalPoolsForGame(zone.m_game_id);
m_asset_pools.resize(assetTypeCount);
for (asset_type_t assetType = 0; assetType < assetTypeCount; assetType++)
{
m_asset_pools[assetType] = std::make_unique<AssetPool>();
gameGlobalAssetPools->LinkAssetPool(assetType, m_asset_pools[assetType].get(), priority);
}
}
ZoneAssetPools::~ZoneAssetPools()
{
const auto assetTypeCount = IGame::GetGameById(m_zone.m_game_id)->GetAssetTypeCount();
const auto* gameGlobalAssetPools = GameGlobalAssetPools::GetGlobalPoolsForGame(m_zone.m_game_id);
assert(assetTypeCount == m_asset_pools.size());
for (asset_type_t assetType = 0; assetType < assetTypeCount; assetType++)
{
assert(m_asset_pools[assetType]);
gameGlobalAssetPools->UnlinkAssetPool(assetType, m_asset_pools[assetType].get());
}
}
XAssetInfoGeneric* ZoneAssetPools::AddAsset(const asset_type_t type,
std::string name,
void* asset,
std::vector<XAssetInfoGeneric*> dependencies,
std::vector<scr_string_t> usedScriptStrings,
std::vector<IndirectAssetReference> indirectAssetReferences)
{
return AddAsset(std::make_unique<XAssetInfoGeneric>(
type, std::move(name), asset, std::move(dependencies), std::move(usedScriptStrings), std::move(indirectAssetReferences), &m_zone));
}
XAssetInfoGeneric* ZoneAssetPools::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
const auto type = xAssetInfo->m_type;
assert(m_asset_pools.size() > type);
auto* assetInfo = m_asset_pools[type]->AddAsset(std::move(xAssetInfo));
const auto normalizedName = XAssetInfoGeneric::NormalizeAssetName(assetInfo->m_name);
GameGlobalAssetPools::GetGlobalPoolsForGame(m_zone.m_game_id)->LinkAsset(type, m_asset_pools[type].get(), normalizedName, assetInfo);
assert(assetInfo);
m_assets_in_order.emplace_back(assetInfo);
return assetInfo;
}
XAssetInfoGeneric* ZoneAssetPools::GetAsset(const asset_type_t type, const std::string& name) const
{
assert(m_asset_pools.size() > type);
return m_asset_pools[type]->GetAsset(name);
}
XAssetInfoGeneric* ZoneAssetPools::GetAssetOrAssetReference(const asset_type_t type, const std::string& name) const
{
auto* result = GetAsset(type, name);
if (result != nullptr || (!name.empty() && name[0] == ','))
return result;
result = GetAsset(type, std::format(",{}", name));
return result;
}
size_t ZoneAssetPools::GetTotalAssetCount() const
{
return m_assets_in_order.size();
}
ZoneAssetPools::all_iterator ZoneAssetPools::begin() const
{
return m_assets_in_order.begin();
}
ZoneAssetPools::all_iterator ZoneAssetPools::end() const
{
return m_assets_in_order.end();
}
+153 -79
View File
@@ -1,109 +1,183 @@
#pragma once
#include "XAssetInfo.h"
#include "Zone/Zone.h"
#include "Game/IAsset.h"
#include "Zone/ZoneTypes.h"
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
class Zone;
template<typename T> class XAssetInfo;
class XAssetInfoGeneric;
class IndirectAssetReference;
template<typename T> class AssetPool
class AssetPool
{
public:
using type = T;
std::map<std::string, XAssetInfo<T>*> m_asset_lookup;
class Iterator
{
typename std::map<std::string, XAssetInfo<T>*>::iterator m_iterator;
public:
explicit Iterator(typename std::map<std::string, XAssetInfo<T>*>::iterator i)
{
m_iterator = i;
}
explicit Iterator(std::unordered_map<std::string, XAssetInfoGeneric*>::iterator i);
bool operator!=(Iterator rhs)
{
return m_iterator != rhs.m_iterator;
}
bool operator!=(const Iterator& rhs) const;
XAssetInfoGeneric* operator*() const;
void operator++();
XAssetInfo<T>* operator*()
{
return m_iterator.operator*().second;
}
void operator++()
{
++m_iterator;
}
private:
std::unordered_map<std::string, XAssetInfoGeneric*>::iterator m_iterator;
};
class CIterator
{
typename std::map<std::string, XAssetInfo<T>*>::const_iterator m_iterator;
public:
explicit CIterator(typename std::map<std::string, XAssetInfo<T>*>::const_iterator i)
{
m_iterator = i;
}
explicit CIterator(std::unordered_map<std::string, XAssetInfoGeneric*>::const_iterator i);
bool operator!=(CIterator rhs)
{
return m_iterator != rhs.m_iterator;
}
bool operator!=(const CIterator& rhs) const;
const XAssetInfoGeneric* operator*() const;
void operator++();
const XAssetInfo<T>* operator*()
{
return m_iterator.operator*().second;
}
void operator++()
{
++m_iterator;
}
private:
std::unordered_map<std::string, XAssetInfoGeneric*>::const_iterator m_iterator;
};
AssetPool()
{
m_asset_lookup = std::map<std::string, XAssetInfo<T>*>();
}
AssetPool() = default;
~AssetPool() = default;
virtual ~AssetPool() = default;
AssetPool(AssetPool&) = delete;
AssetPool(AssetPool&&) = delete;
AssetPool& operator=(AssetPool&) = delete;
AssetPool& operator=(AssetPool&&) = delete;
virtual XAssetInfo<T>* AddAsset(std::unique_ptr<XAssetInfo<T>> xAssetInfo) = 0;
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
XAssetInfoGeneric* GetAsset(const std::string& name);
XAssetInfo<T>* GetAsset(const std::string& name)
{
const auto normalizedName = XAssetInfo<T>::NormalizeAssetName(name);
auto foundAsset = m_asset_lookup.find(normalizedName);
[[nodiscard]] size_t size() const;
[[nodiscard]] bool empty() const;
if (foundAsset == m_asset_lookup.end())
return nullptr;
[[nodiscard]] Iterator begin();
[[nodiscard]] Iterator end();
return foundAsset->second;
}
[[nodiscard]] CIterator begin() const;
[[nodiscard]] CIterator end() const;
Iterator begin()
{
return Iterator(m_asset_lookup.begin());
}
Iterator end()
{
return Iterator(m_asset_lookup.end());
}
CIterator begin() const
{
return CIterator(m_asset_lookup.cbegin());
}
CIterator end() const
{
return CIterator(m_asset_lookup.cend());
}
private:
std::unordered_map<std::string, XAssetInfoGeneric*> m_asset_lookup;
std::vector<std::unique_ptr<XAssetInfoGeneric>> m_assets;
};
template<AssetDefinition Asset_t> class AssetPoolIterator
{
public:
explicit AssetPoolIterator(AssetPool::Iterator i)
: m_iterator(std::move(i))
{
}
bool operator!=(const AssetPoolIterator& rhs) const
{
return m_iterator != rhs.m_iterator;
}
XAssetInfo<typename Asset_t::Type>* operator*() const
{
return reinterpret_cast<XAssetInfo<typename Asset_t::Type>*>(*m_iterator);
}
void operator++()
{
++m_iterator;
}
private:
AssetPool::Iterator m_iterator;
};
template<AssetDefinition Asset_t> class AssetPoolIterators
{
public:
explicit AssetPoolIterators(AssetPool& assetPool)
: m_asset_pool(assetPool)
{
}
AssetPoolIterator<Asset_t> begin()
{
return AssetPoolIterator<Asset_t>(m_asset_pool.begin());
}
AssetPoolIterator<Asset_t> end()
{
return AssetPoolIterator<Asset_t>(m_asset_pool.end());
}
[[nodiscard]] size_t size() const
{
return m_asset_pool.size();
}
[[nodiscard]] bool empty() const
{
return m_asset_pool.empty();
}
private:
AssetPool& m_asset_pool;
};
class ZoneAssetPools
{
public:
using all_iterator = std::vector<XAssetInfoGeneric*>::const_iterator;
ZoneAssetPools(Zone& zone, zone_priority_t priority);
~ZoneAssetPools();
ZoneAssetPools(const ZoneAssetPools& other) = delete;
ZoneAssetPools(ZoneAssetPools&& other) noexcept = delete;
ZoneAssetPools& operator=(const ZoneAssetPools& other) = delete;
ZoneAssetPools& operator=(ZoneAssetPools&& other) noexcept = delete;
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
XAssetInfoGeneric* AddAsset(asset_type_t type,
std::string name,
void* asset,
std::vector<XAssetInfoGeneric*> dependencies,
std::vector<scr_string_t> usedScriptStrings,
std::vector<IndirectAssetReference> indirectAssetReferences);
[[nodiscard]] XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const;
[[nodiscard]] XAssetInfoGeneric* GetAssetOrAssetReference(asset_type_t type, const std::string& name) const;
template<AssetDefinition Asset_t> XAssetInfo<typename Asset_t::Type>* AddAsset(std::unique_ptr<XAssetInfo<typename Asset_t::Type>> xAssetInfo)
{
return reinterpret_cast<XAssetInfo<typename Asset_t::Type>*>(AddAsset(std::unique_ptr<XAssetInfoGeneric>(xAssetInfo.release())));
}
template<AssetDefinition Asset_t> [[nodiscard]] XAssetInfo<typename Asset_t::Type>* GetAsset(const std::string& name) const
{
return reinterpret_cast<XAssetInfo<typename Asset_t::Type>*>(GetAsset(Asset_t::EnumEntry, name));
}
template<AssetDefinition Asset_t> [[nodiscard]] XAssetInfo<typename Asset_t::Type>* GetAssetOrAssetReference(const std::string& name) const
{
return reinterpret_cast<XAssetInfo<typename Asset_t::Type>*>(GetAssetOrAssetReference(Asset_t::EnumEntry, name));
}
template<AssetDefinition Asset_t> [[nodiscard]] AssetPoolIterators<Asset_t> PoolAssets() const
{
return AssetPoolIterators<Asset_t>(*m_asset_pools[Asset_t::EnumEntry]);
}
[[nodiscard]] size_t GetTotalAssetCount() const;
[[nodiscard]] all_iterator begin() const;
[[nodiscard]] all_iterator end() const;
private:
Zone& m_zone;
std::vector<std::unique_ptr<AssetPool>> m_asset_pools;
std::vector<XAssetInfoGeneric*> m_assets_in_order;
};
#include "XAssetInfo.h"
#include "Zone/Zone.h"
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include "AssetPool.h"
#include "GlobalAssetPool.h"
#include "XAssetInfo.h"
#include <vector>
template<typename T> class AssetPoolDynamic final : public AssetPool<T>
{
using AssetPool<T>::m_asset_lookup;
std::vector<std::unique_ptr<XAssetInfo<T>>> m_assets;
public:
explicit AssetPoolDynamic(const zone_priority_t priority)
{
GlobalAssetPool<T>::LinkAssetPool(this, priority);
}
AssetPoolDynamic(AssetPoolDynamic<T>&) = delete;
AssetPoolDynamic(AssetPoolDynamic<T>&&) = delete;
AssetPoolDynamic<T>& operator=(AssetPoolDynamic<T>&) = delete;
AssetPoolDynamic<T>& operator=(AssetPoolDynamic<T>&&) = default;
~AssetPoolDynamic() override
{
GlobalAssetPool<T>::UnlinkAssetPool(this);
m_assets.clear();
m_asset_lookup.clear();
}
XAssetInfo<T>* AddAsset(std::unique_ptr<XAssetInfo<T>> xAssetInfo) override
{
const auto normalizedName = XAssetInfo<T>::NormalizeAssetName(xAssetInfo->m_name);
auto* pAssetInfo = xAssetInfo.get();
m_asset_lookup[normalizedName] = pAssetInfo;
m_assets.emplace_back(std::move(xAssetInfo));
GlobalAssetPool<T>::LinkAsset(this, normalizedName, pAssetInfo);
return pAssetInfo;
}
};
+212
View File
@@ -0,0 +1,212 @@
#include "GlobalAssetPool.h"
#include <algorithm>
#include <cassert>
void GlobalAssetPool::LinkAssetPool(AssetPool* assetPool, const zone_priority_t priority)
{
auto newLink = std::make_unique<LinkedAssetPool>();
newLink->m_asset_pool = assetPool;
newLink->m_priority = priority;
auto* newLinkPtr = newLink.get();
m_linked_asset_pools.emplace_back(std::move(newLink));
SortLinkedAssetPools();
for (auto* asset : *assetPool)
{
const auto normalizedAssetName = XAssetInfoGeneric::NormalizeAssetName(asset->m_name);
LinkAsset(newLinkPtr, normalizedAssetName, asset);
}
}
void GlobalAssetPool::LinkAsset(const AssetPool* assetPool, const std::string& normalizedAssetName, XAssetInfoGeneric* asset)
{
LinkedAssetPool* link = nullptr;
for (const auto& existingLink : m_linked_asset_pools)
{
if (existingLink->m_asset_pool == assetPool)
{
link = existingLink.get();
break;
}
}
assert(link != nullptr);
if (link == nullptr)
return;
LinkAsset(link, normalizedAssetName, asset);
}
void GlobalAssetPool::UnlinkAssetPool(const AssetPool* assetPool)
{
auto iLinkEntry = m_linked_asset_pools.begin();
for (; iLinkEntry != m_linked_asset_pools.end(); ++iLinkEntry)
{
const auto* linkEntry = iLinkEntry->get();
if (linkEntry->m_asset_pool == assetPool)
break;
}
assert(iLinkEntry != m_linked_asset_pools.end());
if (iLinkEntry == m_linked_asset_pools.end())
return;
const auto assetPoolToUnlink = std::move(*iLinkEntry);
m_linked_asset_pools.erase(iLinkEntry);
for (auto iAssetEntry = m_assets.begin(); iAssetEntry != m_assets.end();)
{
auto& assetEntry = *iAssetEntry;
if (assetEntry.second.m_asset_pool != assetPoolToUnlink.get())
{
++iAssetEntry;
continue;
}
if (assetEntry.second.m_duplicate && ReplaceAssetPoolEntry(assetEntry.second))
{
++iAssetEntry;
continue;
}
iAssetEntry = m_assets.erase(iAssetEntry);
}
}
XAssetInfoGeneric* GlobalAssetPool::GetAsset(const std::string& name)
{
const auto normalizedName = XAssetInfoGeneric::NormalizeAssetName(name);
const auto foundEntry = m_assets.find(normalizedName);
if (foundEntry == m_assets.end())
return nullptr;
return foundEntry->second.m_asset;
}
void GlobalAssetPool::SortLinkedAssetPools()
{
std::ranges::sort(m_linked_asset_pools,
[](const std::unique_ptr<LinkedAssetPool>& a, const std::unique_ptr<LinkedAssetPool>& b) -> bool
{
return a->m_priority < b->m_priority;
});
}
bool GlobalAssetPool::ReplaceAssetPoolEntry(GameAssetPoolEntry& assetEntry) const
{
int occurrences = 0;
for (const auto& linkedAssetPool : m_linked_asset_pools)
{
auto* foundAsset = linkedAssetPool->m_asset_pool->GetAsset(assetEntry.m_asset->m_name);
if (foundAsset != nullptr)
{
if (++occurrences == 1)
{
assetEntry.m_asset = foundAsset;
assetEntry.m_duplicate = false;
assetEntry.m_asset_pool = linkedAssetPool.get();
}
else
{
assetEntry.m_duplicate = true;
break;
}
}
}
return occurrences > 0;
}
void GlobalAssetPool::LinkAsset(LinkedAssetPool* link, const std::string& normalizedAssetName, XAssetInfoGeneric* asset)
{
const auto existingAsset = m_assets.find(normalizedAssetName);
if (existingAsset == m_assets.end())
{
const GameAssetPoolEntry entry{
.m_asset = asset,
.m_asset_pool = link,
.m_duplicate = false,
};
m_assets[normalizedAssetName] = entry;
}
else
{
auto& existingEntry = existingAsset->second;
existingEntry.m_duplicate = true;
if (existingEntry.m_asset_pool->m_priority < link->m_priority)
{
existingEntry.m_asset_pool = link;
existingEntry.m_asset = asset;
}
}
}
GameGlobalAssetPools::GameGlobalAssetPools(const GameId gameId)
{
const auto assetTypeCount = IGame::GetGameById(gameId)->GetAssetTypeCount();
m_global_asset_pools.resize(assetTypeCount);
for (auto assetType = 0u; assetType < assetTypeCount; assetType++)
{
m_global_asset_pools[assetType] = std::make_unique<GlobalAssetPool>();
}
}
void GameGlobalAssetPools::LinkAssetPool(const asset_type_t assetType, AssetPool* assetPool, const zone_priority_t priority) const
{
assert(assetType < m_global_asset_pools.size());
m_global_asset_pools[assetType]->LinkAssetPool(assetPool, priority);
}
void GameGlobalAssetPools::LinkAsset(const asset_type_t assetType,
const AssetPool* assetPool,
const std::string& normalizedAssetName,
XAssetInfoGeneric* asset) const
{
assert(assetType < m_global_asset_pools.size());
m_global_asset_pools[assetType]->LinkAsset(assetPool, normalizedAssetName, asset);
}
void GameGlobalAssetPools::UnlinkAssetPool(const asset_type_t assetType, const AssetPool* assetPool) const
{
assert(assetType < m_global_asset_pools.size());
m_global_asset_pools[assetType]->UnlinkAssetPool(assetPool);
}
XAssetInfoGeneric* GameGlobalAssetPools::GetAsset(const asset_type_t assetType, const std::string& name) const
{
assert(assetType < m_global_asset_pools.size());
return m_global_asset_pools[assetType]->GetAsset(name);
}
GameGlobalAssetPools* GameGlobalAssetPools::GetGlobalPoolsForGame(GameId gameId)
{
static GameGlobalAssetPools* globalAssetPools[static_cast<unsigned>(GameId::COUNT)]{
new GameGlobalAssetPools(GameId::IW3),
new GameGlobalAssetPools(GameId::IW4),
new GameGlobalAssetPools(GameId::IW5),
new GameGlobalAssetPools(GameId::T5),
new GameGlobalAssetPools(GameId::T6),
};
assert(static_cast<unsigned>(gameId) < static_cast<unsigned>(GameId::COUNT));
auto* result = globalAssetPools[static_cast<unsigned>(gameId)];
assert(result);
return result;
}
+48 -176
View File
@@ -3,188 +3,60 @@
#include "AssetPool.h"
#include "Zone/ZoneTypes.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
template<typename T> class GlobalAssetPool
struct LinkedAssetPool
{
struct LinkedAssetPool
{
AssetPool<T>* m_asset_pool;
zone_priority_t m_priority;
};
struct GameAssetPoolEntry
{
XAssetInfo<T>* m_asset;
bool m_duplicate;
LinkedAssetPool* m_asset_pool;
};
static std::vector<std::unique_ptr<LinkedAssetPool>> m_linked_asset_pools;
static std::unordered_map<std::string, GameAssetPoolEntry> m_assets;
static void SortLinkedAssetPools()
{
std::sort(m_linked_asset_pools.begin(),
m_linked_asset_pools.end(),
[](const std::unique_ptr<LinkedAssetPool>& a, const std::unique_ptr<LinkedAssetPool>& b) -> bool
{
return a->m_priority < b->m_priority;
});
}
static bool ReplaceAssetPoolEntry(GameAssetPoolEntry& assetEntry)
{
int occurrences = 0;
for (const auto& linkedAssetPool : m_linked_asset_pools)
{
XAssetInfo<T>* foundAsset = linkedAssetPool->m_asset_pool->GetAsset(assetEntry.m_asset->m_name);
if (foundAsset != nullptr)
{
if (++occurrences == 1)
{
assetEntry.m_asset = foundAsset;
assetEntry.m_duplicate = false;
assetEntry.m_asset_pool = linkedAssetPool.get();
}
else
{
assetEntry.m_duplicate = true;
break;
}
}
}
return occurrences > 0;
}
static void LinkAsset(LinkedAssetPool* link, const std::string& normalizedAssetName, XAssetInfo<T>* asset)
{
auto existingAsset = m_assets.find(normalizedAssetName);
if (existingAsset == m_assets.end())
{
GameAssetPoolEntry entry{};
entry.m_asset = asset;
entry.m_asset_pool = link;
entry.m_duplicate = false;
m_assets[normalizedAssetName] = entry;
}
else
{
auto& existingEntry = existingAsset->second;
existingEntry.m_duplicate = true;
if (existingEntry.m_asset_pool->m_priority < link->m_priority)
{
existingEntry.m_asset_pool = link;
existingEntry.m_asset = asset;
}
}
}
public:
static void LinkAssetPool(AssetPool<T>* assetPool, const zone_priority_t priority)
{
auto newLink = std::make_unique<LinkedAssetPool>();
newLink->m_asset_pool = assetPool;
newLink->m_priority = priority;
auto* newLinkPtr = newLink.get();
m_linked_asset_pools.emplace_back(std::move(newLink));
SortLinkedAssetPools();
for (auto asset : *assetPool)
{
const auto normalizedAssetName = XAssetInfo<T>::NormalizeAssetName(asset->m_name);
LinkAsset(newLinkPtr, normalizedAssetName, asset);
}
}
static void LinkAsset(AssetPool<T>* assetPool, const std::string& normalizedAssetName, XAssetInfo<T>* asset)
{
LinkedAssetPool* link = nullptr;
for (const auto& existingLink : m_linked_asset_pools)
{
if (existingLink->m_asset_pool == assetPool)
{
link = existingLink.get();
break;
}
}
assert(link != nullptr);
if (link == nullptr)
return;
LinkAsset(link, normalizedAssetName, asset);
}
static void UnlinkAssetPool(AssetPool<T>* assetPool)
{
auto iLinkEntry = m_linked_asset_pools.begin();
for (; iLinkEntry != m_linked_asset_pools.end(); ++iLinkEntry)
{
LinkedAssetPool* linkEntry = iLinkEntry->get();
if (linkEntry->m_asset_pool == assetPool)
{
break;
}
}
assert(iLinkEntry != m_linked_asset_pools.end());
if (iLinkEntry == m_linked_asset_pools.end())
return;
auto assetPoolToUnlink = std::move(*iLinkEntry);
m_linked_asset_pools.erase(iLinkEntry);
for (auto iAssetEntry = m_assets.begin(); iAssetEntry != m_assets.end();)
{
auto& assetEntry = *iAssetEntry;
if (assetEntry.second.m_asset_pool != assetPoolToUnlink.get())
{
++iAssetEntry;
continue;
}
if (assetEntry.second.m_duplicate && ReplaceAssetPoolEntry(assetEntry.second))
{
++iAssetEntry;
continue;
}
iAssetEntry = m_assets.erase(iAssetEntry);
}
}
static XAssetInfo<T>* GetAssetByName(const std::string& name)
{
const auto normalizedName = XAssetInfo<T>::NormalizeAssetName(name);
const auto foundEntry = m_assets.find(normalizedName);
if (foundEntry == m_assets.end())
return nullptr;
return foundEntry->second.m_asset;
}
AssetPool* m_asset_pool;
zone_priority_t m_priority;
};
template<typename T>
std::vector<std::unique_ptr<typename GlobalAssetPool<T>::LinkedAssetPool>> GlobalAssetPool<T>::m_linked_asset_pools =
std::vector<std::unique_ptr<LinkedAssetPool>>();
struct GameAssetPoolEntry
{
XAssetInfoGeneric* m_asset;
LinkedAssetPool* m_asset_pool;
bool m_duplicate;
};
template<typename T>
std::unordered_map<std::string, typename GlobalAssetPool<T>::GameAssetPoolEntry> GlobalAssetPool<T>::m_assets =
std::unordered_map<std::string, GameAssetPoolEntry>();
class GlobalAssetPool
{
public:
void LinkAssetPool(AssetPool* assetPool, zone_priority_t priority);
void LinkAsset(const AssetPool* assetPool, const std::string& normalizedAssetName, XAssetInfoGeneric* asset);
void UnlinkAssetPool(const AssetPool* assetPool);
XAssetInfoGeneric* GetAsset(const std::string& name);
private:
void SortLinkedAssetPools();
bool ReplaceAssetPoolEntry(GameAssetPoolEntry& assetEntry) const;
void LinkAsset(LinkedAssetPool* link, const std::string& normalizedAssetName, XAssetInfoGeneric* asset);
std::vector<std::unique_ptr<LinkedAssetPool>> m_linked_asset_pools;
std::unordered_map<std::string, GameAssetPoolEntry> m_assets;
};
class GameGlobalAssetPools
{
public:
explicit GameGlobalAssetPools(GameId gameId);
void LinkAssetPool(asset_type_t assetType, AssetPool* assetPool, zone_priority_t priority) const;
void LinkAsset(asset_type_t assetType, const AssetPool* assetPool, const std::string& normalizedAssetName, XAssetInfoGeneric* asset) const;
void UnlinkAssetPool(asset_type_t assetType, const AssetPool* assetPool) const;
[[nodiscard]] XAssetInfoGeneric* GetAsset(asset_type_t assetType, const std::string& name) const;
template<AssetDefinition Asset_t> [[nodiscard]] XAssetInfo<typename Asset_t::Type>* GetAsset(const std::string& name) const
{
return reinterpret_cast<XAssetInfo<typename Asset_t::Type>*>(GetAsset(Asset_t::EnumEntry, name));
}
static GameGlobalAssetPools* GetGlobalPoolsForGame(GameId gameId);
private:
std::vector<std::unique_ptr<GlobalAssetPool>> m_global_asset_pools;
};
+1
View File
@@ -1,4 +1,5 @@
#pragma once
#include "Zone/Zone.h"
#include "Zone/ZoneTypes.h"
-82
View File
@@ -1,82 +0,0 @@
#include "ZoneAssetPools.h"
#include "Game/IW3/GameAssetPoolIW3.h"
#include "Game/IW4/GameAssetPoolIW4.h"
#include "Game/IW5/GameAssetPoolIW5.h"
#include "Game/T5/GameAssetPoolT5.h"
#include "Game/T6/GameAssetPoolT6.h"
#include "Game/T6/ZoneConstantsT6.h"
#include <cassert>
#include <format>
ZoneAssetPools::ZoneAssetPools(Zone* zone)
: m_zone(zone)
{
}
XAssetInfoGeneric* ZoneAssetPools::AddAsset(const asset_type_t type,
std::string name,
void* asset,
std::vector<XAssetInfoGeneric*> dependencies,
std::vector<scr_string_t> usedScriptStrings,
std::vector<IndirectAssetReference> indirectAssetReferences)
{
return AddAsset(std::make_unique<XAssetInfoGeneric>(
type, std::move(name), asset, std::move(dependencies), std::move(usedScriptStrings), std::move(indirectAssetReferences), m_zone));
}
XAssetInfoGeneric* ZoneAssetPools::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
auto* assetInfo = AddAssetToPool(std::move(xAssetInfo));
if (assetInfo)
m_assets_in_order.push_back(assetInfo);
return assetInfo;
}
XAssetInfoGeneric* ZoneAssetPools::GetAssetOrAssetReference(const asset_type_t type, const std::string& name) const
{
auto* result = GetAsset(type, name);
if (result != nullptr || (!name.empty() && name[0] == ','))
return result;
result = GetAsset(type, std::format(",{}", name));
return result;
}
size_t ZoneAssetPools::GetTotalAssetCount() const
{
return m_assets_in_order.size();
}
ZoneAssetPools::iterator ZoneAssetPools::begin() const
{
return m_assets_in_order.begin();
}
ZoneAssetPools::iterator ZoneAssetPools::end() const
{
return m_assets_in_order.end();
}
std::unique_ptr<ZoneAssetPools> ZoneAssetPools::CreateForGame(const GameId game, Zone* zone, const zone_priority_t priority)
{
switch (game)
{
case GameId::IW3:
return std::make_unique<GameAssetPoolIW3>(zone, priority);
case GameId::IW4:
return std::make_unique<GameAssetPoolIW4>(zone, priority);
case GameId::IW5:
return std::make_unique<GameAssetPoolIW5>(zone, priority);
case GameId::T5:
return std::make_unique<GameAssetPoolT5>(zone, priority);
case GameId::T6:
return std::make_unique<GameAssetPoolT6>(zone, priority);
default:
assert(false);
return nullptr;
}
}
-51
View File
@@ -1,51 +0,0 @@
#pragma once
#include "XAssetInfo.h"
#include "Zone/Zone.h"
#include "Zone/ZoneTypes.h"
#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <vector>
class Zone;
class IndirectAssetReference;
class XAssetInfoGeneric;
class ZoneAssetPools
{
public:
using iterator = std::vector<XAssetInfoGeneric*>::const_iterator;
explicit ZoneAssetPools(Zone* zone);
virtual ~ZoneAssetPools() = default;
ZoneAssetPools(const ZoneAssetPools& other) = delete;
ZoneAssetPools(ZoneAssetPools&& other) noexcept = default;
ZoneAssetPools& operator=(const ZoneAssetPools& other) = delete;
ZoneAssetPools& operator=(ZoneAssetPools&& other) noexcept = default;
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
XAssetInfoGeneric* AddAsset(asset_type_t type,
std::string name,
void* asset,
std::vector<XAssetInfoGeneric*> dependencies,
std::vector<scr_string_t> usedScriptStrings,
std::vector<IndirectAssetReference> indirectAssetReferences);
[[nodiscard]] virtual XAssetInfoGeneric* GetAsset(asset_type_t type, const std::string& name) const = 0;
[[nodiscard]] virtual XAssetInfoGeneric* GetAssetOrAssetReference(asset_type_t type, const std::string& name) const;
[[nodiscard]] size_t GetTotalAssetCount() const;
[[nodiscard]] iterator begin() const;
[[nodiscard]] iterator end() const;
static std::unique_ptr<ZoneAssetPools> CreateForGame(GameId game, Zone* zone, zone_priority_t priority);
protected:
virtual XAssetInfoGeneric* AddAssetToPool(std::unique_ptr<XAssetInfoGeneric> xAssetInfo) = 0;
Zone* m_zone;
std::vector<XAssetInfoGeneric*> m_assets_in_order;
};