chore: fix loading and writing code for IW5

This commit is contained in:
Jan 2024-12-28 21:12:24 +01:00
parent 9ae5aaa1db
commit a36581b06e
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
128 changed files with 1554 additions and 2535 deletions

View File

@ -61,7 +61,7 @@ public:
{
static_assert(std::is_base_of_v<IAssetBase, AssetType>);
return LoadIndirectAssetReferenceInternal(AssetType::EnumEntry, assetName);
return LoadIndirectAssetReferenceGeneric(AssetType::EnumEntry, assetName);
}
IndirectAssetReference LoadIndirectAssetReferenceGeneric(asset_type_t assetType, const std::string& assetName);

View File

@ -1,7 +1,10 @@
#include "AssetCreationResult.h"
#include <cassert>
AssetCreationResult AssetCreationResult::Success(XAssetInfoGeneric* assetInfo)
{
assert(assetInfo);
return AssetCreationResult(true, assetInfo);
}

View File

@ -1,176 +0,0 @@
#include "AssetLoadingManager.h"
#include "Utils/StringUtils.h"
#include <algorithm>
#include <format>
#include <iostream>
AssetLoadingManager::AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& 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;
}
AssetLoadingContext* AssetLoadingManager::GetAssetLoadingContext() const
{
return &m_context;
}
XAssetInfoGeneric* AssetLoadingManager::AddAssetInternal(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
const auto assetType = xAssetInfo->m_type;
const auto* pAssetName = xAssetInfo->m_name.c_str();
m_last_dependency_loaded = m_context.m_zone.m_pools->AddAsset(std::move(xAssetInfo));
if (m_last_dependency_loaded == nullptr)
std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName);
return m_last_dependency_loaded;
}
XAssetInfoGeneric* AssetLoadingManager::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
xAssetInfo->m_zone = &m_context.m_zone;
return AddAssetInternal(std::move(xAssetInfo));
}
XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader)
{
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return alreadyLoadedAsset;
auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone.GetMemory());
if (linkAsset)
{
AddAsset(std::make_unique<XAssetInfoGeneric>(assetType, assetName, linkAsset));
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
auto* existingAsset = loader->LoadFromGlobalAssetPools(assetName);
if (existingAsset)
{
AddAssetInternal(std::make_unique<XAssetInfoGeneric>(*existingAsset));
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, *m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return nullptr;
}
XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader)
{
if (loader->CanLoadFromGdt() && !m_context.m_gdt_files.empty()
&& loader->LoadFromGdt(assetName, &m_context, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
{
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, &m_context.m_raw_search_path, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
{
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
auto* existingAsset = loader->LoadFromGlobalAssetPools(assetName);
if (!existingAsset && !assetName.empty() && assetName[0] != ',')
existingAsset = loader->LoadFromGlobalAssetPools(',' + assetName);
if (existingAsset)
{
std::vector<XAssetInfoGeneric*> dependencies;
std::vector<IndirectAssetReference> indirectAssetReferences;
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;
}
indirectAssetReferences.reserve(existingAsset->m_indirect_asset_references.size());
for (const auto& indirectAssetReference : existingAsset->m_indirect_asset_references)
indirectAssetReferences.emplace_back(LoadIndirectAssetReference(indirectAssetReference.m_type, indirectAssetReference.m_name));
// Make sure any used script string is available in the created zone
// The replacement of the scr_string_t values will be done upon writing
for (const auto scrString : existingAsset->m_used_script_strings)
m_context.m_zone.m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString));
AddAssetInternal(std::make_unique<XAssetInfoGeneric>(existingAsset->m_type,
existingAsset->m_name,
existingAsset->m_ptr,
std::move(dependencies),
existingAsset->m_used_script_strings,
std::move(indirectAssetReferences),
existingAsset->m_zone));
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName);
return nullptr;
}
XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName)
{
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return alreadyLoadedAsset;
const auto loader = m_asset_loaders_by_type.find(assetType);
if (loader != m_asset_loaders_by_type.end())
{
const auto ignoreEntry = m_context.m_ignored_asset_map.find(assetName);
if (ignoreEntry != m_context.m_ignored_asset_map.end() && ignoreEntry->second == assetType)
{
const auto linkAssetName = std::format(",{}", assetName);
return LoadIgnoredDependency(assetType, linkAssetName, loader->second.get());
}
return LoadAssetDependency(assetType, assetName, loader->second.get());
}
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return nullptr;
}
IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName)
{
const auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return IndirectAssetReference(assetType, assetName);
const auto ignoreEntry = m_context.m_ignored_asset_map.find(assetName);
if (ignoreEntry != m_context.m_ignored_asset_map.end() && ignoreEntry->second == assetType)
return IndirectAssetReference(assetType, assetName);
const auto loader = m_asset_loaders_by_type.find(assetType);
if (loader != m_asset_loaders_by_type.end())
{
LoadAssetDependency(assetType, assetName, loader->second.get());
return IndirectAssetReference(assetType, assetName);
}
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return IndirectAssetReference(assetType, assetName);
}

View File

@ -1,31 +0,0 @@
#pragma once
#include "AssetLoadingContext.h"
#include "IAssetLoader.h"
#include "IAssetLoadingManager.h"
#include <unordered_map>
class AssetLoadingManager final : public IAssetLoadingManager
{
public:
AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context);
bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName);
[[nodiscard]] AssetLoadingContext* GetAssetLoadingContext() const override;
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo) override;
XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) override;
IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) override;
private:
XAssetInfoGeneric* LoadIgnoredDependency(asset_type_t assetType, const std::string& assetName, IAssetLoader* loader);
XAssetInfoGeneric* LoadAssetDependency(asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader);
XAssetInfoGeneric* AddAssetInternal(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& m_asset_loaders_by_type;
AssetLoadingContext& m_context;
XAssetInfoGeneric* m_last_dependency_loaded;
};

View File

@ -1,17 +0,0 @@
#include "AssetLoaderAddonMapEnts.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* addonMapEnts = memory->Create<AddonMapEnts>();
memset(addonMapEnts, 0, sizeof(AddonMapEnts));
addonMapEnts->name = memory->Dup(assetName.c_str());
return addonMapEnts;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderAddonMapEnts final : public BasicAssetLoader<AssetAddonMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderClipMap.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderClipMap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* clipMap = memory->Create<clipMap_t>();
memset(clipMap, 0, sizeof(clipMap_t));
clipMap->name = memory->Dup(assetName.c_str());
return clipMap;
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderClipMap : public BasicAssetLoader<AssetClipMap>
{
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderComWorld.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* comWorld = memory->Create<ComWorld>();
memset(comWorld, 0, sizeof(ComWorld));
comWorld->name = memory->Dup(assetName.c_str());
return comWorld;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderComWorld final : public BasicAssetLoader<AssetComWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFont.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* font = memory->Create<Font_s>();
memset(font, 0, sizeof(Font_s));
font->fontName = memory->Dup(assetName.c_str());
return font;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderFont final : public BasicAssetLoader<AssetFont>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFx.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* fx = memory->Create<FxEffectDef>();
memset(fx, 0, sizeof(FxEffectDef));
fx->name = memory->Dup(assetName.c_str());
return fx;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderFx final : public BasicAssetLoader<AssetFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFxImpactTable.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderFxImpactTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* fxImpactTable = memory->Create<FxImpactTable>();
memset(fxImpactTable, 0, sizeof(FxImpactTable));
fxImpactTable->name = memory->Dup(assetName.c_str());
return fxImpactTable;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderFxImpactTable final : public BasicAssetLoader<AssetImpactFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFxWorld.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderFxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* fxWorld = memory->Create<FxWorld>();
memset(fxWorld, 0, sizeof(FxWorld));
fxWorld->name = memory->Dup(assetName.c_str());
return fxWorld;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderFxWorld final : public BasicAssetLoader<AssetFxWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,60 +0,0 @@
#include "AssetLoaderGfxImage.h"
#include "Game/IW5/IW5.h"
#include "Image/IwiLoader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
#include <sstream>
using namespace IW5;
void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetImage::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderGfxImage::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderGfxImage::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = std::format("images/{}.iwi", assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
const auto fileSize = static_cast<size_t>(file.m_length);
const auto fileData = std::make_unique<char[]>(fileSize);
file.m_stream->read(fileData.get(), fileSize);
std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
return false;
}
auto* image = memory->Create<GfxImage>();
memset(image, 0, sizeof(GfxImage));
image->name = memory->Dup(assetName.c_str());
image->noPicmip = !texture->HasMipMaps();
image->width = static_cast<uint16_t>(texture->GetWidth());
image->height = static_cast<uint16_t>(texture->GetHeight());
image->depth = static_cast<uint16_t>(texture->GetDepth());
image->texture.loadDef = memory->Alloc<GfxImageLoadDef>();
manager->AddAsset<AssetImage>(assetName, image);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderGfxImage final : public BasicAssetLoader<AssetImage>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderGfxLightDef.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* lightDef = memory->Create<GfxLightDef>();
memset(lightDef, 0, sizeof(GfxLightDef));
lightDef->name = memory->Dup(assetName.c_str());
return lightDef;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderGfxLightDef final : public BasicAssetLoader<AssetLightDef>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderGfxWorld.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* gfxWorld = memory->Create<GfxWorld>();
memset(gfxWorld, 0, sizeof(GfxWorld));
gfxWorld->name = memory->Dup(assetName.c_str());
return gfxWorld;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderGfxWorld final : public BasicAssetLoader<AssetGfxWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderGlassWorld.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderGlassWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* glassWorld = memory->Create<GlassWorld>();
memset(glassWorld, 0, sizeof(GlassWorld));
glassWorld->name = memory->Dup(assetName.c_str());
return glassWorld;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderGlassWorld final : public BasicAssetLoader<AssetGlassWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,43 +0,0 @@
#include "AssetLoaderLeaderboard.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* leaderboard = memory->Create<LeaderboardDef>();
memset(leaderboard, 0, sizeof(LeaderboardDef));
leaderboard->name = memory->Dup(assetName.c_str());
return leaderboard;
}
bool AssetLoaderLeaderboard::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderLeaderboard::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* leaderboardDef = memory->Alloc<LeaderboardDef>();
leaderboardDef->name = memory->Dup(assetName.c_str());
if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory))
manager->AddAsset<AssetLeaderboard>(assetName, leaderboardDef);
else
std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderLeaderboard final : public BasicAssetLoader<AssetLeaderboard>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderLoadedSound.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderLoadedSound::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* loadedSound = memory->Create<LoadedSound>();
memset(loadedSound, 0, sizeof(LoadedSound));
loadedSound->name = memory->Dup(assetName.c_str());
return loadedSound;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderLoadedSound final : public BasicAssetLoader<AssetLoadedSound>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderMapEnts.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* mapEnts = memory->Create<MapEnts>();
memset(mapEnts, 0, sizeof(MapEnts));
mapEnts->name = memory->Dup(assetName.c_str());
return mapEnts;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderMapEnts final : public BasicAssetLoader<AssetMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,57 +0,0 @@
#include "AssetLoaderMaterial.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/Material/JsonMaterialLoader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetMaterial::Type>();
asset->info.name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderMaterial::CanLoadFromRaw() const
{
return true;
}
std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName)
{
std::string sanitizedFileName(assetName);
if (sanitizedFileName[0] == '*')
{
std::ranges::replace(sanitizedFileName, '*', '_');
const auto parenthesisPos = sanitizedFileName.find('(');
if (parenthesisPos != std::string::npos)
sanitizedFileName.erase(parenthesisPos);
sanitizedFileName = "generated/" + sanitizedFileName;
}
return std::format("materials/{}.json", sanitizedFileName);
}
bool AssetLoaderMaterial::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(GetFileNameForAsset(assetName));
if (!file.IsOpen())
return false;
auto* material = memory->Alloc<Material>();
material->info.name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies))
manager->AddAsset<AssetMaterial>(assetName, material, std::move(dependencies));
else
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderMaterial final : public BasicAssetLoader<AssetMaterial>
{
static std::string GetFileNameForAsset(const std::string& assetName);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderMenuDef.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderMenuDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* menu = memory->Create<menuDef_t>();
memset(menu, 0, sizeof(menuDef_t));
menu->window.name = memory->Dup(assetName.c_str());
return menu;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderMenuDef final : public BasicAssetLoader<AssetMenu>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,233 +0,0 @@
#include "AssetLoaderMenuList.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/Menu/MenuConversionZoneStateIW5.h"
#include "Game/IW5/Menu/MenuConverterIW5.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <iostream>
using namespace IW5;
namespace IW5
{
class MenuLoader
{
public:
static bool ProcessParsedResults(const std::string& fileName,
ISearchPath* searchPath,
MemoryManager* memory,
IAssetLoadingManager* manager,
menu::ParsingResult* parsingResult,
menu::MenuAssetZoneState* zoneState,
MenuConversionZoneState* conversionState,
std::vector<menuDef_t*>& menus,
std::vector<XAssetInfoGeneric*>& menuListDependencies)
{
const auto menuCount = parsingResult->m_menus.size();
const auto functionCount = parsingResult->m_functions.size();
const auto menuLoadCount = parsingResult->m_menus_to_load.size();
auto totalItemCount = 0u;
for (const auto& menu : parsingResult->m_menus)
totalItemCount += menu->m_items.size();
std::cout << "Successfully read menu file \"" << fileName << "\" (" << menuLoadCount << " loads, " << menuCount << " menus, " << functionCount
<< " functions, " << totalItemCount << " items)\n";
// Add all functions to the zone state to make them available for all menus to be converted
for (auto& function : parsingResult->m_functions)
zoneState->AddFunction(std::move(function));
// Prepare a list of all menus of this file
std::vector<XAssetInfo<menuDef_t>*> allMenusOfFile;
allMenusOfFile.reserve(parsingResult->m_menus.size());
// Convert all menus and add them as assets
for (auto& menu : parsingResult->m_menus)
{
MenuConverter converter(ObjLoading::Configuration.MenuNoOptimization, searchPath, memory, manager);
auto* menuAsset = converter.ConvertMenu(*menu);
if (menuAsset == nullptr)
{
std::cout << "Failed to convert menu file \"" << menu->m_name << "\"\n";
return false;
}
menus.push_back(menuAsset);
auto* menuAssetInfo = manager->AddAsset<AssetMenu>(menu->m_name, menuAsset, std::move(converter.GetDependencies()));
if (menuAssetInfo)
{
allMenusOfFile.push_back(menuAssetInfo);
menuListDependencies.push_back(menuAssetInfo);
}
zoneState->AddMenu(std::move(menu));
}
// Register this file with all loaded menus
conversionState->AddLoadedFile(fileName, std::move(allMenusOfFile));
return true;
}
static MenuList* CreateMenuListAsset(const std::string& assetName, MemoryManager* memory, const std::vector<menuDef_t*>& menus)
{
auto* menuListAsset = memory->Create<MenuList>();
menuListAsset->name = memory->Dup(assetName.c_str());
menuListAsset->menuCount = static_cast<int>(menus.size());
if (menuListAsset->menuCount > 0)
{
menuListAsset->menus = memory->Alloc<menuDef_t*>(menuListAsset->menuCount);
for (auto i = 0; i < menuListAsset->menuCount; i++)
menuListAsset->menus[i] = menus[i];
}
else
menuListAsset->menus = nullptr;
return menuListAsset;
}
static std::unique_ptr<menu::ParsingResult>
ParseMenuFile(const std::string& menuFileName, ISearchPath* searchPath, const menu::MenuAssetZoneState* zoneState)
{
const auto file = searchPath->Open(menuFileName);
if (!file.IsOpen())
return nullptr;
menu::MenuFileReader reader(*file.m_stream,
menuFileName,
menu::FeatureLevel::IW5,
[searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr<std::istream>
{
auto foundFileToInclude = searchPath->Open(filename);
if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream)
return nullptr;
return std::move(foundFileToInclude.m_stream);
});
reader.IncludeZoneState(zoneState);
reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing);
return reader.ReadMenuFile();
}
};
} // namespace IW5
void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* menuList = memory->Create<MenuList>();
memset(menuList, 0, sizeof(MenuList));
menuList->name = memory->Dup(assetName.c_str());
return menuList;
}
bool AssetLoaderMenuList::CanLoadFromRaw() const
{
return true;
}
bool BuildMenuFileQueue(std::deque<std::string>& menuLoadQueue,
const std::string& menuListAssetName,
ISearchPath* searchPath,
MemoryManager* memory,
IAssetLoadingManager* manager,
menu::MenuAssetZoneState* zoneState,
MenuConversionZoneState* conversionState,
std::vector<menuDef_t*>& menus,
std::vector<XAssetInfoGeneric*>& menuListDependencies)
{
const auto alreadyLoadedMenuListFileMenus = conversionState->m_menus_by_filename.find(menuListAssetName);
if (alreadyLoadedMenuListFileMenus == conversionState->m_menus_by_filename.end())
{
const auto menuListResult = MenuLoader::ParseMenuFile(menuListAssetName, searchPath, zoneState);
if (menuListResult)
{
MenuLoader::ProcessParsedResults(
menuListAssetName, searchPath, memory, manager, menuListResult.get(), zoneState, conversionState, menus, menuListDependencies);
for (const auto& menuToLoad : menuListResult->m_menus_to_load)
menuLoadQueue.push_back(menuToLoad);
zoneState->AddMenusToLoad(menuListAssetName, std::move(menuListResult->m_menus_to_load));
}
else
return false;
}
return true;
}
void LoadMenuFileFromQueue(const std::string& menuFilePath,
ISearchPath* searchPath,
MemoryManager* memory,
IAssetLoadingManager* manager,
menu::MenuAssetZoneState* zoneState,
MenuConversionZoneState* conversionState,
std::vector<menuDef_t*>& menus,
std::vector<XAssetInfoGeneric*>& menuListDependencies)
{
const auto alreadyLoadedMenuFile = conversionState->m_menus_by_filename.find(menuFilePath);
if (alreadyLoadedMenuFile != conversionState->m_menus_by_filename.end())
{
std::cout << "Already loaded \"" << menuFilePath << "\", skipping\n";
for (auto* menu : alreadyLoadedMenuFile->second)
{
menus.push_back(menu->Asset());
menuListDependencies.push_back(menu);
}
return;
}
const auto menuFileResult = MenuLoader::ParseMenuFile(menuFilePath, searchPath, zoneState);
if (menuFileResult)
{
MenuLoader::ProcessParsedResults(
menuFilePath, searchPath, memory, manager, menuFileResult.get(), zoneState, conversionState, menus, menuListDependencies);
if (!menuFileResult->m_menus_to_load.empty())
std::cout << "WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"" << menuFilePath << "\"\n";
}
else
std::cerr << "Could not read menu file \"" << menuFilePath << "\"\n";
}
bool AssetLoaderMenuList::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
std::vector<menuDef_t*> menus;
std::vector<XAssetInfoGeneric*> menuListDependencies;
auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<menu::MenuAssetZoneState>();
auto* conversionState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuConversionZoneState>();
std::deque<std::string> menuLoadQueue;
if (!BuildMenuFileQueue(menuLoadQueue, assetName, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies))
return false;
while (!menuLoadQueue.empty())
{
const auto& menuFileToLoad = menuLoadQueue.front();
LoadMenuFileFromQueue(menuFileToLoad, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies);
menuLoadQueue.pop_front();
}
auto* menuListAsset = MenuLoader::CreateMenuListAsset(assetName, memory, menus);
if (menuListAsset)
manager->AddAsset<AssetMenuList>(assetName, menuListAsset, menuListDependencies);
return true;
}
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderMenuList final : public BasicAssetLoader<AssetMenuList>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderPathData.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderPathData::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* pathData = memory->Create<PathData>();
memset(pathData, 0, sizeof(PathData));
pathData->name = memory->Dup(assetName.c_str());
return pathData;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderPathData final : public BasicAssetLoader<AssetPathData>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderPhysCollmap.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderPhysCollmap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* collmap = memory->Create<PhysCollmap>();
memset(collmap, 0, sizeof(PhysCollmap));
collmap->name = memory->Dup(assetName.c_str());
return collmap;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderPhysCollmap final : public BasicAssetLoader<AssetPhysCollMap>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderPhysPreset.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* physPreset = memory->Create<PhysPreset>();
memset(physPreset, 0, sizeof(PhysPreset));
physPreset->name = memory->Dup(assetName.c_str());
return physPreset;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderPhysPreset final : public BasicAssetLoader<AssetPhysPreset>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderPixelShader.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderPixelShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* pixelShader = memory->Create<MaterialPixelShader>();
memset(pixelShader, 0, sizeof(MaterialPixelShader));
pixelShader->name = memory->Dup(assetName.c_str());
return pixelShader;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderPixelShader final : public BasicAssetLoader<AssetPixelShader>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,80 +0,0 @@
#include "AssetLoaderRawFile.h"
#include "Game/IW5/IW5.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <filesystem>
#include <iostream>
#include <zlib.h>
using namespace IW5;
void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* rawFile = memory->Create<RawFile>();
memset(rawFile, 0, sizeof(RawFile));
rawFile->name = memory->Dup(assetName.c_str());
return rawFile;
}
bool AssetLoaderRawFile::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderRawFile::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
const auto uncompressedBuffer = std::make_unique<char[]>(static_cast<size_t>(file.m_length));
file.m_stream->read(uncompressedBuffer.get(), file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
const auto compressionBufferSize = static_cast<size_t>(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING);
auto* compressedBuffer = memory->Alloc<char>(compressionBufferSize);
z_stream_s zs{};
zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.avail_in = static_cast<uInt>(file.m_length);
zs.avail_out = compressionBufferSize;
zs.next_in = reinterpret_cast<const Bytef*>(uncompressedBuffer.get());
zs.next_out = reinterpret_cast<Bytef*>(compressedBuffer);
int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
{
throw std::runtime_error("Initializing deflate failed");
}
ret = deflate(&zs, Z_FINISH);
if (ret != Z_STREAM_END)
{
std::cerr << "Deflate failed for loading rawfile \"" << assetName << "\"\n";
deflateEnd(&zs);
return false;
}
const auto compressedSize = compressionBufferSize - zs.avail_out;
auto* rawFile = memory->Create<RawFile>();
rawFile->name = memory->Dup(assetName.c_str());
rawFile->compressedLen = static_cast<int>(compressedSize);
rawFile->len = static_cast<int>(file.m_length);
rawFile->buffer = static_cast<const char*>(compressedBuffer);
deflateEnd(&zs);
manager->AddAsset<AssetRawFile>(assetName, rawFile);
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderRawFile final : public BasicAssetLoader<AssetRawFile>
{
static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64;
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,78 +0,0 @@
#include "AssetLoaderScriptFile.h"
#include "Game/IW5/IW5.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <filesystem>
#include <iostream>
using namespace IW5;
void* AssetLoaderScriptFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* scriptFile = memory->Create<ScriptFile>();
memset(scriptFile, 0, sizeof(ScriptFile));
scriptFile->name = memory->Dup(assetName.c_str());
return scriptFile;
}
bool AssetLoaderScriptFile::CanLoadFromRaw() const
{
return true;
}
// See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format
bool AssetLoaderScriptFile::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName + ".gscbin");
if (!file.IsOpen())
return false;
const auto fileBuffer = std::make_unique<char[]>(static_cast<size_t>(file.m_length));
file.m_stream->read(fileBuffer.get(), file.m_length);
if (file.m_stream->gcount() != file.m_length)
return false;
auto* scriptFile = memory->Create<ScriptFile>();
scriptFile->name = memory->Dup(assetName.c_str());
// Retrieve data from the buffer
size_t offset = 0;
// Read past the name pointer, we will use the one from assetName
offset += strlen(fileBuffer.get()) + 1;
memcpy(&scriptFile->compressedLen, fileBuffer.get() + offset, sizeof(scriptFile->compressedLen));
offset += sizeof(scriptFile->compressedLen);
memcpy(&scriptFile->len, fileBuffer.get() + offset, sizeof(scriptFile->len));
offset += sizeof(scriptFile->len);
memcpy(&scriptFile->bytecodeLen, fileBuffer.get() + offset, sizeof(scriptFile->bytecodeLen));
offset += sizeof(scriptFile->bytecodeLen);
if (scriptFile->compressedLen <= 0 || scriptFile->bytecodeLen <= 0)
{
std::cerr << "Error: Invalid length of the buffers in " << assetName << " specified\n";
return false;
}
if (offset + (scriptFile->compressedLen + scriptFile->bytecodeLen) > file.m_length)
{
std::cerr << "Error: Specified length in " << assetName << " GSC BIN structure exceeds the actual file size\n";
return false;
}
scriptFile->buffer = memory->Alloc<char>(scriptFile->compressedLen);
memcpy(const_cast<char*>(scriptFile->buffer), fileBuffer.get() + offset, scriptFile->compressedLen);
offset += scriptFile->compressedLen;
scriptFile->bytecode = memory->Alloc<unsigned char>(scriptFile->bytecodeLen);
memcpy(scriptFile->bytecode, fileBuffer.get() + offset, scriptFile->bytecodeLen);
manager->AddAsset<AssetScript>(assetName, scriptFile);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderScriptFile final : public BasicAssetLoader<AssetScript>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderSoundAliasList.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderSoundAliasList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* sndAliasList = memory->Create<snd_alias_list_t>();
memset(sndAliasList, 0, sizeof(snd_alias_list_t));
sndAliasList->aliasName = memory->Dup(assetName.c_str());
return sndAliasList;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderSoundAliasList final : public BasicAssetLoader<AssetSound>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderSoundCurve.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderSoundCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* sndCurve = memory->Create<SndCurve>();
memset(sndCurve, 0, sizeof(SndCurve));
sndCurve->filename = memory->Dup(assetName.c_str());
return sndCurve;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderSoundCurve final : public BasicAssetLoader<AssetSoundCurve>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,40 +0,0 @@
#include "AssetLoaderStringTable.h"
#include "Csv/CsvStream.h"
#include "Game/IW5/CommonIW5.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include "StringTable/StringTableLoader.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* stringTable = memory->Create<StringTable>();
memset(stringTable, 0, sizeof(StringTable));
stringTable->name = memory->Dup(assetName.c_str());
return stringTable;
}
bool AssetLoaderStringTable::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderStringTable::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(assetName);
if (!file.IsOpen())
return false;
string_table::StringTableLoaderV2<StringTable, Common::StringTable_HashString> loader;
auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream);
manager->AddAsset<AssetStringTable>(assetName, stringTable);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderStringTable final : public BasicAssetLoader<AssetStringTable>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderStructuredDataDef.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderStructuredDataDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* structuredDataDefSet = memory->Create<StructuredDataDefSet>();
memset(structuredDataDefSet, 0, sizeof(StructuredDataDefSet));
structuredDataDefSet->name = memory->Dup(assetName.c_str());
return structuredDataDefSet;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderStructuredDataDef final : public BasicAssetLoader<AssetStructuredDataDef>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderSurfaceFxTable.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderSurfaceFxTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* surfaceFxTable = memory->Create<SurfaceFxTable>();
memset(surfaceFxTable, 0, sizeof(SurfaceFxTable));
surfaceFxTable->name = memory->Dup(assetName.c_str());
return surfaceFxTable;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderSurfaceFxTable final : public BasicAssetLoader<AssetSurfaceFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderTechniqueSet.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* techniqueSet = memory->Create<MaterialTechniqueSet>();
memset(techniqueSet, 0, sizeof(MaterialTechniqueSet));
techniqueSet->name = memory->Dup(assetName.c_str());
return techniqueSet;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderTechniqueSet final : public BasicAssetLoader<AssetTechniqueSet>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderTracerDef.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderTracerDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* tracerDef = memory->Create<TracerDef>();
memset(tracerDef, 0, sizeof(TracerDef));
tracerDef->name = memory->Dup(assetName.c_str());
return tracerDef;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderTracerDef final : public BasicAssetLoader<AssetTracer>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderVehicleDef.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderVehicleDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* vehicleDef = memory->Create<VehicleDef>();
memset(vehicleDef, 0, sizeof(VehicleDef));
vehicleDef->name = memory->Dup(assetName.c_str());
return vehicleDef;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderVehicleDef final : public BasicAssetLoader<AssetVehicle>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderVehicleTrack.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderVehicleTrack::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* vehicleTrack = memory->Create<VehicleTrack>();
memset(vehicleTrack, 0, sizeof(VehicleTrack));
vehicleTrack->name = memory->Dup(assetName.c_str());
return vehicleTrack;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderVehicleTrack final : public BasicAssetLoader<AssetVehicleTrack>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderVertexDecl.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderVertexDecl::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* vertexDecl = memory->Create<MaterialVertexDeclaration>();
memset(vertexDecl, 0, sizeof(MaterialVertexDeclaration));
vertexDecl->name = memory->Dup(assetName.c_str());
return vertexDecl;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderVertexDecl final : public BasicAssetLoader<AssetVertexDecl>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderVertexShader.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderVertexShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* vertexShader = memory->Create<MaterialVertexShader>();
memset(vertexShader, 0, sizeof(MaterialVertexShader));
vertexShader->name = memory->Dup(assetName.c_str());
return vertexShader;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderVertexShader final : public BasicAssetLoader<AssetVertexShader>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,20 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderWeapon final : public BasicAssetLoader<AssetWeapon>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromGdt() const override;
bool LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,45 +0,0 @@
#include "AssetLoaderWeaponAttachment.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/Weapon/JsonWeaponAttachmentLoader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
void* AssetLoaderWeaponAttachment::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* attachment = memory->Create<WeaponAttachment>();
memset(attachment, 0, sizeof(WeaponAttachment));
attachment->szInternalName = memory->Dup(assetName.c_str());
return attachment;
}
bool AssetLoaderWeaponAttachment::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderWeaponAttachment::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("attachment/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* attachment = memory->Alloc<WeaponAttachment>();
attachment->szInternalName = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
std::vector<IndirectAssetReference> indirectAssetReferences;
if (LoadWeaponAttachmentAsJson(*file.m_stream, *attachment, memory, manager, dependencies, indirectAssetReferences))
manager->AddAsset<AssetAttachment>(assetName, attachment, std::move(dependencies), std::vector<scr_string_t>(), std::move(indirectAssetReferences));
else
std::cerr << "Failed to load attachment \"" << assetName << "\"\n";
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderWeaponAttachment final : public BasicAssetLoader<AssetAttachment>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderXAnim.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* anim = memory->Create<XAnimParts>();
memset(anim, 0, sizeof(XAnimParts));
anim->name = memory->Dup(assetName.c_str());
return anim;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderXAnim final : public BasicAssetLoader<AssetXAnim>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -1,47 +0,0 @@
#include "AssetLoaderXModel.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/XModel/XModelLoaderIW5.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* asset = memory->Alloc<AssetXModel::Type>();
asset->name = memory->Dup(assetName.c_str());
return asset;
}
bool AssetLoaderXModel::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderXModel::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName));
if (!file.IsOpen())
return false;
auto* xmodel = memory->Alloc<XModel>();
xmodel->name = memory->Dup(assetName.c_str());
std::vector<XAssetInfoGeneric*> dependencies;
if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies))
{
manager->AddAsset<AssetXModel>(assetName, xmodel, std::move(dependencies));
}
else
{
std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
return false;
}
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderXModel final : public BasicAssetLoader<AssetXModel>
{
static std::string GetFileNameForAsset(const std::string& assetName);
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW5

View File

@ -1,17 +0,0 @@
#include "AssetLoaderXModelSurfs.h"
#include "Game/IW5/IW5.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW5;
void* AssetLoaderXModelSurfs::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* modelSurfs = memory->Create<XModelSurfs>();
memset(modelSurfs, 0, sizeof(XModelSurfs));
modelSurfs->name = memory->Dup(assetName.c_str());
return modelSurfs;
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
namespace IW5
{
class AssetLoaderXModelSurfs final : public BasicAssetLoader<AssetXModelSurfs>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW5

View File

@ -0,0 +1,69 @@
#include "LoaderImageIW5.h"
#include "Game/IW5/IW5.h"
#include "Image/IwiLoader.h"
#include <cstring>
#include <format>
#include <iostream>
#include <sstream>
using namespace IW5;
namespace
{
constexpr auto MAX_IMAGE_NAME_SIZE = 0x800;
class ImageLoader final : public AssetCreator<AssetImage>
{
public:
ImageLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto fileName = std::format("images/{}.iwi", assetName);
const auto file = m_search_path.Open(fileName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
const auto fileSize = static_cast<size_t>(file.m_length);
const auto fileData = std::make_unique<char[]>(fileSize);
file.m_stream->read(fileData.get(), fileSize);
std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
return AssetCreationResult::Failure();
}
auto* image = m_memory.Alloc<GfxImage>();
image->name = m_memory.Dup(assetName.c_str());
image->noPicmip = !texture->HasMipMaps();
image->width = static_cast<uint16_t>(texture->GetWidth());
image->height = static_cast<uint16_t>(texture->GetHeight());
image->depth = static_cast<uint16_t>(texture->GetDepth());
image->texture.loadDef = m_memory.Alloc<GfxImageLoadDef>();
return AssetCreationResult::Success(context.AddAsset<AssetImage>(assetName, image));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW5
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<ImageLoader>(memory, searchPath);
}
} // namespace IW5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace IW5
{
std::unique_ptr<AssetCreator<AssetImage>> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5

View File

@ -1,6 +1,7 @@
#include "InfoStringToStructConverter.h"
#include <cassert>
#include <format>
#include <iostream>
using namespace IW5;
@ -8,12 +9,12 @@ using namespace IW5;
InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString,
void* structure,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
MemoryManager& memory,
AssetCreationContext& context,
GenericAssetRegistration& registration,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory),
m_loading_manager(manager),
: InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory, context, registration),
m_fields(fields),
m_field_count(fieldCount)
{
@ -58,15 +59,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* fx = m_loading_manager->LoadDependency<AssetFx>(value);
auto* fx = m_context.LoadDependency<AssetFx>(value);
if (fx == nullptr)
{
std::cout << "Failed to load fx asset \"" << value << "\"\n";
std::cerr << std::format("Failed to load fx asset \"{}\"\n", value);
return false;
}
m_dependencies.emplace(fx);
m_registration.AddDependency(fx);
*reinterpret_cast<FxEffectDef**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = fx->Asset();
return true;
@ -80,15 +81,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* xmodel = m_loading_manager->LoadDependency<AssetXModel>(value);
auto* xmodel = m_context.LoadDependency<AssetXModel>(value);
if (xmodel == nullptr)
{
std::cout << "Failed to load xmodel asset \"" << value << "\"\n";
std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value);
return false;
}
m_dependencies.emplace(xmodel);
m_registration.AddDependency(xmodel);
*reinterpret_cast<XModel**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = xmodel->Asset();
return true;
@ -102,15 +103,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* material = m_loading_manager->LoadDependency<AssetMaterial>(value);
auto* material = m_context.LoadDependency<AssetMaterial>(value);
if (material == nullptr)
{
std::cout << "Failed to load material asset \"" << value << "\"\n";
std::cerr << std::format("Failed to load material asset \"{}\"\n", value);
return false;
}
m_dependencies.emplace(material);
m_registration.AddDependency(material);
*reinterpret_cast<Material**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = material->Asset();
return true;
@ -124,15 +125,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* tracer = m_loading_manager->LoadDependency<AssetTracer>(value);
auto* tracer = m_context.LoadDependency<AssetTracer>(value);
if (tracer == nullptr)
{
std::cout << "Failed to load tracer asset \"" << value << "\"\n";
std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value);
return false;
}
m_dependencies.emplace(tracer);
m_registration.AddDependency(tracer);
*reinterpret_cast<TracerDef**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = tracer->Asset();
return true;
@ -160,15 +161,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* collmap = m_loading_manager->LoadDependency<AssetPhysCollMap>(value);
auto* collmap = m_context.LoadDependency<AssetPhysCollMap>(value);
if (collmap == nullptr)
{
std::cout << "Failed to load collmap asset \"" << value << "\"\n";
std::cerr << std::format("Failed to load collmap asset \"{}\"\n", value);
return false;
}
m_dependencies.emplace(collmap);
m_registration.AddDependency(collmap);
*reinterpret_cast<PhysCollmap**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = collmap->Asset();
return true;
@ -182,12 +183,12 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
return true;
}
auto* name = m_memory->Alloc<snd_alias_list_name>();
name->soundName = m_memory->Dup(value.c_str());
auto* name = m_memory.Alloc<snd_alias_list_name>();
name->soundName = m_memory.Dup(value.c_str());
reinterpret_cast<SndAliasCustom*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset)->name = name;
m_indirect_asset_references.emplace(ASSET_TYPE_SOUND, value);
m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference<AssetSound>(value));
return true;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "Game/IW5/IW5.h"
#include "InfoString/InfoStringToStructConverterBase.h"
@ -7,24 +8,22 @@ namespace IW5
{
class InfoStringToStructConverter : public InfoStringToStructConverterBase
{
protected:
IAssetLoadingManager* m_loading_manager;
const cspField_t* m_fields;
size_t m_field_count;
static bool GetHashValue(const std::string& value, unsigned int& hash);
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
bool ConvertBaseField(const cspField_t& field, const std::string& value);
public:
InfoStringToStructConverter(const InfoString& infoString,
void* structure,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
MemoryManager& memory,
AssetCreationContext& context,
GenericAssetRegistration& registration,
const cspField_t* fields,
size_t fieldCount);
bool Convert() override;
protected:
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
bool ConvertBaseField(const cspField_t& field, const std::string& value);
const cspField_t* m_fields;
size_t m_field_count;
};
} // namespace IW5

View File

@ -122,9 +122,9 @@ namespace
namespace IW5
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory)
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory)
{
const JsonLoader loader(stream, *memory);
const JsonLoader loader(stream, memory);
return loader.Load(leaderboard);
}

View File

@ -7,5 +7,5 @@
namespace IW5
{
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory);
bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory);
} // namespace IW5

View File

@ -0,0 +1,53 @@
#include "LoaderLeaderboardIW5.h"
#include "Game/IW5/IW5.h"
#include "JsonLeaderboardDefLoader.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
namespace
{
class LeaderboardLoader final : public AssetCreator<AssetLeaderboard>
{
public:
LeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* leaderboardDef = m_memory.Alloc<LeaderboardDef>();
leaderboardDef->name = m_memory.Dup(assetName.c_str());
if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, m_memory))
{
std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset<AssetLeaderboard>(assetName, leaderboardDef));
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW5
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LeaderboardLoader>(memory, searchPath);
}
} // namespace IW5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace IW5
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5

View File

@ -1,23 +0,0 @@
#include "AssetLoaderLocalizeIW5.h"
using namespace IW5;
AssetLoaderLocalize::AssetLoaderLocalize(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: CommonLocalizeLoader(searchPath, zone),
m_memory(memory)
{
}
AssetCreationResult AssetLoaderLocalize::CreateAsset(const std::string& assetName, AssetCreationContext& context)
{
return CreateLocalizeAsset(assetName, context);
}
AssetCreationResult AssetLoaderLocalize::CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context)
{
auto* asset = m_memory.Alloc<LocalizeEntry>();
asset->name = m_memory.Dup(localizeEntry.m_key.c_str());
asset->value = m_memory.Dup(localizeEntry.m_value.c_str());
return AssetCreationResult::Success(context.AddAsset<AssetLocalize>(localizeEntry.m_key, asset));
}

View File

@ -1,25 +0,0 @@
#pragma once
#include "Asset/AssetCreationContext.h"
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "Localize/CommonLocalizeLoader.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
namespace IW5
{
class AssetLoaderLocalize final : public AssetCreator<AssetLocalize>, public CommonLocalizeLoader
{
public:
AssetLoaderLocalize(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override;
protected:
AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override;
private:
MemoryManager& m_memory;
};
} // namespace IW5

View File

@ -0,0 +1,44 @@
#include "LoaderLocalizeIW5.h"
#include "Localize/CommonLocalizeLoader.h"
using namespace IW5;
namespace
{
class LocalizeLoader final : public AssetCreator<AssetLocalize>, public CommonLocalizeLoader
{
public:
LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
: CommonLocalizeLoader(searchPath, zone),
m_memory(memory)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
return CreateLocalizeAsset(assetName, context);
}
protected:
AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override
{
auto* asset = m_memory.Alloc<LocalizeEntry>();
asset->name = m_memory.Dup(localizeEntry.m_key.c_str());
asset->value = m_memory.Dup(localizeEntry.m_value.c_str());
return AssetCreationResult::Success(context.AddAsset<AssetLocalize>(localizeEntry.m_key, asset));
}
private:
MemoryManager& m_memory;
};
} // namespace
namespace IW5
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace IW5

View File

@ -0,0 +1,14 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
#include <memory>
namespace IW5
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace IW5

View File

@ -16,12 +16,11 @@ namespace
class JsonLoader
{
public:
JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector<XAssetInfoGeneric*>& dependencies)
JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
: m_stream(stream),
m_memory(memory),
m_manager(manager),
m_dependencies(dependencies)
m_context(context),
m_registration(registration)
{
}
@ -159,13 +158,13 @@ namespace
textureDef.semantic = jTexture.semantic;
auto* imageAsset = m_manager.LoadDependency<AssetImage>(jTexture.image);
auto* imageAsset = m_context.LoadDependency<AssetImage>(jTexture.image);
if (!imageAsset)
{
PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image));
return false;
}
m_dependencies.push_back(imageAsset);
m_registration.AddDependency(imageAsset);
if (jTexture.water)
{
@ -365,13 +364,13 @@ namespace
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
material.cameraRegion = jMaterial.cameraRegion;
auto* techniqueSet = m_manager.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
auto* techniqueSet = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
if (!techniqueSet)
{
PrintError(material, "Could not find technique set");
return false;
}
m_dependencies.push_back(techniqueSet);
m_registration.AddDependency(techniqueSet);
material.techniqueSet = techniqueSet->Asset();
if (!jMaterial.textures.empty())
@ -430,17 +429,17 @@ namespace
std::istream& m_stream;
MemoryManager& m_memory;
IAssetLoadingManager& m_manager;
std::vector<XAssetInfoGeneric*>& m_dependencies;
AssetCreationContext& m_context;
AssetRegistration<AssetMaterial>& m_registration;
};
} // namespace
namespace IW5
{
bool LoadMaterialAsJson(
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies)
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
{
const JsonLoader loader(stream, *memory, *manager, dependencies);
const JsonLoader loader(stream, memory, context, registration);
return loader.Load(material);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "Asset/AssetCreationContext.h"
#include "Asset/AssetRegistration.h"
#include "Game/IW5/IW5.h"
#include "Utils/MemoryManager.h"
@ -9,5 +10,5 @@
namespace IW5
{
bool LoadMaterialAsJson(
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies);
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration);
} // namespace IW5

View File

@ -0,0 +1,70 @@
#include "LoaderMaterialIW5.h"
#include "Game/IW5/IW5.h"
#include "JsonMaterialLoader.h"
#include <algorithm>
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
namespace
{
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto file = m_search_path.Open(GetFileNameForAsset(assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration))
{
std::cerr << std::format("Failed to load material \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
std::string GetFileNameForAsset(const std::string& assetName)
{
std::string sanitizedFileName(assetName);
if (sanitizedFileName[0] == '*')
{
std::ranges::replace(sanitizedFileName, '*', '_');
const auto parenthesisPos = sanitizedFileName.find('(');
if (parenthesisPos != std::string::npos)
sanitizedFileName.erase(parenthesisPos);
sanitizedFileName = std::format("generated/{}", sanitizedFileName);
}
return std::format("materials/{}.json", sanitizedFileName);
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW5
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MaterialLoader>(memory, searchPath);
}
} // namespace IW5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace IW5
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5

View File

@ -0,0 +1,230 @@
#include "LoaderMenuListIW5.h"
#include "Game/IW5/IW5.h"
#include "Game/IW5/Menu/MenuConversionZoneStateIW5.h"
#include "Game/IW5/Menu/MenuConverterIW5.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW5;
namespace
{
class MenuListLoader final : public AssetCreator<AssetMenuList>
{
public:
MenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
std::vector<menuDef_t*> menus;
AssetRegistration<AssetMenuList> registration(assetName);
auto* zoneState = context.GetZoneAssetLoaderState<menu::MenuAssetZoneState>();
auto* conversionState = context.GetZoneAssetLoaderState<MenuConversionZoneState>();
std::deque<std::string> menuLoadQueue;
const auto alreadyLoadedMenuListFileMenus = conversionState->m_menus_by_filename.find(assetName);
if (alreadyLoadedMenuListFileMenus == conversionState->m_menus_by_filename.end())
{
const auto file = m_search_path.Open(assetName);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
const auto menuListResult = ParseMenuFile(*file.m_stream, assetName, zoneState);
if (menuListResult)
{
ProcessParsedResults(assetName, context, menuListResult.get(), zoneState, conversionState, menus, registration);
for (const auto& menuToLoad : menuListResult->m_menus_to_load)
menuLoadQueue.emplace_back(menuToLoad);
zoneState->AddMenusToLoad(assetName, std::move(menuListResult->m_menus_to_load));
}
else
return AssetCreationResult::Failure();
}
while (!menuLoadQueue.empty())
{
const auto& menuFileToLoad = menuLoadQueue.front();
LoadMenuFileFromQueue(menuFileToLoad, context, zoneState, conversionState, menus, registration);
menuLoadQueue.pop_front();
}
auto* menuListAsset = m_memory.Create<MenuList>();
menuListAsset->name = m_memory.Dup(assetName.c_str());
registration.SetAsset(menuListAsset);
CreateMenuListAsset(*menuListAsset, menus);
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
void FinalizeZone(AssetCreationContext& context) override
{
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
}
private:
bool LoadMenuFileFromQueue(const std::string& menuFilePath,
AssetCreationContext& context,
menu::MenuAssetZoneState* zoneState,
MenuConversionZoneState* conversionState,
std::vector<menuDef_t*>& menus,
AssetRegistration<AssetMenuList>& registration)
{
const auto alreadyLoadedMenuFile = conversionState->m_menus_by_filename.find(menuFilePath);
if (alreadyLoadedMenuFile != conversionState->m_menus_by_filename.end())
{
std::cout << std::format("Already loaded \"{}\", skipping\n", menuFilePath);
for (auto* menu : alreadyLoadedMenuFile->second)
{
menus.emplace_back(menu->Asset());
registration.AddDependency(menu);
}
return true;
}
const auto file = m_search_path.Open(menuFilePath);
if (!file.IsOpen())
{
std::cerr << std::format("Could not open menu file \"{}\"\n", menuFilePath);
return false;
}
const auto menuFileResult = ParseMenuFile(*file.m_stream, menuFilePath, zoneState);
if (menuFileResult)
{
ProcessParsedResults(menuFilePath, context, menuFileResult.get(), zoneState, conversionState, menus, registration);
if (!menuFileResult->m_menus_to_load.empty())
std::cout << std::format("WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"\n", menuFilePath);
return true;
}
else
std::cerr << std::format("Could not read menu file \"{}\"\n", menuFilePath);
return false;
}
bool ProcessParsedResults(const std::string& fileName,
AssetCreationContext& context,
menu::ParsingResult* parsingResult,
menu::MenuAssetZoneState* zoneState,
MenuConversionZoneState* conversionState,
std::vector<menuDef_t*>& menus,
AssetRegistration<AssetMenuList>& registration)
{
const auto menuCount = parsingResult->m_menus.size();
const auto functionCount = parsingResult->m_functions.size();
const auto menuLoadCount = parsingResult->m_menus_to_load.size();
auto totalItemCount = 0u;
for (const auto& menu : parsingResult->m_menus)
totalItemCount += menu->m_items.size();
std::cout << std::format("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)\n",
fileName,
menuLoadCount,
menuCount,
functionCount,
totalItemCount);
// Add all functions to the zone state to make them available for all menus to be converted
for (auto& function : parsingResult->m_functions)
zoneState->AddFunction(std::move(function));
// Prepare a list of all menus of this file
std::vector<XAssetInfo<menuDef_t>*> allMenusOfFile;
allMenusOfFile.reserve(parsingResult->m_menus.size());
// Convert all menus and add them as assets
for (auto& commonMenu : parsingResult->m_menus)
{
auto converter = IMenuConverter::Create(ObjLoading::Configuration.MenuNoOptimization, m_search_path, m_memory, context);
auto* menuAsset = m_memory.Alloc<menuDef_t>();
AssetRegistration<AssetMenu> menuRegistration(commonMenu->m_name, menuAsset);
converter->ConvertMenu(*commonMenu, *menuAsset, menuRegistration);
if (menuAsset == nullptr)
{
std::cerr << std::format("Failed to convert menu file \"{}\"\n", commonMenu->m_name);
return false;
}
menus.emplace_back(menuAsset);
auto* menuAssetInfo = context.AddAsset(std::move(menuRegistration));
if (menuAssetInfo)
{
allMenusOfFile.emplace_back(menuAssetInfo);
registration.AddDependency(menuAssetInfo);
}
zoneState->AddMenu(std::move(commonMenu));
}
// Register this file with all loaded menus
conversionState->AddLoadedFile(fileName, std::move(allMenusOfFile));
return true;
}
void CreateMenuListAsset(MenuList& menuList, const std::vector<menuDef_t*>& menus)
{
menuList.menuCount = static_cast<int>(menus.size());
if (menuList.menuCount > 0)
{
menuList.menus = m_memory.Alloc<menuDef_t*>(menuList.menuCount);
for (auto i = 0; i < menuList.menuCount; i++)
menuList.menus[i] = menus[i];
}
else
menuList.menus = nullptr;
}
std::unique_ptr<menu::ParsingResult> ParseMenuFile(std::istream& stream, const std::string& menuFileName, const menu::MenuAssetZoneState* zoneState)
{
menu::MenuFileReader reader(stream,
menuFileName,
menu::FeatureLevel::IW4,
[this](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr<std::istream>
{
auto foundFileToInclude = m_search_path.Open(filename);
if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream)
return nullptr;
return std::move(foundFileToInclude.m_stream);
});
reader.IncludeZoneState(zoneState);
reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing);
return reader.ReadMenuFile();
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW5
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MenuListLoader>(memory, searchPath);
}
} // namespace IW5

View File

@ -0,0 +1,13 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW5/IW5.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace IW5
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath);
} // namespace IW5

Some files were not shown because too many files have changed in this diff Show More