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:
@@ -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
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/ZoneTypes.h"
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user