diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp b/src/Linker/Game/IW4/ZoneCreatorIW4.cpp index c5a74e95..92e9c5f0 100644 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp +++ b/src/Linker/Game/IW4/ZoneCreatorIW4.cpp @@ -5,6 +5,27 @@ using namespace IW4; +ZoneCreator::ZoneCreator() +{ + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + { + AddAssetTypeName(assetType, GameAssetPoolIW4::AssetTypeNameByType(assetType)); + } +} + +void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) +{ + m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); +} + +void ZoneCreator::CreateZoneAssetPools(Zone* zone) const +{ + zone->m_pools = std::make_unique(zone, zone->m_priority); + + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + zone->m_pools->InitPoolDynamic(assetType); +} + bool ZoneCreator::SupportsGame(const std::string& gameName) const { return gameName == g_GameIW4.GetShortName(); diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.h b/src/Linker/Game/IW4/ZoneCreatorIW4.h index 7bab80a1..79288247 100644 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.h +++ b/src/Linker/Game/IW4/ZoneCreatorIW4.h @@ -1,11 +1,22 @@ #pragma once +#include +#include + +#include "Zone/ZoneTypes.h" #include "ZoneCreation/IZoneCreator.h" namespace IW4 { class ZoneCreator final : public IZoneCreator { + std::unordered_map m_asset_types_by_name; + + void AddAssetTypeName(asset_type_t assetType, std::string name); + void CreateZoneAssetPools(Zone* zone) const; + public: + ZoneCreator(); + _NODISCARD bool SupportsGame(const std::string& gameName) const override; _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; }; diff --git a/src/Linker/Game/T6/ZoneCreatorT6.cpp b/src/Linker/Game/T6/ZoneCreatorT6.cpp index b38f1949..c8b24fd3 100644 --- a/src/Linker/Game/T6/ZoneCreatorT6.cpp +++ b/src/Linker/Game/T6/ZoneCreatorT6.cpp @@ -1,49 +1,33 @@ #include "ZoneCreatorT6.h" +#include + +#include "ObjLoading.h" #include "Game/T6/T6.h" #include "Game/T6/GameT6.h" #include "Game/T6/GameAssetPoolT6.h" using namespace T6; -namespace T6 +ZoneCreator::ZoneCreator() { - class SpecifiedAsset + for(auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) { - public: - XAssetType m_type; - std::string m_name; - bool m_reference; - }; + AddAssetTypeName(assetType, GameAssetPoolT6::AssetTypeNameByType(assetType)); + } +} - class AssetLoaderImpl - { - ZoneCreationContext& m_context; +void ZoneCreator::AddAssetTypeName(asset_type_t assetType, std::string name) +{ + m_asset_types_by_name.emplace(std::make_pair(std::move(name), assetType)); +} - void CreateZoneAssetPools(Zone* zone) const - { - zone->m_pools = std::make_unique(zone, zone->m_priority); +void ZoneCreator::CreateZoneAssetPools(Zone* zone) const +{ + zone->m_pools = std::make_unique(zone, zone->m_priority); - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); - } - - public: - explicit AssetLoaderImpl(ZoneCreationContext& context) - : m_context(context) - { - } - - std::unique_ptr CreateZoneForDefinition() - { - auto zone = std::make_unique(m_context.m_zone_name, 0, &g_GameT6); - CreateZoneAssetPools(zone.get()); - - std::vector specifiedAssets; - - return zone; - } - }; + for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) + zone->m_pools->InitPoolDynamic(assetType); } bool ZoneCreator::SupportsGame(const std::string& gameName) const @@ -53,6 +37,30 @@ bool ZoneCreator::SupportsGame(const std::string& gameName) const std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const { - AssetLoaderImpl impl(context); - return impl.CreateZoneForDefinition(); + auto zone = std::make_unique(context.m_zone_name, 0, &g_GameT6); + CreateZoneAssetPools(zone.get()); + + std::vector gdtList; + gdtList.reserve(context.m_gdt_files.size()); + for (const auto& gdt : context.m_gdt_files) + gdtList.push_back(gdt.get()); + const auto assetLoadingContext = std::make_unique(zone.get(), context.m_asset_search_path, std::move(gdtList)); + + for(const auto& assetEntry : context.m_definition->m_assets) + { + if (assetEntry.m_is_reference) + continue; + + const auto foundAssetTypeEntry = m_asset_types_by_name.find(assetEntry.m_asset_type); + if(foundAssetTypeEntry == m_asset_types_by_name.end()) + { + std::cout << "Unknown asset type \"" << assetEntry.m_asset_type << "\"" << std::endl; + return nullptr; + } + + if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name)) + return nullptr; + } + + return zone; } diff --git a/src/Linker/Game/T6/ZoneCreatorT6.h b/src/Linker/Game/T6/ZoneCreatorT6.h index ea890f82..ac6f7d6a 100644 --- a/src/Linker/Game/T6/ZoneCreatorT6.h +++ b/src/Linker/Game/T6/ZoneCreatorT6.h @@ -1,11 +1,22 @@ #pragma once +#include +#include + +#include "Zone/ZoneTypes.h" #include "ZoneCreation/IZoneCreator.h" namespace T6 { class ZoneCreator final : public IZoneCreator { + std::unordered_map m_asset_types_by_name; + + void AddAssetTypeName(asset_type_t assetType, std::string name); + void CreateZoneAssetPools(Zone* zone) const; + public: + ZoneCreator(); + _NODISCARD bool SupportsGame(const std::string& gameName) const override; _NODISCARD std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; }; diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index de445d10..fdda3553 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -427,12 +427,12 @@ class Linker::Impl std::unique_ptr CreateZoneForDefinition(const std::string& zoneName, ZoneDefinition& zoneDefinition, ISearchPath* assetSearchPath, ISearchPath* gdtSearchPath) const { - auto context = std::make_unique(zoneName, assetSearchPath); + auto context = std::make_unique(zoneName, assetSearchPath, &zoneDefinition); if (!GetGameNameFromZoneDefinition(context->m_game_name, zoneName, zoneDefinition)) return nullptr; if (!LoadGdtFilesFromZoneDefinition(context->m_gdt_files, zoneName, zoneDefinition, gdtSearchPath)) return nullptr; - + for(const auto* assetLoader : ZONE_CREATORS) { if(assetLoader->SupportsGame(context->m_game_name)) @@ -523,6 +523,8 @@ public: { printf("Loaded zone \"%s\"\n", zone->m_name.c_str()); } + + zones.emplace_back(std::move(zone)); } auto result = true; diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.cpp b/src/Linker/ZoneCreation/ZoneCreationContext.cpp index 9a6e6675..d63a82be 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.cpp +++ b/src/Linker/ZoneCreation/ZoneCreationContext.cpp @@ -1,12 +1,14 @@ #include "ZoneCreationContext.h" ZoneCreationContext::ZoneCreationContext() - : m_asset_search_path(nullptr) + : m_asset_search_path(nullptr), + m_definition(nullptr) { } -ZoneCreationContext::ZoneCreationContext(std::string zoneName, ISearchPath* assetSearchPath) - : m_asset_search_path(assetSearchPath), - m_zone_name(std::move(zoneName)) +ZoneCreationContext::ZoneCreationContext(std::string zoneName, ISearchPath* assetSearchPath, ZoneDefinition* definition) + : m_zone_name(std::move(zoneName)), + m_asset_search_path(assetSearchPath), + m_definition(definition) { } diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.h b/src/Linker/ZoneCreation/ZoneCreationContext.h index 2173c6be..8169909f 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.h +++ b/src/Linker/ZoneCreation/ZoneCreationContext.h @@ -5,15 +5,17 @@ #include "SearchPath/ISearchPath.h" #include "Obj/Gdt/Gdt.h" +#include "Zone/Definition/ZoneDefinition.h" class ZoneCreationContext { public: - ISearchPath* m_asset_search_path; std::string m_zone_name; std::string m_game_name; + ISearchPath* m_asset_search_path; + ZoneDefinition* m_definition; std::vector> m_gdt_files; ZoneCreationContext(); - ZoneCreationContext(std::string zoneName, ISearchPath* assetSearchPath); + ZoneCreationContext(std::string zoneName, ISearchPath* assetSearchPath, ZoneDefinition* definition); }; diff --git a/src/ObjLoading/AssetLoading/AssetLoadingContext.cpp b/src/ObjLoading/AssetLoading/AssetLoadingContext.cpp new file mode 100644 index 00000000..a17a79ed --- /dev/null +++ b/src/ObjLoading/AssetLoading/AssetLoadingContext.cpp @@ -0,0 +1,45 @@ +#include "AssetLoadingContext.h" + +AssetLoadingContext::AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector gdtFiles) + : m_zone(zone), + m_raw_search_path(rawSearchPath), + m_gdt_files(std::move(gdtFiles)) +{ + BuildGdtEntryCache(); +} + +void AssetLoadingContext::BuildGdtEntryCache() +{ + for(auto* gdt : m_gdt_files) + { + for(const auto& entry : gdt->m_entries) + { + auto gdfMapEntry = m_entries_by_gdf_and_by_name.find(entry->m_gdf_name); + if(gdfMapEntry == m_entries_by_gdf_and_by_name.end()) + { + std::unordered_map entryMap; + entryMap.emplace(std::make_pair(entry->m_name, entry.get())); + m_entries_by_gdf_and_by_name.emplace(std::make_pair(entry->m_gdf_name, std::move(entryMap))); + } + else + { + gdfMapEntry->second.emplace(std::make_pair(entry->m_name, entry.get())); + } + } + } +} + +GdtEntry* AssetLoadingContext::GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) +{ + const auto foundGdtMap = m_entries_by_gdf_and_by_name.find(gdfName); + + if (foundGdtMap == m_entries_by_gdf_and_by_name.end()) + return nullptr; + + const auto foundGdtEntry = foundGdtMap->second.find(entryName); + + if (foundGdtEntry == foundGdtMap->second.end()) + return nullptr; + + return foundGdtEntry->second; +} diff --git a/src/ObjLoading/AssetLoading/AssetLoadingContext.h b/src/ObjLoading/AssetLoading/AssetLoadingContext.h new file mode 100644 index 00000000..26bc0bfe --- /dev/null +++ b/src/ObjLoading/AssetLoading/AssetLoadingContext.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "IGdtQueryable.h" +#include "Obj/Gdt/Gdt.h" +#include "SearchPath/ISearchPath.h" +#include "Zone/Zone.h" + +class AssetLoadingContext final : public IGdtQueryable +{ + std::unordered_map> m_entries_by_gdf_and_by_name; + + void BuildGdtEntryCache(); + +public: + Zone* const m_zone; + ISearchPath* const m_raw_search_path; + const std::vector m_gdt_files; + + AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector gdtFiles); + GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override; +}; diff --git a/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp b/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp new file mode 100644 index 00000000..5d6b9f24 --- /dev/null +++ b/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp @@ -0,0 +1,69 @@ +#include "AssetLoadingManager.h" +#include + +AssetLoadingManager::AssetLoadingManager(const std::unordered_map>& assetLoadersByType, AssetLoadingContext& context): + m_asset_loaders_by_type(assetLoadersByType), + m_context(context), + m_last_dependency_loaded(nullptr) +{ +} + +bool AssetLoadingManager::LoadAssetFromLoader(const asset_type_t assetType, const std::string& assetName) +{ + return LoadDependency(assetType, assetName) != nullptr; +} + +void AssetLoadingManager::AddAsset(const asset_type_t assetType, const std::string& assetName, void* asset, std::vector& dependencies) +{ + m_last_dependency_loaded = m_context.m_zone->m_pools->AddAsset(assetType, assetName, asset, dependencies); + if (m_last_dependency_loaded == nullptr) + std::cout << "Failed to add asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\" to pool: \"" << assetName << "\"" << std::endl; +} + +XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName) +{ + const auto loader = m_asset_loaders_by_type.find(assetType); + if (loader != m_asset_loaders_by_type.end()) + { + if (loader->second->CanLoadFromGdt() && loader->second->LoadFromGdt(assetName, &m_context, m_context.m_zone->GetMemory(), this)) + { + auto* lastDependency = m_last_dependency_loaded; + m_last_dependency_loaded = nullptr; + return lastDependency; + } + + if (loader->second->CanLoadFromRaw() && loader->second->LoadFromRaw(assetName, m_context.m_raw_search_path, m_context.m_zone->GetMemory(), this)) + { + auto* lastDependency = m_last_dependency_loaded; + m_last_dependency_loaded = nullptr; + return lastDependency; + } + + auto* existingAsset = loader->second->LoadFromGlobalAssetPools(assetName); + if(existingAsset) + { + std::vector dependencies; + for (const auto* dependency : existingAsset->m_dependencies) + { + auto* newDependency = LoadDependency(dependency->m_type, dependency->m_name); + if (newDependency) + dependencies.push_back(newDependency); + else + return nullptr; + } + + AddAsset(existingAsset->m_type, existingAsset->m_name, existingAsset->m_ptr, dependencies); + auto* lastDependency = m_last_dependency_loaded; + m_last_dependency_loaded = nullptr; + return lastDependency; + } + + std::cout << "Failed to load asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\": \"" << assetName << "\"" << std::endl; + } + else + { + std::cout << "Failed to find loader for asset type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"" << std::endl; + } + + return nullptr; +} diff --git a/src/ObjLoading/AssetLoading/AssetLoadingManager.h b/src/ObjLoading/AssetLoading/AssetLoadingManager.h new file mode 100644 index 00000000..d6bcb2c2 --- /dev/null +++ b/src/ObjLoading/AssetLoading/AssetLoadingManager.h @@ -0,0 +1,20 @@ +#pragma once +#include + +#include "AssetLoadingContext.h" +#include "IAssetLoader.h" +#include "IAssetLoadingManager.h" + +class AssetLoadingManager final : public IAssetLoadingManager +{ + const std::unordered_map>& m_asset_loaders_by_type; + AssetLoadingContext& m_context; + XAssetInfoGeneric* m_last_dependency_loaded; + +public: + AssetLoadingManager(const std::unordered_map>& assetLoadersByType, AssetLoadingContext& context); + + bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName); + void AddAsset(asset_type_t assetType, const std::string& assetName, void* asset, std::vector& dependencies) override; + XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) override; +}; diff --git a/src/ObjLoading/AssetLoading/BasicAssetLoader.h b/src/ObjLoading/AssetLoading/BasicAssetLoader.h new file mode 100644 index 00000000..f9a80653 --- /dev/null +++ b/src/ObjLoading/AssetLoading/BasicAssetLoader.h @@ -0,0 +1,18 @@ +#pragma once +#include "IAssetLoader.h" +#include "Pool/GlobalAssetPool.h" + +template +class BasicAssetLoader : public IAssetLoader +{ +public: + _NODISCARD asset_type_t GetHandlingAssetType() const override + { + return AssetType; + } + + _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override + { + return GlobalAssetPool::GetAssetByName(assetName); + } +}; diff --git a/src/ObjLoading/AssetLoading/IAssetLoader.h b/src/ObjLoading/AssetLoading/IAssetLoader.h new file mode 100644 index 00000000..a2a9749f --- /dev/null +++ b/src/ObjLoading/AssetLoading/IAssetLoader.h @@ -0,0 +1,42 @@ +#pragma once +#include + +#include "Utils/ClassUtils.h" +#include "SearchPath/ISearchPath.h" +#include "IAssetLoadingManager.h" +#include "IGdtQueryable.h" +#include "Zone/ZoneTypes.h" + +class IAssetLoader +{ +public: + IAssetLoader() = default; + virtual ~IAssetLoader() = default; + IAssetLoader(const IAssetLoader& other) = default; + IAssetLoader(IAssetLoader&& other) noexcept = default; + IAssetLoader& operator=(const IAssetLoader& other) = default; + IAssetLoader& operator=(IAssetLoader&& other) noexcept = default; + + _NODISCARD virtual asset_type_t GetHandlingAssetType() const = 0; + _NODISCARD virtual XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const = 0; + + _NODISCARD virtual bool CanLoadFromGdt() const + { + return false; + } + + _NODISCARD virtual bool CanLoadFromRaw() const + { + return false; + } + + virtual bool LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager) const + { + return false; + } + + virtual bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const + { + return false; + } +}; diff --git a/src/ObjLoading/AssetLoading/IAssetLoadingManager.h b/src/ObjLoading/AssetLoading/IAssetLoadingManager.h new file mode 100644 index 00000000..c2a89361 --- /dev/null +++ b/src/ObjLoading/AssetLoading/IAssetLoadingManager.h @@ -0,0 +1,24 @@ +#pragma once +#include + +#include "Pool/XAssetInfo.h" +#include "Zone/ZoneTypes.h" + +class IAssetLoadingManager +{ +public: + IAssetLoadingManager() = default; + virtual ~IAssetLoadingManager() = default; + IAssetLoadingManager(const IAssetLoadingManager& other) = default; + IAssetLoadingManager(IAssetLoadingManager&& other) noexcept = default; + IAssetLoadingManager& operator=(const IAssetLoadingManager& other) = default; + IAssetLoadingManager& operator=(IAssetLoadingManager&& other) noexcept = default; + + virtual void AddAsset(asset_type_t assetType, const std::string& assetName, void* asset, std::vector& dependencies) = 0; + void AddAsset(const asset_type_t assetType, const std::string& assetName, void* asset) + { + std::vector dependencies; + AddAsset(assetType, assetName, asset, dependencies); + } + virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0; +}; diff --git a/src/ObjLoading/AssetLoading/IGdtQueryable.h b/src/ObjLoading/AssetLoading/IGdtQueryable.h new file mode 100644 index 00000000..79ff4ff8 --- /dev/null +++ b/src/ObjLoading/AssetLoading/IGdtQueryable.h @@ -0,0 +1,17 @@ +#pragma once +#include + +#include "Obj/Gdt/GdtEntry.h" + +class IGdtQueryable +{ +public: + IGdtQueryable() = default; + virtual ~IGdtQueryable() = default; + IGdtQueryable(const IGdtQueryable& other) = default; + IGdtQueryable(IGdtQueryable&& other) noexcept = default; + IGdtQueryable& operator=(const IGdtQueryable& other) = default; + IGdtQueryable& operator=(IGdtQueryable&& other) noexcept = default; + + virtual GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) = 0; +}; diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp new file mode 100644 index 00000000..839c6d6a --- /dev/null +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp @@ -0,0 +1,32 @@ +#include "AssetLoaderRawFile.h" + +#include "Game/IW4/IW4.h" +#include "Pool/GlobalAssetPool.h" + +using namespace IW4; + +bool AssetLoaderRawFile::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const +{ + const auto file = searchPath->Open(assetName); + if (!file.IsOpen()) + return false; + + auto* rawFile = memory->Create(); + rawFile->name = memory->Dup(assetName.c_str()); + rawFile->len = static_cast(file.m_length); + + auto* fileBuffer = static_cast(memory->Alloc(static_cast(file.m_length + 1))); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return false; + + rawFile->data.buffer = fileBuffer; + manager->AddAsset(ASSET_TYPE_RAWFILE, assetName, rawFile); + + return true; +} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h new file mode 100644 index 00000000..5027064c --- /dev/null +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h @@ -0,0 +1,15 @@ +#pragma once +#include "Game/IW4/IW4.h" +#include "AssetLoading/BasicAssetLoader.h" +#include "AssetLoading/IAssetLoadingManager.h" +#include "SearchPath/ISearchPath.h" + +namespace IW4 +{ + class AssetLoaderRawFile final : public BasicAssetLoader + { + public: + _NODISCARD bool CanLoadFromRaw() const override; + bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; + }; +} diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp index 31aadf48..ae22394c 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp @@ -3,106 +3,160 @@ #include "Game/IW4/GameAssetPoolIW4.h" #include "ObjContainer/IPak/IPak.h" #include "ObjLoading.h" +#include "AssetLoaders/AssetLoaderRawFile.h" +#include "AssetLoading/AssetLoadingManager.h" #include "Image/Texture.h" #include "Image/IwiLoader.h" -namespace IW4 +using namespace IW4; + +ObjLoader::ObjLoader() { - bool ObjLoader::SupportsZone(Zone* zone) const +#define REGISTER_ASSET_LOADER(t) {auto l = std::make_unique(); m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l);} +#define BASIC_LOADER(assetType, assetClass) BasicAssetLoader + + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_PHYSPRESET, PhysPreset)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_PHYSCOLLMAP, PhysCollmap)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL_SURFS, XModelSurfs)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_PIXELSHADER, MaterialPixelShader)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_VERTEXSHADER, MaterialVertexShader)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_VERTEXDECL, MaterialVertexDeclaration)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_IMAGE, GfxImage)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SOUND, snd_alias_list_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SOUND_CURVE, SndCurve)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LOADED_SOUND, LoadedSound)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_CLIPMAP_SP, clipMap_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_CLIPMAP_MP, clipMap_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_COMWORLD, ComWorld)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GAMEWORLD_SP, GameWorldSp)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GAMEWORLD_MP, GameWorldMp)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MAP_ENTS, MapEnts)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FXWORLD, FxWorld)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GFXWORLD, GfxWorld)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LIGHT_DEF, GfxLightDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FONT, Font_s)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENULIST, MenuList)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENU, menuDef_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_WEAPON, WeaponCompleteDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FX, FxEffectDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_IMPACT_FX, FxImpactTable)) + REGISTER_ASSET_LOADER(AssetLoaderRawFile) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_STRINGTABLE, StringTable)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LEADERBOARD, LeaderboardDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_STRUCTURED_DATA_DEF, StructuredDataDefSet)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TRACER, TracerDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_VEHICLE, VehicleDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts)) + +#undef BASIC_LOADER +#undef REGISTER_ASSET_LOADER +} + +bool ObjLoader::SupportsZone(Zone* zone) const +{ + return zone->m_game == &g_GameIW4; +} + +bool ObjLoader::IsMpZone(Zone* zone) +{ + return zone->m_name.compare(0, 3, "mp_") == 0 + || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0; +} + +bool ObjLoader::IsZmZone(Zone* zone) +{ + return zone->m_name.compare(0, 3, "zm_") == 0 + || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0; +} + +void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const +{ +} + +void ObjLoader::UnloadContainersOfZone(Zone* zone) const +{ +} + +void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone) +{ + // TODO: Load Texture from LoadDef here +} + +void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone) +{ + Texture* loadedTexture = nullptr; + IwiLoader loader(zone->GetMemory()); + + const auto imageFileName = "images/" + std::string(image->name) + ".iwi"; + { - return zone->m_game == &g_GameIW4; - } - - bool ObjLoader::IsMpZone(Zone* zone) - { - return zone->m_name.compare(0, 3, "mp_") == 0 - || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0; - } - - bool ObjLoader::IsZmZone(Zone* zone) - { - return zone->m_name.compare(0, 3, "zm_") == 0 - || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0; - } - - void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const - { - } - - void ObjLoader::UnloadContainersOfZone(Zone* zone) const - { - } - - void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone) - { - // TODO: Load Texture from LoadDef here - } - - void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone) - { - Texture* loadedTexture = nullptr; - IwiLoader loader(zone->GetMemory()); - - const auto imageFileName = "images/" + std::string(image->name) + ".iwi"; - + const auto filePathImage = searchPath->Open(imageFileName); + if (filePathImage.IsOpen()) { - const auto filePathImage = searchPath->Open(imageFileName); - if (filePathImage.IsOpen()) - { - loadedTexture = loader.LoadIwi(*filePathImage.m_stream); - } - } - - if (loadedTexture != nullptr) - { - image->texture.texture = loadedTexture; - image->cardMemory.platform[0] = 0; - - const auto textureMipCount = loadedTexture->GetMipMapCount(); - for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++) - image->cardMemory.platform[0] += static_cast(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount()); - } - else - { - printf("Could not find data for image \"%s\"\n", image->name); + loadedTexture = loader.LoadIwi(*filePathImage.m_stream); } } - void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone) + if (loadedTexture != nullptr) { - auto* assetPool = dynamic_cast(zone->m_pools.get()); + image->texture.texture = loadedTexture; + image->cardMemory.platform[0] = 0; - if (assetPool && assetPool->m_image != nullptr) - { - for (auto* imageEntry : *assetPool->m_image) - { - auto* image = imageEntry->Asset(); - - if (image->cardMemory.platform[0] > 0) - { - continue; - } - - // Do not load linked assets - if (image->name && image->name[0] == ',') - { - continue; - } - - if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0) - { - LoadImageFromLoadDef(image, zone); - } - else - { - LoadImageFromIwi(image, searchPath, zone); - } - } - } + const auto textureMipCount = loadedTexture->GetMipMapCount(); + for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++) + image->cardMemory.platform[0] += static_cast(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount()); } - - void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const + else { - LoadImageData(searchPath, zone); + printf("Could not find data for image \"%s\"\n", image->name); } } + +void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone) +{ + auto* assetPool = dynamic_cast(zone->m_pools.get()); + + if (assetPool && assetPool->m_image != nullptr) + { + for (auto* imageEntry : *assetPool->m_image) + { + auto* image = imageEntry->Asset(); + + if (image->cardMemory.platform[0] > 0) + { + continue; + } + + // Do not load linked assets + if (image->name && image->name[0] == ',') + { + continue; + } + + if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0) + { + LoadImageFromLoadDef(image, zone); + } + else + { + LoadImageFromIwi(image, searchPath, zone); + } + } + } +} + +void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const +{ + LoadImageData(searchPath, zone); +} + +bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const +{ + AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context); + return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); +} \ No newline at end of file diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.h b/src/ObjLoading/Game/IW4/ObjLoaderIW4.h index 59530c42..7b504c60 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.h +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.h @@ -1,6 +1,10 @@ #pragma once +#include +#include + #include "IObjLoader.h" +#include "AssetLoading/IAssetLoader.h" #include "SearchPath/ISearchPath.h" #include "Game/IW4/IW4.h" @@ -8,6 +12,8 @@ namespace IW4 { class ObjLoader final : public IObjLoader { + std::unordered_map> m_asset_loaders_by_type; + static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone); static void LoadImageFromLoadDef(GfxImage* image, Zone* zone); static void LoadImageData(ISearchPath* searchPath, Zone* zone); @@ -16,11 +22,15 @@ namespace IW4 static bool IsZmZone(Zone* zone); public: + ObjLoader(); + bool SupportsZone(Zone* zone) const override; void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override; void UnloadContainersOfZone(Zone* zone) const override; void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override; + + bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override; }; } diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp new file mode 100644 index 00000000..2a3d7246 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp @@ -0,0 +1,32 @@ +#include "AssetLoaderRawFile.h" + +#include "Game/T6/T6.h" +#include "Pool/GlobalAssetPool.h" + +using namespace T6; + +bool AssetLoaderRawFile::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const +{ + const auto file = searchPath->Open(assetName); + if (!file.IsOpen()) + return false; + + auto* rawFile = memory->Create(); + rawFile->name = memory->Dup(assetName.c_str()); + rawFile->len = static_cast(file.m_length); + + auto* fileBuffer = static_cast(memory->Alloc(static_cast(file.m_length + 1))); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return false; + + rawFile->buffer = static_cast(fileBuffer); + manager->AddAsset(ASSET_TYPE_RAWFILE, assetName, rawFile); + + return true; +} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h new file mode 100644 index 00000000..7c6b11a9 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h @@ -0,0 +1,15 @@ +#pragma once +#include "Game/T6/T6.h" +#include "AssetLoading/BasicAssetLoader.h" +#include "AssetLoading/IAssetLoadingManager.h" +#include "SearchPath/ISearchPath.h" + +namespace T6 +{ + class AssetLoaderRawFile final : public BasicAssetLoader + { + public: + _NODISCARD bool CanLoadFromRaw() const override; + bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; + }; +} diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 51fcbc0e..105f1d7e 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -4,6 +4,8 @@ #include "Game/T6/GameAssetPoolT6.h" #include "ObjContainer/IPak/IPak.h" #include "ObjLoading.h" +#include "AssetLoaders/AssetLoaderRawFile.h" +#include "AssetLoading/AssetLoadingManager.h" #include "Image/Texture.h" #include "Image/IwiLoader.h" #include "Game/T6/CommonT6.h" @@ -13,6 +15,64 @@ namespace T6 const int ObjLoader::IPAK_READ_HASH = CommonT6::Com_HashKey("ipak_read", 64); const int ObjLoader::GLOBAL_HASH = CommonT6::Com_HashKey("GLOBAL", 64); + ObjLoader::ObjLoader() + { +#define REGISTER_ASSET_LOADER(t) {auto l = std::make_unique(); m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l);} +#define BASIC_LOADER(assetType, assetClass) BasicAssetLoader + + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_PHYSPRESET, PhysPreset)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_PHYSCONSTRAINTS, PhysConstraints)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_IMAGE, GfxImage)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SOUND, SndBank)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SOUND_PATCH, SndPatch)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_CLIPMAP, clipMap_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_CLIPMAP_PVS, clipMap_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_COMWORLD, ComWorld)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GAMEWORLD_SP, GameWorldSp)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GAMEWORLD_MP, GameWorldMp)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MAP_ENTS, MapEnts)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GFXWORLD, GfxWorld)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LIGHT_DEF, GfxLightDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FONT, Font_s)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FONTICON, FontIcon)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENULIST, MenuList)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENU, menuDef_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_WEAPON, WeaponVariantDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT, WeaponAttachment)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT_UNIQUE, WeaponAttachmentUnique)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_WEAPON_CAMO, WeaponCamo)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SNDDRIVER_GLOBALS, SndDriverGlobals)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FX, FxEffectDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_IMPACT_FX, FxImpactTable)) + REGISTER_ASSET_LOADER(AssetLoaderRawFile) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_STRINGTABLE, StringTable)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LEADERBOARD, LeaderboardDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XGLOBALS, XGlobals)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DDL, ddlDef_t)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_GLASSES, Glasses)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_EMBLEMSET, EmblemSet)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SCRIPTPARSETREE, ScriptParseTree)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_VEHICLEDEF, VehicleDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MEMORYBLOCK, MemoryBlock)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TRACER, TracerDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SKINNEDVERTS, SkinnedVertsDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_QDB, Qdb)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_SLUG, Slug)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FOOTSTEP_TABLE, FootstepTableDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FOOTSTEPFX_TABLE, FootstepFXTableDef)) + REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ZBARRIER, ZBarrierDef)) + +#undef BASIC_LOADER +#undef REGISTER_ASSET_LOADER + } + bool ObjLoader::SupportsZone(Zone* zone) const { return zone->m_game == &g_GameT6; @@ -227,4 +287,10 @@ namespace T6 { LoadImageData(searchPath, zone); } + + bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) const + { + AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context); + return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); + } } diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.h b/src/ObjLoading/Game/T6/ObjLoaderT6.h index 5e977938..daae32c2 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.h +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.h @@ -1,6 +1,10 @@ #pragma once +#include +#include + #include "IObjLoader.h" +#include "AssetLoading/IAssetLoader.h" #include "SearchPath/ISearchPath.h" #include "Game/T6/T6.h" @@ -11,6 +15,8 @@ namespace T6 static const int IPAK_READ_HASH; static const int GLOBAL_HASH; + std::unordered_map> m_asset_loaders_by_type; + static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone); static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone); @@ -22,11 +28,15 @@ namespace T6 static void LoadCommonIPaks(ISearchPath* searchPath, Zone* zone); public: + ObjLoader(); + bool SupportsZone(Zone* zone) const override; void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override; void UnloadContainersOfZone(Zone* zone) const override; void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override; + + bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override; }; } diff --git a/src/ObjLoading/IObjLoader.h b/src/ObjLoading/IObjLoader.h index f55b7969..171c6b4f 100644 --- a/src/ObjLoading/IObjLoader.h +++ b/src/ObjLoading/IObjLoader.h @@ -1,5 +1,6 @@ #pragma once +#include "AssetLoading/AssetLoadingContext.h" #include "SearchPath/ISearchPath.h" #include "Zone/Zone.h" @@ -34,4 +35,6 @@ public: * \param zone The zone of the assets to load the obj data for. */ virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const = 0; + + virtual bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const = 0; }; \ No newline at end of file diff --git a/src/ObjLoading/ObjLoading.cpp b/src/ObjLoading/ObjLoading.cpp index 79ced6b6..853f6338 100644 --- a/src/ObjLoading/ObjLoading.cpp +++ b/src/ObjLoading/ObjLoading.cpp @@ -87,3 +87,16 @@ SearchPaths ObjLoading::GetIWDSearchPaths() return iwdPaths; } + +bool ObjLoading::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) +{ + for (const auto* loader : OBJ_LOADERS) + { + if (loader->SupportsZone(context->m_zone)) + { + return loader->LoadAssetForZone(context, assetType, assetName); + } + } + + return false; +} diff --git a/src/ObjLoading/ObjLoading.h b/src/ObjLoading/ObjLoading.h index 148fa10b..e0735cd2 100644 --- a/src/ObjLoading/ObjLoading.h +++ b/src/ObjLoading/ObjLoading.h @@ -1,5 +1,6 @@ #pragma once +#include "AssetLoading/AssetLoadingContext.h" #include "Zone/Zone.h" #include "SearchPath/ISearchPath.h" #include "SearchPath/SearchPaths.h" @@ -50,4 +51,6 @@ public: * \param zone The zone of the assets to load the obj data for. */ static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone); + + static bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName); }; diff --git a/src/Unlinker/ContentLister/ContentPrinter.cpp b/src/Unlinker/ContentLister/ContentPrinter.cpp index 093e232e..5edfecef 100644 --- a/src/Unlinker/ContentLister/ContentPrinter.cpp +++ b/src/Unlinker/ContentLister/ContentPrinter.cpp @@ -13,7 +13,7 @@ void ContentPrinter::PrintContent() const for(const auto& asset : *pools) { - printf("%s, %s\n", pools->GetAssetTypeName(asset->m_type).c_str(), asset->m_name.c_str()); + printf("%s, %s\n", pools->GetAssetTypeName(asset->m_type), asset->m_name.c_str()); } puts(""); diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp index 875bf1a7..1b1a4932 100644 --- a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.cpp @@ -8,8 +8,7 @@ using namespace IW4; -const std::string GameAssetPoolIW4::ASSET_TYPE_INVALID = "invalid_asset"; -const std::string GameAssetPoolIW4::ASSET_TYPE_NAMES[] +const char* GameAssetPoolIW4::ASSET_TYPE_NAMES[] { "physpreset", "physcollmap", @@ -383,10 +382,15 @@ XAssetInfoGeneric* GameAssetPoolIW4::GetAsset(const asset_type_t type, std::stri #undef CASE_GET_ASSET } -const std::string& GameAssetPoolIW4::GetAssetTypeName(const asset_type_t assetType) const +const char* GameAssetPoolIW4::AssetTypeNameByType(asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent::value)) return ASSET_TYPE_NAMES[assetType]; return ASSET_TYPE_INVALID; } + +const char* GameAssetPoolIW4::GetAssetTypeName(const asset_type_t assetType) const +{ + return AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h index 4d48c66d..1340b2d6 100644 --- a/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h +++ b/src/ZoneCommon/Game/IW4/GameAssetPoolIW4.h @@ -10,8 +10,8 @@ class GameAssetPoolIW4 final : public ZoneAssetPools { int m_priority; - static const std::string ASSET_TYPE_INVALID; - static const std::string ASSET_TYPE_NAMES[]; + static constexpr const char* ASSET_TYPE_INVALID = "invalid_asset_type"; + static const char* ASSET_TYPE_NAMES[]; protected: XAssetInfoGeneric* AddAssetToPool(asset_type_t type, std::string name, void* asset, std::vector& dependencies) override; @@ -60,5 +60,6 @@ public: void InitPoolDynamic(asset_type_t type) override; XAssetInfoGeneric* GetAsset(asset_type_t type, std::string name) const override; - const std::string& GetAssetTypeName(asset_type_t assetType) const override; + static const char* AssetTypeNameByType(asset_type_t assetType); + const char* GetAssetTypeName(asset_type_t assetType) const override; }; diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp index c6c8dd0c..580734d9 100644 --- a/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp +++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp @@ -8,8 +8,7 @@ using namespace T6; -const std::string GameAssetPoolT6::ASSET_TYPE_INVALID = "invalid_asset"; -const std::string GameAssetPoolT6::ASSET_TYPE_NAMES[] +const char* GameAssetPoolT6::ASSET_TYPE_NAMES[] { "xmodelpieces", "physpreset", @@ -478,10 +477,15 @@ XAssetInfoGeneric* GameAssetPoolT6::GetAsset(const asset_type_t type, std::strin #undef CASE_GET_ASSET } -const std::string& GameAssetPoolT6::GetAssetTypeName(const asset_type_t assetType) const +const char* GameAssetPoolT6::AssetTypeNameByType(asset_type_t assetType) { if (assetType >= 0 && assetType < static_cast(std::extent::value)) return ASSET_TYPE_NAMES[assetType]; return ASSET_TYPE_INVALID; } + +const char* GameAssetPoolT6::GetAssetTypeName(const asset_type_t assetType) const +{ + return AssetTypeNameByType(assetType); +} diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.h b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h index c1e196e7..6b8589d9 100644 --- a/src/ZoneCommon/Game/T6/GameAssetPoolT6.h +++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h @@ -8,8 +8,8 @@ class GameAssetPoolT6 final : public ZoneAssetPools { int m_priority; - static const std::string ASSET_TYPE_INVALID; - static const std::string ASSET_TYPE_NAMES[]; + static constexpr const char* ASSET_TYPE_INVALID = "invalid_asset_type"; + static const char* ASSET_TYPE_NAMES[]; protected: XAssetInfoGeneric* AddAssetToPool(asset_type_t type, std::string name, void* asset, std::vector& dependencies) override; @@ -71,5 +71,6 @@ public: void InitPoolDynamic(asset_type_t type) override; XAssetInfoGeneric* GetAsset(asset_type_t type, std::string name) const override; - const std::string& GetAssetTypeName(asset_type_t assetType) const override; + static const char* AssetTypeNameByType(asset_type_t assetType); + const char* GetAssetTypeName(asset_type_t assetType) const override; }; diff --git a/src/ZoneCommon/Pool/GlobalAssetPool.h b/src/ZoneCommon/Pool/GlobalAssetPool.h index 4c085332..ef6f8fe4 100644 --- a/src/ZoneCommon/Pool/GlobalAssetPool.h +++ b/src/ZoneCommon/Pool/GlobalAssetPool.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -25,7 +25,7 @@ class GlobalAssetPool }; static std::vector m_linked_asset_pools; - static std::map m_assets; + static std::unordered_map m_assets; static void SortLinkedAssetPools() { @@ -159,10 +159,19 @@ public: iAssetEntry = m_assets.erase(iAssetEntry); } } + + static XAssetInfo* GetAssetByName(const std::string& name) + { + const auto foundEntry = m_assets.find(name); + if (foundEntry == m_assets.end()) + return nullptr; + + return foundEntry->second.m_asset; + } }; template std::vector::LinkedAssetPool*> GlobalAssetPool::m_linked_asset_pools = std::vector(); template -std::map::GameAssetPoolEntry> GlobalAssetPool::m_assets = std::map(); \ No newline at end of file +std::unordered_map::GameAssetPoolEntry> GlobalAssetPool::m_assets = std::unordered_map(); \ No newline at end of file diff --git a/src/ZoneCommon/Pool/XAssetInfo.h b/src/ZoneCommon/Pool/XAssetInfo.h index d95b3095..a953c19c 100644 --- a/src/ZoneCommon/Pool/XAssetInfo.h +++ b/src/ZoneCommon/Pool/XAssetInfo.h @@ -9,7 +9,7 @@ class Zone; class XAssetInfoGeneric { public: - int m_type = -1; + asset_type_t m_type = -1; std::string m_name; Zone* m_zone; std::vector m_dependencies; diff --git a/src/ZoneCommon/Pool/ZoneAssetPools.h b/src/ZoneCommon/Pool/ZoneAssetPools.h index 0adf74ba..d304f15c 100644 --- a/src/ZoneCommon/Pool/ZoneAssetPools.h +++ b/src/ZoneCommon/Pool/ZoneAssetPools.h @@ -25,7 +25,7 @@ public: XAssetInfoGeneric* AddAsset(asset_type_t type, std::string name, void* asset, std::vector& dependencies); virtual XAssetInfoGeneric* GetAsset(asset_type_t type, std::string name) const = 0; - virtual const std::string& GetAssetTypeName(asset_type_t assetType) const = 0; + virtual const char* GetAssetTypeName(asset_type_t assetType) const = 0; virtual void InitPoolStatic(asset_type_t type, size_t capacity) = 0; virtual void InitPoolDynamic(asset_type_t type) = 0;