chore: refactor IW4 asset loaders

This commit is contained in:
Jan 2024-12-25 21:39:05 +01:00
parent f9456101e6
commit 7ef944ebd4
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
139 changed files with 2370 additions and 2965 deletions

View File

@ -1,6 +1,7 @@
#include "ZoneCreator.h"
#include "AssetLoading/AssetLoadingContext.h"
#include "Gdt/GdtLookup.h"
#include "IObjCompiler.h"
#include "IObjLoader.h"
@ -45,6 +46,19 @@ namespace
namespace zone_creator
{
void InitLookup(const ZoneCreationContext& context, GdtLookup& lookup)
{
std::vector<const Gdt*> gdtFiles;
gdtFiles.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
{
gdtFiles.emplace_back(gdt.get());
}
lookup.Initialize(gdtFiles);
}
std::unique_ptr<Zone> CreateZoneForDefinition(GameId gameId, ZoneCreationContext& context)
{
auto zone = CreateZone(context, gameId);
@ -53,12 +67,15 @@ namespace zone_creator
IgnoreReferencesFromAssets(context);
IgnoredAssetLookup ignoredAssetLookup(context.m_ignored_assets);
GdtLookup lookup;
InitLookup(context, lookup);
const auto* objCompiler = IObjCompiler::GetObjCompilerForGame(gameId);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(gameId);
AssetCreatorCollection creatorCollection(*zone);
objCompiler->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_definition);
objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path);
objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path, gdtLookup);
AssetCreationContext creationContext(zone.get(), &creatorCollection, &ignoredAssetLookup);

View File

@ -1,4 +1,5 @@
#pragma once
#include "Game/IW4/IW4.h"
namespace IW4

View File

@ -1,5 +1,6 @@
#include "AssetCreationContext.h"
#include <cassert>
#include <format>
#include <iostream>
@ -51,6 +52,8 @@ void GenericAssetRegistration::AddIndirectAssetReference(IndirectAssetReference
std::unique_ptr<XAssetInfoGeneric> GenericAssetRegistration::CreateXAssetInfo()
{
assert(m_asset);
std::vector<XAssetInfoGeneric*> dependencies(m_dependencies.begin(), m_dependencies.end());
std::vector<scr_string_t> scriptStrings(m_used_script_strings.begin(), m_used_script_strings.end());
std::vector<IndirectAssetReference> indirectAssetReferences(m_indirect_asset_references.begin(), m_indirect_asset_references.end());

View File

@ -52,7 +52,7 @@ public:
{
static_assert(std::is_base_of_v<IAssetBase, AssetType>);
return static_cast<XAssetInfo<typename AssetType::Type>*>(LoadDependencyInternal(AssetType::EnumEntry, assetName));
return static_cast<XAssetInfo<typename AssetType::Type>*>(LoadDependencyGeneric(AssetType::EnumEntry, assetName));
}
XAssetInfoGeneric* LoadDependencyGeneric(asset_type_t assetType, const std::string& assetName);
@ -76,7 +76,7 @@ public:
return dynamic_cast<T*>(foundEntry->second.get());
auto newState = std::make_unique<T>();
newState->SetZone(&m_zone);
newState->SetZone(m_zone);
auto* newStatePtr = newState.get();
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
return newStatePtr;

View File

@ -25,7 +25,7 @@ public:
std::unique_ptr<XAssetInfoGeneric> CreateXAssetInfo();
private:
protected:
asset_type_t m_type;
std::string m_name;
void* m_asset;
@ -39,6 +39,11 @@ template<typename AssetType> class AssetRegistration : public GenericAssetRegist
static_assert(std::is_base_of_v<IAssetBase, AssetType>);
public:
AssetRegistration(std::string assetName)
: GenericAssetRegistration(AssetType::EnumEntry, std::move(assetName), nullptr)
{
}
AssetRegistration(std::string assetName, typename AssetType::Type* asset)
: GenericAssetRegistration(AssetType::EnumEntry, std::move(assetName), asset)
{
@ -48,4 +53,9 @@ public:
AssetRegistration(AssetRegistration&& other) = default;
AssetRegistration& operator=(const AssetRegistration& other) = delete;
AssetRegistration& operator=(AssetRegistration&& other) noexcept = default;
void SetAsset(typename AssetType::Type* asset)
{
m_asset = asset;
}
};

View File

@ -2,49 +2,6 @@
AssetLoadingContext::AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector<Gdt*> gdtFiles)
: m_zone(zone),
m_raw_search_path(rawSearchPath),
m_gdt_files(std::move(gdtFiles))
m_raw_search_path(rawSearchPath)
{
BuildGdtEntryCache();
}
void AssetLoadingContext::BuildGdtEntryCache()
{
for (const 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<std::string, GdtEntry*> 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
{
auto entryMapEntry = gdfMapEntry->second.find(entry->m_name);
if (entryMapEntry == gdfMapEntry->second.end())
gdfMapEntry->second.emplace(std::make_pair(entry->m_name, entry.get()));
else
entryMapEntry->second = 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;
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "IGdtQueryable.h"
#include "Gdt/IGdtQueryable.h"
#include "IZoneAssetLoaderState.h"
#include "Obj/Gdt/Gdt.h"
#include "SearchPath/ISearchPath.h"
@ -32,15 +32,10 @@ public:
return newStatePtr;
}
private:
void BuildGdtEntryCache();
public:
Zone& m_zone;
ISearchPath& m_raw_search_path;
const std::vector<Gdt*> m_gdt_files;
std::unordered_map<std::string, asset_type_t> m_ignored_asset_map;
std::unordered_map<std::string, std::unordered_map<std::string, GdtEntry*>> m_entries_by_gdf_and_by_name;
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetLoaderState>> m_zone_asset_loader_states;
};

View File

@ -1,6 +1,7 @@
#pragma once
#include "Gdt/IGdtQueryable.h"
#include "IAssetLoadingManager.h"
#include "IGdtQueryable.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/ClassUtils.h"
#include "Zone/ZoneTypes.h"

View File

@ -1,7 +1,6 @@
#include "AssetLoaderRawFileIW3.h"
#include "Game/IW3/IW3.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>

View File

@ -1,17 +0,0 @@
#include "AssetLoaderAddonMapEnts.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderAddonMapEnts final : public BasicAssetLoader<AssetAddonMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,27 +0,0 @@
#include "AssetLoaderClipMap.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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;
}
asset_type_t AssetLoaderClipMapSp::GetHandlingAssetType() const
{
return ASSET_TYPE_CLIPMAP_SP;
}
asset_type_t AssetLoaderClipMapMp::GetHandlingAssetType() const
{
return ASSET_TYPE_CLIPMAP_MP;
}

View File

@ -1,25 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderClipMap : public BasicAssetLoaderWithoutType<clipMap_t>
{
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
class AssetLoaderClipMapSp final : public AssetLoaderClipMap
{
public:
_NODISCARD asset_type_t GetHandlingAssetType() const override;
};
class AssetLoaderClipMapMp final : public AssetLoaderClipMap
{
public:
_NODISCARD asset_type_t GetHandlingAssetType() const override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderComWorld.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderComWorld final : public BasicAssetLoader<AssetComWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFont.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderFont final : public BasicAssetLoader<AssetFont>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFx.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderFx final : public BasicAssetLoader<AssetFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFxImpactTable.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderFxImpactTable final : public BasicAssetLoader<AssetImpactFx>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderFxWorld.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderFxWorld final : public BasicAssetLoader<AssetFxWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,72 +0,0 @@
#include "AssetLoaderGfxLightDef.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <iostream>
#include <sstream>
using namespace IW4;
std::string AssetLoaderGfxLightDef::GetAssetFilename(const std::string& assetName)
{
std::ostringstream ss;
ss << "lights/" << assetName;
return ss.str();
}
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;
}
bool AssetLoaderGfxLightDef::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderGfxLightDef::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto filename = GetAssetFilename(assetName);
const auto file = searchPath->Open(filename);
if (!file.IsOpen())
return false;
const auto imageNameSize = file.m_length - sizeof(char) - sizeof(char);
if (imageNameSize < 0 || imageNameSize > MAX_IMAGE_NAME_SIZE)
return false;
std::string imageName(static_cast<size_t>(imageNameSize), '\0');
int8_t samplerState;
int8_t lmapLookupStart;
file.m_stream->read(reinterpret_cast<char*>(&samplerState), sizeof(int8_t));
file.m_stream->read(&imageName[0], static_cast<size_t>(imageNameSize));
file.m_stream->read(reinterpret_cast<char*>(&lmapLookupStart), sizeof(int8_t));
auto* imageDependency = manager->LoadDependency<AssetImage>(imageName);
if (!imageDependency)
{
std::cerr << "Could not load GfxLightDef \"" << assetName << "\" due to missing image \"" << imageName << "\"\n";
return false;
}
auto* lightDef = memory->Create<GfxLightDef>();
lightDef->name = memory->Dup(assetName.c_str());
lightDef->attenuation.samplerState = samplerState;
lightDef->attenuation.image = imageDependency->Asset();
lightDef->lmapLookupStart = static_cast<int>(static_cast<uint8_t>(lmapLookupStart));
manager->AddAsset<AssetLightDef>(assetName, lightDef);
return true;
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderGfxLightDef final : public BasicAssetLoader<AssetLightDef>
{
static constexpr auto MAX_IMAGE_NAME_SIZE = 0x800;
static std::string GetAssetFilename(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 IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderGfxWorld.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderGfxWorld final : public BasicAssetLoader<AssetGfxWorld>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,43 +0,0 @@
#include "AssetLoaderLeaderboard.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/Leaderboard/JsonLeaderboardDefLoader.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
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 IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderLoadedSound.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderLoadedSound final : public BasicAssetLoader<AssetLoadedSound>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderMapEnts.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderMapEnts final : public BasicAssetLoader<AssetMapEnts>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderMaterial final : public BasicAssetLoader<AssetMaterial>
{
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;
};
} // namespace IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderMenuDef.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderMenuDef final : public BasicAssetLoader<AssetMenu>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,233 +0,0 @@
#include "AssetLoaderMenuList.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/Menu/MenuConversionZoneStateIW4.h"
#include "Game/IW4/Menu/MenuConverterIW4.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <iostream>
using namespace IW4;
namespace IW4
{
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::IW4,
[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 IW4
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
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 IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderPhysCollmap.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderPhysCollmap final : public BasicAssetLoader<AssetPhysCollMap>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,134 +0,0 @@
#include "AssetLoaderPhysPreset.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
#include "Game/IW4/InfoString/PhysPresetFields.h"
#include "Game/IW4/ObjConstantsIW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <iostream>
#include <limits>
using namespace IW4;
namespace IW4
{
class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter
{
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
assert(false);
return false;
}
public:
InfoStringToPhysPresetConverter(const InfoString& infoString,
PhysPresetInfo* physPreset,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager* memory,
IAssetLoadingManager* manager,
const cspField_t* fields,
const size_t fieldCount)
: InfoStringToStructConverter(infoString, physPreset, zoneScriptStrings, memory, manager, fields, fieldCount)
{
}
};
} // namespace IW4
void AssetLoaderPhysPreset::CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset)
{
physPreset->mass = std::clamp(physPresetInfo->mass, 1.0f, 2000.0f) * 0.001f;
physPreset->bounce = physPresetInfo->bounce;
if (physPresetInfo->isFrictionInfinity != 0)
physPreset->friction = std::numeric_limits<float>::infinity();
else
physPreset->friction = physPresetInfo->friction;
physPreset->bulletForceScale = physPresetInfo->bulletForceScale;
physPreset->explosiveForceScale = physPresetInfo->explosiveForceScale;
physPreset->sndAliasPrefix = physPresetInfo->sndAliasPrefix;
physPreset->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction;
physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity;
physPreset->tempDefaultToCylinder = physPresetInfo->tempDefaultToCylinder != 0;
physPreset->perSurfaceSndAlias = physPresetInfo->perSurfaceSndAlias != 0;
}
bool AssetLoaderPhysPreset::LoadFromInfoString(
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
{
const auto presetInfo = std::make_unique<PhysPresetInfo>();
memset(presetInfo.get(), 0, sizeof(PhysPresetInfo));
InfoStringToPhysPresetConverter converter(
infoString, presetInfo.get(), zone->m_script_strings, memory, manager, phys_preset_fields, std::extent_v<decltype(phys_preset_fields)>);
if (!converter.Convert())
{
std::cout << "Failed to parse phys preset: \"" << assetName << "\"\n";
return true;
}
auto* physPreset = memory->Create<PhysPreset>();
CopyFromPhysPresetInfo(presetInfo.get(), physPreset);
physPreset->name = memory->Dup(assetName.c_str());
manager->AddAsset<AssetPhysPreset>(assetName, physPreset, converter.GetDependencies(), converter.GetUsedScriptStrings());
return true;
}
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;
}
bool AssetLoaderPhysPreset::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderPhysPreset::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName);
if (gdtEntry == nullptr)
return false;
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cout << "Failed to read phys preset gdt entry: \"" << assetName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}
bool AssetLoaderPhysPreset::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderPhysPreset::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "physic/" + assetName;
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
InfoString infoString;
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream))
{
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
return true;
}
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "InfoString/InfoString.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderPhysPreset final : public BasicAssetLoader<AssetPhysPreset>
{
static void CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset);
static bool
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
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 IW4

View File

@ -1,63 +0,0 @@
#include "AssetLoaderPixelShader.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstdint>
#include <cstring>
#include <iostream>
#include <sstream>
using namespace IW4;
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;
}
bool AssetLoaderPixelShader::CanLoadFromRaw() const
{
return true;
}
std::string AssetLoaderPixelShader::GetFileNameForAsset(const std::string& assetName)
{
std::ostringstream ss;
ss << "shader_bin/ps_" << assetName << ".cso";
return ss.str();
}
bool AssetLoaderPixelShader::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = GetFileNameForAsset(assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
if (file.m_length % sizeof(uint32_t) != 0)
{
std::cerr << "Invalid pixel shader \"" << assetName << "\": Size must be dividable by " << sizeof(uint32_t) << "\n";
return false;
}
auto* pixelShader = memory->Create<MaterialPixelShader>();
pixelShader->name = memory->Dup(assetName.c_str());
pixelShader->prog.loadDef.programSize = static_cast<uint16_t>(static_cast<size_t>(file.m_length) / sizeof(uint32_t));
pixelShader->prog.loadDef.loadForRenderer = 0;
pixelShader->prog.ps = nullptr;
auto* fileBuffer = memory->Alloc<uint32_t>(pixelShader->prog.loadDef.programSize);
file.m_stream->read(reinterpret_cast<char*>(fileBuffer), static_cast<std::streamsize>(pixelShader->prog.loadDef.programSize) * sizeof(uint32_t));
if (file.m_stream->gcount() != file.m_length)
return false;
pixelShader->prog.loadDef.program = fileBuffer;
manager->AddAsset<AssetPixelShader>(assetName, pixelShader);
return true;
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
#include <string>
namespace IW4
{
class AssetLoaderPixelShader final : public BasicAssetLoader<AssetPixelShader>
{
public:
_NODISCARD static std::string GetFileNameForAsset(const std::string& assetName);
_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 IW4

View File

@ -1,80 +0,0 @@
#include "AssetLoaderRawFile.h"
#include "Game/IW4/IW4.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <filesystem>
#include <iostream>
#include <zlib.h>
using namespace IW4;
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->data.compressedBuffer = 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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
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 IW4

View File

@ -1,63 +0,0 @@
#include "AssetLoaderSndCurve.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include "Sound/SoundCurveLoader.h"
#include <cstring>
#include <iostream>
#include <sstream>
using namespace IW4;
void* AssetLoaderSndCurve::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;
}
bool AssetLoaderSndCurve::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderSndCurve::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto sndCurveData = sound_curve::LoadSoundCurve(manager, assetName);
if (!sndCurveData)
return false;
if (sndCurveData->knots.size() > std::extent_v<decltype(SndCurve::knots)>)
{
std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->knots.size() << ")\n";
return false;
}
auto* sndCurve = memory->Create<SndCurve>();
sndCurve->filename = memory->Dup(assetName.c_str());
sndCurve->knotCount = static_cast<uint16_t>(sndCurveData->knots.size());
for (auto i = 0u; i < std::extent_v<decltype(SndCurve::knots)>; i++)
{
if (i < sndCurveData->knots.size())
{
const auto& [x, y] = sndCurveData->knots[i];
sndCurve->knots[i][0] = static_cast<float>(x);
sndCurve->knots[i][1] = static_cast<float>(y);
}
else
{
sndCurve->knots[i][0] = 0;
sndCurve->knots[i][1] = 0;
}
}
manager->AddAsset<AssetSoundCurve>(assetName, sndCurve);
return true;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderSndCurve final : public BasicAssetLoader<AssetSoundCurve>
{
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 IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderSoundAliasList.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderSoundAliasList final : public BasicAssetLoader<AssetSound>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,40 +0,0 @@
#include "AssetLoaderStringTable.h"
#include "Csv/CsvStream.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include "StringTable/StringTableLoader.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
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 IW4

View File

@ -1,220 +0,0 @@
#include "AssetLoaderStructuredDataDefSet.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include "StructuredDataDef/StructuredDataDefReader.h"
#include "Utils/Alignment.h"
#include <cstring>
using namespace IW4;
void* AssetLoaderStructuredDataDefSet::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;
}
bool AssetLoaderStructuredDataDefSet::CanLoadFromRaw() const
{
return true;
}
StructuredDataType AssetLoaderStructuredDataDefSet::ConvertType(CommonStructuredDataType inputType)
{
switch (inputType.m_category)
{
case CommonStructuredDataTypeCategory::INT:
return {DATA_INT, {0}};
case CommonStructuredDataTypeCategory::BYTE:
return {DATA_BYTE, {0}};
case CommonStructuredDataTypeCategory::BOOL:
return {DATA_BOOL, {0}};
case CommonStructuredDataTypeCategory::FLOAT:
return {DATA_FLOAT, {0}};
case CommonStructuredDataTypeCategory::SHORT:
return {DATA_SHORT, {0}};
case CommonStructuredDataTypeCategory::STRING:
return {DATA_STRING, {inputType.m_info.string_length}};
case CommonStructuredDataTypeCategory::ENUM:
return {DATA_ENUM, {inputType.m_info.type_index}};
case CommonStructuredDataTypeCategory::STRUCT:
return {DATA_STRUCT, {inputType.m_info.type_index}};
case CommonStructuredDataTypeCategory::INDEXED_ARRAY:
return {DATA_INDEXED_ARRAY, {inputType.m_info.type_index}};
case CommonStructuredDataTypeCategory::ENUM_ARRAY:
return {DATA_ENUM_ARRAY, {inputType.m_info.type_index}};
case CommonStructuredDataTypeCategory::UNKNOWN:
default:
assert(false);
return {DATA_INT, {0}};
}
}
void AssetLoaderStructuredDataDefSet::ConvertEnum(StructuredDataEnum* outputEnum, CommonStructuredDataEnum* inputEnum, MemoryManager* memory)
{
outputEnum->entryCount = static_cast<int>(inputEnum->m_entries.size());
if (inputEnum->m_reserved_entry_count <= 0)
outputEnum->reservedEntryCount = outputEnum->entryCount;
else
outputEnum->reservedEntryCount = inputEnum->m_reserved_entry_count;
inputEnum->SortEntriesByName();
if (!inputEnum->m_entries.empty())
{
outputEnum->entries = memory->Alloc<StructuredDataEnumEntry>(inputEnum->m_entries.size());
for (auto entryIndex = 0u; entryIndex < inputEnum->m_entries.size(); entryIndex++)
{
auto& outputEntry = outputEnum->entries[entryIndex];
const auto& inputEntry = inputEnum->m_entries[entryIndex];
outputEntry.string = memory->Dup(inputEntry.m_name.c_str());
outputEntry.index = static_cast<uint16_t>(inputEntry.m_value);
}
}
else
outputEnum->entries = nullptr;
}
void AssetLoaderStructuredDataDefSet::ConvertStruct(StructuredDataStruct* outputStruct, CommonStructuredDataStruct* inputStruct, MemoryManager* memory)
{
outputStruct->size = static_cast<int>(inputStruct->m_size_in_byte);
outputStruct->bitOffset = inputStruct->m_bit_offset;
outputStruct->propertyCount = static_cast<int>(inputStruct->m_properties.size());
inputStruct->SortPropertiesByName();
if (!inputStruct->m_properties.empty())
{
outputStruct->properties = memory->Alloc<StructuredDataStructProperty>(inputStruct->m_properties.size());
for (auto propertyIndex = 0u; propertyIndex < inputStruct->m_properties.size(); propertyIndex++)
{
auto& outputProperty = outputStruct->properties[propertyIndex];
const auto& inputProperty = inputStruct->m_properties[propertyIndex];
outputProperty.name = memory->Dup(inputProperty.m_name.c_str());
outputProperty.type = ConvertType(inputProperty.m_type);
if (outputProperty.type.type != DATA_BOOL)
{
assert(inputProperty.m_offset_in_bits % 8 == 0);
outputProperty.offset = inputProperty.m_offset_in_bits / 8;
}
else
outputProperty.offset = inputProperty.m_offset_in_bits;
}
}
else
outputStruct->properties = nullptr;
}
void AssetLoaderStructuredDataDefSet::ConvertIndexedArray(StructuredDataIndexedArray* outputIndexedArray,
const CommonStructuredDataIndexedArray* inputIndexedArray,
MemoryManager* memory)
{
outputIndexedArray->arraySize = static_cast<int>(inputIndexedArray->m_element_count);
outputIndexedArray->elementType = ConvertType(inputIndexedArray->m_array_type);
outputIndexedArray->elementSize = utils::Align(inputIndexedArray->m_element_size_in_bits, 8u) / 8u;
}
void AssetLoaderStructuredDataDefSet::ConvertEnumedArray(StructuredDataEnumedArray* outputEnumedArray,
const CommonStructuredDataEnumedArray* inputEnumedArray,
MemoryManager* memory)
{
outputEnumedArray->enumIndex = static_cast<int>(inputEnumedArray->m_enum_index);
outputEnumedArray->elementType = ConvertType(inputEnumedArray->m_array_type);
outputEnumedArray->elementSize = utils::Align(inputEnumedArray->m_element_size_in_bits, 8u) / 8u;
}
void AssetLoaderStructuredDataDefSet::ConvertDef(StructuredDataDef* outputDef, const CommonStructuredDataDef* inputDef, MemoryManager* memory)
{
outputDef->version = inputDef->m_version;
outputDef->formatChecksum = inputDef->m_checksum;
outputDef->enumCount = static_cast<int>(inputDef->m_enums.size());
if (!inputDef->m_enums.empty())
{
outputDef->enums = memory->Alloc<StructuredDataEnum>(inputDef->m_enums.size());
for (auto enumIndex = 0u; enumIndex < inputDef->m_enums.size(); enumIndex++)
ConvertEnum(&outputDef->enums[enumIndex], inputDef->m_enums[enumIndex].get(), memory);
}
else
outputDef->enums = nullptr;
outputDef->structCount = static_cast<int>(inputDef->m_structs.size());
if (!inputDef->m_structs.empty())
{
outputDef->structs = memory->Alloc<StructuredDataStruct>(inputDef->m_structs.size());
for (auto structIndex = 0u; structIndex < inputDef->m_structs.size(); structIndex++)
ConvertStruct(&outputDef->structs[structIndex], inputDef->m_structs[structIndex].get(), memory);
}
else
outputDef->structs = nullptr;
outputDef->indexedArrayCount = static_cast<int>(inputDef->m_indexed_arrays.size());
if (!inputDef->m_indexed_arrays.empty())
{
outputDef->indexedArrays = memory->Alloc<StructuredDataIndexedArray>(inputDef->m_indexed_arrays.size());
for (auto indexedArrayIndex = 0u; indexedArrayIndex < inputDef->m_indexed_arrays.size(); indexedArrayIndex++)
ConvertIndexedArray(&outputDef->indexedArrays[indexedArrayIndex], &inputDef->m_indexed_arrays[indexedArrayIndex], memory);
}
else
outputDef->indexedArrays = nullptr;
outputDef->enumedArrayCount = static_cast<int>(inputDef->m_enumed_arrays.size());
if (!inputDef->m_enumed_arrays.empty())
{
outputDef->enumedArrays = memory->Alloc<StructuredDataEnumedArray>(inputDef->m_enumed_arrays.size());
for (auto enumedArrayIndex = 0u; enumedArrayIndex < inputDef->m_enumed_arrays.size(); enumedArrayIndex++)
ConvertEnumedArray(&outputDef->enumedArrays[enumedArrayIndex], &inputDef->m_enumed_arrays[enumedArrayIndex], memory);
}
else
outputDef->enumedArrays = nullptr;
outputDef->rootType = ConvertType(inputDef->m_root_type);
outputDef->size = inputDef->m_size_in_byte;
}
StructuredDataDefSet* AssetLoaderStructuredDataDefSet::ConvertSet(const std::string& assetName,
const std::vector<std::unique_ptr<CommonStructuredDataDef>>& defs,
MemoryManager* memory)
{
auto* set = memory->Create<StructuredDataDefSet>();
set->name = memory->Dup(assetName.c_str());
set->defCount = defs.size();
set->defs = memory->Alloc<StructuredDataDef>(defs.size());
for (auto defIndex = 0u; defIndex < defs.size(); defIndex++)
ConvertDef(&set->defs[defIndex], defs[defIndex].get(), memory);
return set;
}
bool AssetLoaderStructuredDataDefSet::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;
StructuredDataDefReader reader(*file.m_stream,
assetName,
[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);
});
bool readingDefsSuccessful;
const auto defs = reader.ReadStructureDataDefs(readingDefsSuccessful);
if (readingDefsSuccessful)
manager->AddAsset<AssetStructuredDataDef>(assetName, ConvertSet(assetName, defs, memory));
return true;
}

View File

@ -1,29 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
#include "StructuredDataDef/CommonStructuredDataDef.h"
namespace IW4
{
class AssetLoaderStructuredDataDefSet final : public BasicAssetLoader<AssetStructuredDataDef>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
static StructuredDataType ConvertType(CommonStructuredDataType inputType);
static void ConvertEnum(StructuredDataEnum* outputEnum, CommonStructuredDataEnum* inputEnum, MemoryManager* memory);
static void ConvertStruct(StructuredDataStruct* outputStruct, CommonStructuredDataStruct* inputStruct, MemoryManager* memory);
static void ConvertIndexedArray(StructuredDataIndexedArray* outputIndexedArray,
const CommonStructuredDataIndexedArray* inputIndexedArray,
MemoryManager* memory);
static void
ConvertEnumedArray(StructuredDataEnumedArray* outputEnumedArray, const CommonStructuredDataEnumedArray* inputEnumedArray, MemoryManager* memory);
static void ConvertDef(StructuredDataDef* outputDef, const CommonStructuredDataDef* inputDef, MemoryManager* memory);
static StructuredDataDefSet*
ConvertSet(const std::string& assetName, const std::vector<std::unique_ptr<CommonStructuredDataDef>>& defs, MemoryManager* memory);
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
} // namespace IW4

View File

@ -1,36 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
#include "StateMap/StateMapDefinition.h"
#include "Techset/TechniqueStateMapCache.h"
#include "Techset/TechsetDefinition.h"
#include "Techset/TechsetDefinitionCache.h"
namespace IW4
{
class AssetLoaderTechniqueSet final : public BasicAssetLoader<AssetTechniqueSet>
{
static bool CreateTechsetFromDefinition(const std::string& assetName,
const techset::TechsetDefinition& definition,
ISearchPath* searchPath,
MemoryManager* memory,
IAssetLoadingManager* manager);
public:
static std::string GetTechsetFileName(const std::string& techsetAssetName);
static std::string GetTechniqueFileName(const std::string& techniqueName);
static std::string GetStateMapFileName(const std::string& stateMapName);
static techset::TechsetDefinition*
LoadTechsetDefinition(const std::string& assetName, ISearchPath* searchPath, techset::TechsetDefinitionCache* definitionCache);
static const state_map::StateMapDefinition*
LoadStateMapDefinition(const std::string& stateMapName, ISearchPath* searchPath, techset::TechniqueStateMapCache* stateMapCache);
_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 IW4

View File

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

View File

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

View File

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

View File

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

View File

@ -1,101 +0,0 @@
#include "AssetLoaderVertexDecl.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/TechsetConstantsIW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <iostream>
using namespace IW4;
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;
}
bool AssetLoaderVertexDecl::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderVertexDecl::NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset)
{
if (offset >= assetName.size())
return false;
if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1]))
{
abbreviation = std::string(assetName, offset, 2);
offset += 2;
}
else
{
abbreviation = std::string(assetName, offset, 1);
offset += 1;
}
return true;
}
bool AssetLoaderVertexDecl::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
MaterialVertexDeclaration decl{};
size_t currentOffset = 0u;
if (!assetName.empty() && assetName[0] == ',')
currentOffset = 1u;
std::string sourceAbbreviation;
while (NextAbbreviation(assetName, sourceAbbreviation, currentOffset))
{
if (decl.streamCount >= std::extent_v<decltype(MaterialVertexStreamRouting::data)>)
{
std::cout << "Failed to add vertex decl stream. Too many abbreviations: " << assetName << "\n";
return false;
}
std::string destinationAbbreviation;
if (!NextAbbreviation(assetName, destinationAbbreviation, currentOffset))
{
std::cout << "Failed to detect vertex decl destination abbreviation: " << assetName << "\n";
return false;
}
const auto foundSourceAbbreviation = std::ranges::find(materialStreamSourceAbbreviation, sourceAbbreviation);
if (foundSourceAbbreviation == std::end(materialStreamSourceAbbreviation))
{
std::cout << "Unknown vertex decl source abbreviation: " << sourceAbbreviation << "\n";
return false;
}
const auto foundDestinationAbbreviation = std::ranges::find(materialStreamDestinationAbbreviation, destinationAbbreviation);
if (foundDestinationAbbreviation == std::end(materialStreamDestinationAbbreviation))
{
std::cout << "Unknown vertex decl destination abbreviation: " << destinationAbbreviation << "\n";
return false;
}
const auto sourceIndex = static_cast<MaterialStreamStreamSource_e>(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation));
const auto destinationIndex =
static_cast<MaterialStreamDestination_e>(foundDestinationAbbreviation - std::begin(materialStreamDestinationAbbreviation));
decl.routing.data[decl.streamCount].source = sourceIndex;
decl.routing.data[decl.streamCount].dest = destinationIndex;
decl.hasOptionalSource = decl.hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN;
decl.streamCount++;
}
decl.name = memory->Dup(assetName.c_str());
auto* allocatedDecl = memory->Create<MaterialVertexDeclaration>(decl);
manager->AddAsset<AssetVertexDecl>(assetName, allocatedDecl);
return true;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderVertexDecl final : public BasicAssetLoader<AssetVertexDecl>
{
static bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset);
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 IW4

View File

@ -1,63 +0,0 @@
#include "AssetLoaderVertexShader.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstdint>
#include <cstring>
#include <iostream>
#include <sstream>
using namespace IW4;
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;
}
bool AssetLoaderVertexShader::CanLoadFromRaw() const
{
return true;
}
std::string AssetLoaderVertexShader::GetFileNameForAsset(const std::string& assetName)
{
std::ostringstream ss;
ss << "shader_bin/vs_" << assetName << ".cso";
return ss.str();
}
bool AssetLoaderVertexShader::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = GetFileNameForAsset(assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
if (file.m_length % sizeof(uint32_t) != 0)
{
std::cerr << "Invalid vertex shader \"" << assetName << "\": Size must be dividable by " << sizeof(uint32_t) << "\n";
return false;
}
auto* vertexShader = memory->Create<MaterialVertexShader>();
vertexShader->name = memory->Dup(assetName.c_str());
vertexShader->prog.loadDef.programSize = static_cast<uint16_t>(static_cast<size_t>(file.m_length) / sizeof(uint32_t));
vertexShader->prog.loadDef.loadForRenderer = 0;
vertexShader->prog.vs = nullptr;
auto* fileBuffer = memory->Alloc<uint32_t>(vertexShader->prog.loadDef.programSize);
file.m_stream->read(reinterpret_cast<char*>(fileBuffer), static_cast<std::streamsize>(vertexShader->prog.loadDef.programSize) * sizeof(uint32_t));
if (file.m_stream->gcount() != file.m_length)
return false;
vertexShader->prog.loadDef.program = fileBuffer;
manager->AddAsset<AssetVertexShader>(assetName, vertexShader);
return true;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderVertexShader final : public BasicAssetLoader<AssetVertexShader>
{
public:
_NODISCARD static std::string GetFileNameForAsset(const std::string& assetName);
_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 IW4

View File

@ -1,20 +0,0 @@
#pragma once
#include "AssetLoading/BasicAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
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 IW4

View File

@ -1,17 +0,0 @@
#include "AssetLoaderXAnim.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderXAnim final : public BasicAssetLoader<AssetXAnim>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

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

View File

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

View File

@ -1,17 +0,0 @@
#include "AssetLoaderXModelSurfs.h"
#include "Game/IW4/IW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include <cstring>
using namespace IW4;
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/IW4/IW4.h"
#include "SearchPath/ISearchPath.h"
namespace IW4
{
class AssetLoaderXModelSurfs final : public BasicAssetLoader<AssetXModelSurfs>
{
public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
};
} // namespace IW4

View File

@ -1,6 +1,7 @@
#include "InfoStringToStructConverter.h"
#include <cassert>
#include <format>
#include <iostream>
using namespace IW4;
@ -8,12 +9,12 @@ using namespace IW4;
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;
@ -145,7 +146,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as mph\n";
std::cerr << std::format("Failed to parse value \"{}\" as mph\n", value);
return false;
}
@ -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/IW4/IW4.h"
#include "InfoString/InfoStringToStructConverterBase.h"
@ -7,22 +8,22 @@ namespace IW4
{
class InfoStringToStructConverter : public InfoStringToStructConverterBase
{
protected:
IAssetLoadingManager* m_loading_manager;
const cspField_t* m_fields;
size_t m_field_count;
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 IW4

View File

@ -0,0 +1,52 @@
#include "AssetLoaderLeaderboardIW4.h"
#include "Game/IW4/IW4.h"
#include "JsonLeaderboardDefLoader.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW4;
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 IW4
{
std::unique_ptr<AssetCreator<AssetLeaderboard>> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LeaderboardLoader>(memory, searchPath);
}
} // namespace IW4

View File

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

View File

@ -0,0 +1,80 @@
#include "LoaderLightDefIW4.h"
#include "Game/IW4/IW4.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW4;
namespace
{
constexpr auto MAX_IMAGE_NAME_SIZE = 0x800;
class LoaderLightDef final : public AssetCreator<AssetLightDef>
{
public:
LoaderLightDef(MemoryManager& memory, ISearchPath& searchPath)
: m_memory(memory),
m_search_path(searchPath)
{
}
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto filename = GetAssetFilename(assetName);
const auto file = m_search_path.Open(filename);
if (!file.IsOpen())
return AssetCreationResult::NoAction();
const auto imageNameSize = file.m_length - sizeof(char) - sizeof(char);
if (imageNameSize < 0 || imageNameSize > MAX_IMAGE_NAME_SIZE)
return AssetCreationResult::Failure();
auto* lightDef = m_memory.Alloc<GfxLightDef>();
lightDef->name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetLightDef> registration(assetName, lightDef);
std::string imageName(static_cast<size_t>(imageNameSize), '\0');
int8_t samplerState;
int8_t lmapLookupStart;
file.m_stream->read(reinterpret_cast<char*>(&samplerState), sizeof(int8_t));
file.m_stream->read(&imageName[0], static_cast<size_t>(imageNameSize));
file.m_stream->read(reinterpret_cast<char*>(&lmapLookupStart), sizeof(int8_t));
auto* imageDependency = context.LoadDependency<AssetImage>(imageName);
if (!imageDependency)
{
std::cerr << std::format("Could not load GfxLightDef \"{}\" due to missing image \"{}\"\n", assetName, imageName);
return AssetCreationResult::Failure();
}
registration.AddDependency(imageDependency);
lightDef->attenuation.samplerState = samplerState;
lightDef->attenuation.image = imageDependency->Asset();
lightDef->lmapLookupStart = static_cast<int>(static_cast<uint8_t>(lmapLookupStart));
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
std::string GetAssetFilename(const std::string& assetName)
{
return std::format("lights/{}", assetName);
}
MemoryManager& m_memory;
ISearchPath& m_search_path;
};
} // namespace
namespace IW4
{
std::unique_ptr<AssetCreator<AssetLightDef>> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<LoaderLightDef>(memory, searchPath);
}
} // namespace IW4

View File

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

View File

@ -1,23 +0,0 @@
#include "AssetLoaderLocalizeIW4.h"
using namespace IW4;
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/IW4/IW4.h"
#include "Localize/CommonLocalizeLoader.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include "Zone/Zone.h"
namespace IW4
{
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 IW4

View File

@ -0,0 +1,43 @@
#include "AssetLoaderLocalizeIW4.h"
#include "Localize/CommonLocalizeLoader.h"
using namespace IW4;
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 IW4
{
std::unique_ptr<AssetCreator<AssetLocalize>> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
return std::make_unique<LocalizeLoader>(memory, searchPath, zone);
}
} // namespace IW4

View File

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

View File

@ -1,4 +1,4 @@
#include "AssetLoaderMaterial.h"
#include "LoaderMaterialIW4.h"
#include "AssetLoaderTechniqueSet.h"
#include "AssetLoading/AbstractGdtEntryReader.h"
@ -6,21 +6,25 @@
#include "Game/IW4/IW4.h"
#include "Game/IW4/MaterialConstantsIW4.h"
#include "Game/IW4/ObjConstantsIW4.h"
#include "Game/IW4/Techset/LoaderTechsetIW4.h"
#include "Game/IW4/TechsetConstantsIW4.h"
#include "ObjLoading.h"
#include "Pool/GlobalAssetPool.h"
#include "StateMap/StateMapFromTechniqueExtractor.h"
#include "StateMap/StateMapHandler.h"
#include "Techset/TechniqueFileReader.h"
#include "Techset/TechniqueStateMapCache.h"
#include "Techset/TechsetDefinitionCache.h"
#include <cmath>
#include <cstring>
#include <format>
#include <iostream>
#include <sstream>
using namespace IW4;
namespace IW4
namespace
{
class SkipMaterialException final : public std::exception
{
@ -29,39 +33,33 @@ namespace IW4
class MaterialGdtLoader : AbstractGdtEntryReader
{
public:
MaterialGdtLoader(const GdtEntry& entry, MemoryManager* memory, ISearchPath* searchPath, IAssetLoadingManager* manager)
MaterialGdtLoader(const GdtEntry& entry,
Material& material,
MemoryManager& memory,
ISearchPath& searchPath,
AssetCreationContext& context,
AssetRegistration<AssetMaterial>& registration)
: AbstractGdtEntryReader(entry),
m_material(material),
m_memory(memory),
m_search_path(searchPath),
m_manager(manager),
m_state_map_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<techset::TechniqueStateMapCache>()),
m_material(nullptr),
m_base_state_bits{}
m_context(context),
m_registration(registration),
m_state_map_cache(context.GetZoneAssetLoaderState<techset::TechniqueStateMapCache>()),
m_base_state_bits{},
m_techset_creator(CreateTechsetLoader(memory, searchPath))
{
}
bool Load()
{
m_material = m_memory->Create<Material>();
memset(m_material, 0, sizeof(Material));
m_material->info.name = m_memory->Dup(m_entry.m_name.c_str());
material_template();
FinalizeMaterial();
return true;
}
_NODISCARD Material* GetMaterial() const
{
return m_material;
}
_NODISCARD std::vector<XAssetInfoGeneric*> GetDependencies()
{
return std::move(m_dependencies);
}
private:
void material_template()
{
@ -120,11 +118,7 @@ namespace IW4
custom_template();
}
else
{
std::ostringstream ss;
ss << "Unknown material type: \"" << materialType << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Unknown material type: \"{}\"", materialType));
}
void mtl_phong_template()
@ -253,7 +247,7 @@ namespace IW4
else
throw GdtReadingException("ColorMap may not be blank in particle cloud materials");
std::cout << "Using particlecloud for \"" << m_material->info.name << "\"\n";
std::cout << std::format("Using particlecloud for \"{}\"\n", m_material.info.name);
}
void mtl_tools_template()
@ -332,11 +326,7 @@ namespace IW4
mtl_splatter_template();
}
else
{
std::ostringstream ss;
ss << "Unknown custom template: \"" << customTemplate << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Unknown custom template: \"{}\"", customTemplate));
}
void mtl_custom_template()
@ -584,11 +574,7 @@ namespace IW4
const auto sortKeyNum = strtoul(sortKey.c_str(), &endPtr, 10);
if (endPtr != &sortKey[sortKey.size()])
{
std::ostringstream ss;
ss << "Invalid sort value: \"" << sortKey << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Invalid sort value: \"{}\"", sortKey));
SetSort(static_cast<unsigned char>(sortKeyNum));
}
@ -628,11 +614,7 @@ namespace IW4
else if (alphaTest == GDT_ALPHA_TEST_GT0) // TODO: This is not available for IW3
SetAlphaTest(AlphaTest_e::GT0);
else
{
std::ostringstream ss;
ss << "Invalid alphatest value: \"" << alphaTest << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Invalid alphatest value: \"{}\"", alphaTest));
}
void blendfunc_template()
@ -682,9 +664,7 @@ namespace IW4
}
else
{
std::ostringstream ss;
ss << "Invalid blendfunc value: \"" << blendFunc << "\"";
throw GdtReadingException(ss.str());
throw GdtReadingException(std::format("Invalid blendfunc value: \"{}\"", blendFunc));
}
}
@ -740,9 +720,7 @@ namespace IW4
SetDepthWrite(false);
else
{
std::ostringstream ss;
ss << "Invalid depthWrite blendFunc value: \"" << blendFunc << "\"";
throw GdtReadingException(ss.str());
throw GdtReadingException(std::format("Invalid depthWrite blendFunc value: \"{}\"", blendFunc));
}
}
@ -807,28 +785,21 @@ namespace IW4
void SetTechniqueSet(const std::string& techsetName)
{
auto* techset = m_manager->LoadDependency<AssetTechniqueSet>(techsetName);
auto* techset = m_context.LoadDependency<AssetTechniqueSet>(techsetName);
if (techset == nullptr)
{
std::ostringstream ss;
ss << "Could not load techset: \"" << techsetName << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Could not load techset: \"{}\"", techsetName));
m_dependencies.push_back(techset);
m_material->techniqueSet = techset->Asset();
m_registration.AddDependency(techset);
m_material.techniqueSet = techset->Asset();
auto* loadingContext = m_manager->GetAssetLoadingContext();
auto& searchPath = loadingContext->m_raw_search_path;
auto* definitionCache = loadingContext->GetZoneAssetLoaderState<techset::TechsetDefinitionCache>();
auto* definitionCache = m_context.GetZoneAssetLoaderState<techset::TechsetDefinitionCache>();
const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, &searchPath, definitionCache);
bool failure = false;
const auto* techsetDefinition = m_techset_creator->LoadTechsetDefinition(techsetName, m_context, failure);
if (techsetDefinition == nullptr)
{
std::ostringstream ss;
ss << "Could not find techset definition for: \"" << techsetName << "\"";
throw GdtReadingException(ss.str());
throw GdtReadingException(std::format("Could not find techset definition for: \"{}\"", techsetName));
}
SetTechniqueSetStateBits(techsetDefinition);
@ -852,17 +823,17 @@ namespace IW4
if (foundStateBits != m_state_bits.end())
{
m_material->stateBitsEntry[i] = static_cast<unsigned char>(foundStateBits - m_state_bits.begin());
m_material.stateBitsEntry[i] = static_cast<unsigned char>(foundStateBits - m_state_bits.begin());
}
else
{
m_material->stateBitsEntry[i] = static_cast<unsigned char>(m_state_bits.size());
m_material.stateBitsEntry[i] = static_cast<unsigned char>(m_state_bits.size());
m_state_bits.push_back(stateBitsForTechnique);
}
}
else
{
m_material->stateBitsEntry[i] = std::numeric_limits<unsigned char>::max();
m_material.stateBitsEntry[i] = std::numeric_limits<unsigned char>::max();
}
}
}
@ -889,8 +860,8 @@ namespace IW4
if (preloadedStateMap)
return preloadedStateMap;
const auto techniqueFileName = AssetLoaderTechniqueSet::GetTechniqueFileName(techniqueName);
const auto file = m_search_path->Open(techniqueFileName);
const auto techniqueFileName = GetTechniqueFileName(techniqueName);
const auto file = m_search_path.Open(techniqueFileName);
if (!file.IsOpen())
return nullptr;
@ -903,7 +874,7 @@ namespace IW4
}
const auto stateMapName = extractor.RetrieveStateMap();
const auto* loadedStateMap = AssetLoaderTechniqueSet::LoadStateMapDefinition(stateMapName, m_search_path, m_state_map_cache);
const auto* loadedStateMap = m_techset_creator->LoadStateMapDefinition(stateMapName, m_context);
m_state_map_cache->SetTechniqueUsesStateMap(techniqueName, loadedStateMap);
return loadedStateMap;
@ -924,18 +895,18 @@ namespace IW4
std::string tempName;
if (techsetDefinition->GetTechniqueByIndex(TECHNIQUE_LIT, tempName))
{
if (m_material->info.sortKey >= SORTKEY_TRANS_START)
m_material->cameraRegion = CAMERA_REGION_LIT_TRANS;
if (m_material.info.sortKey >= SORTKEY_TRANS_START)
m_material.cameraRegion = CAMERA_REGION_LIT_TRANS;
else
m_material->cameraRegion = CAMERA_REGION_LIT_OPAQUE;
m_material.cameraRegion = CAMERA_REGION_LIT_OPAQUE;
}
else if (techsetDefinition->GetTechniqueByIndex(TECHNIQUE_EMISSIVE, tempName))
{
m_material->cameraRegion = CAMERA_REGION_EMISSIVE;
m_material.cameraRegion = CAMERA_REGION_EMISSIVE;
}
else
{
m_material->cameraRegion = CAMERA_REGION_NONE;
m_material.cameraRegion = CAMERA_REGION_NONE;
}
}
@ -993,16 +964,12 @@ namespace IW4
break;
}
auto* image = m_manager->LoadDependency<AssetImage>(textureName);
auto* image = m_context.LoadDependency<AssetImage>(textureName);
if (image == nullptr)
{
std::ostringstream ss;
ss << "Could not load image: \"" << textureName << "\"";
throw GdtReadingException(ss.str());
}
throw GdtReadingException(std::format("Could not load image: \"{}\"", textureName));
m_dependencies.push_back(image);
m_registration.AddDependency(image);
textureDef.u.image = image->Asset();
m_textures.push_back(textureDef);
@ -1023,13 +990,13 @@ namespace IW4
void SetSort(const unsigned char sort) const
{
m_material->info.sortKey = sort;
m_material.info.sortKey = sort;
}
void SetTextureAtlas(const unsigned char rowCount, const unsigned char columnCount) const
{
m_material->info.textureAtlasRowCount = rowCount;
m_material->info.textureAtlasColumnCount = columnCount;
m_material.info.textureAtlasRowCount = rowCount;
m_material.info.textureAtlasColumnCount = columnCount;
}
void SetAlphaTest(const AlphaTest_e alphaTest)
@ -1054,9 +1021,7 @@ namespace IW4
case AlphaTest_e::UNKNOWN:
default:
std::ostringstream ss;
ss << "Unknown alphatest value: \"" << static_cast<int>(alphaTest) << "\"";
throw GdtReadingException(ss.str());
throw GdtReadingException(std::format("Unknown alphatest value: \"{}\"", static_cast<int>(alphaTest)));
}
}
@ -1113,9 +1078,7 @@ namespace IW4
if (colorWriteRed != colorWriteGreen || colorWriteRed != colorWriteBlue)
{
std::ostringstream ss;
ss << "Invalid ColorWrite values: values for rgb must match";
throw GdtReadingException(ss.str());
throw GdtReadingException("Invalid ColorWrite values: values for rgb must match");
}
m_base_state_bits.loadBits[0] &= ~GFXS0_COLORWRITE_MASK;
@ -1286,38 +1249,38 @@ namespace IW4
{
if (!m_textures.empty())
{
m_material->textureTable = m_memory->Alloc<MaterialTextureDef>(m_textures.size());
m_material->textureCount = static_cast<unsigned char>(m_textures.size());
memcpy(m_material->textureTable, m_textures.data(), sizeof(MaterialTextureDef) * m_textures.size());
m_material.textureTable = m_memory.Alloc<MaterialTextureDef>(m_textures.size());
m_material.textureCount = static_cast<unsigned char>(m_textures.size());
std::memcpy(m_material.textureTable, m_textures.data(), sizeof(MaterialTextureDef) * m_textures.size());
}
else
{
m_material->textureTable = nullptr;
m_material->textureCount = 0u;
m_material.textureTable = nullptr;
m_material.textureCount = 0u;
}
if (!m_constants.empty())
{
m_material->constantTable = m_memory->Alloc<MaterialConstantDef>(m_constants.size());
m_material->constantCount = static_cast<unsigned char>(m_constants.size());
memcpy(m_material->constantTable, m_constants.data(), sizeof(MaterialConstantDef) * m_constants.size());
m_material.constantTable = m_memory.Alloc<MaterialConstantDef>(m_constants.size());
m_material.constantCount = static_cast<unsigned char>(m_constants.size());
std::memcpy(m_material.constantTable, m_constants.data(), sizeof(MaterialConstantDef) * m_constants.size());
}
else
{
m_material->constantTable = nullptr;
m_material->constantCount = 0u;
m_material.constantTable = nullptr;
m_material.constantCount = 0u;
}
if (!m_state_bits.empty())
{
m_material->stateBitsTable = m_memory->Alloc<GfxStateBits>(m_state_bits.size());
m_material->stateBitsCount = static_cast<unsigned char>(m_state_bits.size());
memcpy(m_material->stateBitsTable, m_state_bits.data(), sizeof(GfxStateBits) * m_state_bits.size());
m_material.stateBitsTable = m_memory.Alloc<GfxStateBits>(m_state_bits.size());
m_material.stateBitsCount = static_cast<unsigned char>(m_state_bits.size());
std::memcpy(m_material.stateBitsTable, m_state_bits.data(), sizeof(GfxStateBits) * m_state_bits.size());
}
else
{
m_material->stateBitsTable = nullptr;
m_material->stateBitsCount = 0u;
m_material.stateBitsTable = nullptr;
m_material.stateBitsCount = 0u;
}
}
@ -1330,9 +1293,7 @@ namespace IW4
return i;
}
std::ostringstream ss;
ss << "Unknown " << propertyName << " value: \"" << value << "\"";
throw GdtReadingException(ss.str());
throw GdtReadingException(std::format("Unknown {} value: \"{}\"", propertyName, value));
}
template<typename T> T ReadEnumProperty(const std::string& propertyName, const char** validValuesArray, const size_t validValuesArraySize) const
@ -1340,59 +1301,69 @@ namespace IW4
return static_cast<T>(GetIndexForString(propertyName, ReadStringProperty(propertyName), validValuesArray, validValuesArraySize));
}
MemoryManager* m_memory;
ISearchPath* m_search_path;
IAssetLoadingManager* m_manager;
Material& m_material;
MemoryManager& m_memory;
ISearchPath& m_search_path;
AssetCreationContext& m_context;
AssetRegistration<AssetMaterial>& m_registration;
techset::TechniqueStateMapCache* m_state_map_cache;
std::unordered_map<const state_map::StateMapDefinition*, GfxStateBits> m_state_bits_per_state_map;
std::vector<XAssetInfoGeneric*> m_dependencies;
Material* m_material;
GfxStateBits m_base_state_bits;
std::vector<GfxStateBits> m_state_bits;
std::vector<MaterialTextureDef> m_textures;
std::vector<MaterialConstantDef> m_constants;
std::unique_ptr<ITechsetCreator> m_techset_creator;
};
} // namespace IW4
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
auto* material = memory->Create<Material>();
memset(material, 0, sizeof(Material));
material->info.name = memory->Dup(assetName.c_str());
return material;
}
bool AssetLoaderMaterial::CanLoadFromGdt() const
{
return true;
}
bool AssetLoaderMaterial::LoadFromGdt(
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto* entry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_MATERIAL, assetName);
if (!entry)
return false;
MaterialGdtLoader loader(*entry, memory, &manager->GetAssetLoadingContext()->m_raw_search_path, manager);
try
class MaterialLoader final : public AssetCreator<AssetMaterial>
{
if (loader.Load())
public:
MaterialLoader(MemoryManager& memory, ISearchPath& searchPath);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
manager->AddAsset<AssetMaterial>(assetName, loader.GetMaterial(), loader.GetDependencies());
}
}
catch (const SkipMaterialException&)
{
return false;
}
catch (const GdtReadingException& e)
{
std::cerr << "Error while trying to load material from gdt: " << e.what() << " @ GdtEntry \"" << entry->m_name << "\"\n";
return false;
}
const auto* entry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_MATERIAL, assetName);
if (!entry)
return AssetCreationResult::NoAction();
return true;
}
auto* material = m_memory.Alloc<Material>();
material->info.name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetMaterial> registration(assetName, material);
MaterialGdtLoader loader(*entry, *material, m_memory, m_search_path, context, registration);
try
{
if (loader.Load())
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
catch (const SkipMaterialException&)
{
return AssetCreationResult::NoAction();
}
catch (const GdtReadingException& e)
{
std::cerr << std::format("Error while trying to load material from gdt: {} @ GdtEntry \"{}\"\n", e.what(), entry->m_name);
}
return AssetCreationResult::Failure();
}
private:
MemoryManager& m_memory;
ISearchPath& m_search_path;
IGdtQueryable& m_gdt;
};
} // namespace
namespace IW4
{
std::unique_ptr<AssetCreator<AssetMaterial>> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt)
{
return std::make_unique<MaterialLoader>(memory, searchPath, gdt);
}
} // namespace IW4

View File

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

View File

@ -0,0 +1,229 @@
#include "AssetLoaderMenuListIW4.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/Menu/MenuConversionZoneStateIW4.h"
#include "Game/IW4/Menu/MenuConverterIW4.h"
#include "ObjLoading.h"
#include "Parsing/Menu/MenuFileReader.h"
#include <cstring>
#include <format>
#include <iostream>
using namespace IW4;
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 IW4
{
std::unique_ptr<AssetCreator<AssetMenuList>> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath)
{
return std::make_unique<MenuListLoader>(memory, searchPath);
}
} // namespace IW4

View File

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

View File

@ -16,19 +16,17 @@
#include <cassert>
#include <cstring>
#include <format>
#include <sstream>
using namespace IW4;
using namespace menu;
namespace IW4
namespace
{
class MenuConverterImpl : public AbstractMenuConverter
class MenuConverter : public AbstractMenuConverter, public IMenuConverter
{
MenuConversionZoneState* m_conversion_zone_state;
MenuAssetZoneState* m_parsing_zone_state;
_NODISCARD static rectDef_s ConvertRectDef(const CommonRect& rect)
[[nodiscard]] static rectDef_s ConvertRectDef(const CommonRect& rect)
{
return rectDef_s{
static_cast<float>(rect.x),
@ -40,7 +38,7 @@ namespace IW4
};
}
_NODISCARD static rectDef_s ConvertRectDefRelativeTo(const CommonRect& rect, const CommonRect& rectRelativeTo)
[[nodiscard]] static rectDef_s ConvertRectDefRelativeTo(const CommonRect& rect, const CommonRect& rectRelativeTo)
{
return rectDef_s{
static_cast<float>(rectRelativeTo.x + rect.x),
@ -78,26 +76,26 @@ namespace IW4
return input;
}
_NODISCARD Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const
[[nodiscard]] Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const
{
if (materialName.empty())
return nullptr;
auto* materialDependency = m_manager->LoadDependency<AssetMaterial>(materialName);
auto* materialDependency = m_context.LoadDependency<AssetMaterial>(materialName);
if (!materialDependency)
throw MenuConversionException("Failed to load material \"" + materialName + "\"", menu, item);
throw MenuConversionException(std::format("Failed to load material \"{}\"", materialName), menu, item);
return materialDependency->Asset();
}
_NODISCARD snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const
[[nodiscard]] snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const
{
if (soundName.empty())
return nullptr;
auto* soundDependency = m_manager->LoadDependency<AssetSound>(soundName);
auto* soundDependency = m_context.LoadDependency<AssetSound>(soundName);
if (!soundDependency)
throw MenuConversionException("Failed to load sound \"" + soundName + "\"", menu, item);
throw MenuConversionException(std::format("Failed to load sound \"{}\"", soundName), menu, item);
return soundDependency->Asset();
}
@ -416,7 +414,7 @@ namespace IW4
if (!expression)
return nullptr;
auto* statement = m_memory->Create<Statement_s>();
auto* statement = m_memory.Alloc<Statement_s>();
statement->lastResult = Operand{};
statement->lastExecuteTime = 0;
statement->supportingData = nullptr; // Supporting data is set upon using it
@ -424,7 +422,7 @@ namespace IW4
std::vector<expressionEntry> expressionEntries;
ConvertExpressionEntry(statement, expressionEntries, expression, menu, item);
auto* outputExpressionEntries = m_memory->Alloc<expressionEntry>(expressionEntries.size());
auto* outputExpressionEntries = m_memory.Alloc<expressionEntry>(expressionEntries.size());
memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size());
statement->entries = outputExpressionEntries;
@ -481,7 +479,7 @@ namespace IW4
switch (value.m_type)
{
case SimpleExpressionValue::Type::STRING:
staticValue = m_memory->Dup(value.m_string_value->c_str());
staticValue = m_memory.Dup(value.m_string_value->c_str());
break;
case SimpleExpressionValue::Type::DOUBLE:
@ -586,13 +584,13 @@ namespace IW4
if (!setLocalVar)
return;
auto* outputHandler = m_memory->Alloc<MenuEventHandler>();
auto* outputSetLocalVar = m_memory->Alloc<SetLocalVarData>();
auto* outputHandler = m_memory.Alloc<MenuEventHandler>();
auto* outputSetLocalVar = m_memory.Alloc<SetLocalVarData>();
outputHandler->eventType = SetLocalVarTypeToEventType(setLocalVar->m_type);
outputHandler->eventData.setLocalVarData = outputSetLocalVar;
outputSetLocalVar->localVarName = m_memory->Dup(setLocalVar->m_var_name.c_str());
outputSetLocalVar->localVarName = m_memory.Dup(setLocalVar->m_var_name.c_str());
outputSetLocalVar->expression = ConvertExpression(setLocalVar->m_value.get(), menu, item);
elements.push_back(outputHandler);
@ -604,9 +602,9 @@ namespace IW4
if (!script)
return;
auto* outputHandler = m_memory->Create<MenuEventHandler>();
auto* outputHandler = m_memory.Alloc<MenuEventHandler>();
outputHandler->eventType = EVENT_UNCONDITIONAL;
outputHandler->eventData.unconditionalScript = m_memory->Dup(script->m_script.c_str());
outputHandler->eventData.unconditionalScript = m_memory.Dup(script->m_script.c_str());
elements.push_back(outputHandler);
}
@ -631,8 +629,8 @@ namespace IW4
}
else
{
auto* outputHandler = m_memory->Alloc<MenuEventHandler>();
auto* outputCondition = m_memory->Alloc<ConditionalScript>();
auto* outputHandler = m_memory.Alloc<MenuEventHandler>();
auto* outputCondition = m_memory.Alloc<ConditionalScript>();
outputHandler->eventType = EVENT_IF;
outputHandler->eventData.conditionalScript = outputCondition;
@ -644,7 +642,7 @@ namespace IW4
if (condition->m_else_elements)
{
auto* outputElseHandler = m_memory->Create<MenuEventHandler>();
auto* outputElseHandler = m_memory.Alloc<MenuEventHandler>();
outputElseHandler->eventType = EVENT_ELSE;
outputElseHandler->eventData.elseScript = ConvertEventHandlerSet(condition->m_else_elements.get(), menu, item);
@ -699,8 +697,8 @@ namespace IW4
if (elements.empty())
return nullptr;
auto* outputSet = m_memory->Alloc<MenuEventHandlerSet>();
auto* outputElements = m_memory->Alloc<MenuEventHandler*>(elements.size());
auto* outputSet = m_memory.Alloc<MenuEventHandlerSet>();
auto* outputElements = m_memory.Alloc<MenuEventHandler*>(elements.size());
memcpy(outputElements, elements.data(), sizeof(void*) * elements.size());
outputSet->eventHandlerCount = static_cast<int>(elements.size());
@ -717,7 +715,7 @@ namespace IW4
return nullptr;
const auto keyHandlerCount = keyHandlers.size();
auto* output = m_memory->Alloc<ItemKeyHandler>(keyHandlerCount);
auto* output = m_memory.Alloc<ItemKeyHandler>(keyHandlerCount);
auto currentKeyHandler = keyHandlers.cbegin();
for (auto i = 0u; i < keyHandlerCount; i++)
{
@ -829,7 +827,7 @@ namespace IW4
if (floatExpressionCount <= 0)
return nullptr;
auto* floatExpressions = m_memory->Alloc<ItemFloatExpression>(floatExpressionCount);
auto* floatExpressions = m_memory.Alloc<ItemFloatExpression>(floatExpressionCount);
auto floatExpressionIndex = 0;
for (const auto& [expression, expressionIsStatic, target, staticValue, staticValueArraySize, dynamicFlagsToSet] : locations)
{
@ -855,7 +853,7 @@ namespace IW4
ss << "\"" << element << "\" ";
}
return m_memory->Dup(ss.str().c_str());
return m_memory.Dup(ss.str().c_str());
}
_NODISCARD const char* ConvertEnableDvar(const CommonItemDef& commonItem, int& dvarFlags) const
@ -903,7 +901,7 @@ namespace IW4
if (commonListBox == nullptr)
return nullptr;
auto* listBox = m_memory->Alloc<listBoxDef_s>();
auto* listBox = m_memory.Alloc<listBoxDef_s>();
listBox->notselectable = commonListBox->m_not_selectable ? 1 : 0;
listBox->noScrollBars = commonListBox->m_no_scrollbars ? 1 : 0;
listBox->usePaging = commonListBox->m_use_paging ? 1 : 0;
@ -938,7 +936,7 @@ namespace IW4
if (commonEditField == nullptr)
return nullptr;
auto* editField = m_memory->Alloc<editFieldDef_s>();
auto* editField = m_memory.Alloc<editFieldDef_s>();
editField->defVal = static_cast<float>(commonEditField->m_def_val);
editField->minVal = static_cast<float>(commonEditField->m_min_val);
editField->maxVal = static_cast<float>(commonEditField->m_max_val);
@ -958,7 +956,7 @@ namespace IW4
if (commonMultiValue == nullptr)
return nullptr;
auto* multiValue = m_memory->Alloc<multiDef_s>();
auto* multiValue = m_memory.Alloc<multiDef_s>();
multiValue->count = static_cast<int>(std::min(std::extent_v<decltype(multiDef_s::dvarList)>, commonMultiValue->m_step_names.size()));
multiValue->strDef = !commonMultiValue->m_string_values.empty() ? 1 : 0;
@ -989,7 +987,7 @@ namespace IW4
if (commonNewsTicker == nullptr)
return nullptr;
auto* newsTicker = m_memory->Alloc<newsTickerDef_s>();
auto* newsTicker = m_memory.Alloc<newsTickerDef_s>();
newsTicker->spacing = commonNewsTicker->m_spacing;
newsTicker->speed = commonNewsTicker->m_speed;
newsTicker->feedId = commonNewsTicker->m_news_feed_id;
@ -999,8 +997,7 @@ namespace IW4
_NODISCARD itemDef_s* ConvertItem(const CommonMenuDef& parentMenu, const CommonItemDef& commonItem) const
{
auto* item = m_memory->Create<itemDef_s>();
memset(item, 0, sizeof(itemDef_s));
auto* item = m_memory.Alloc<itemDef_s>();
item->window.name = ConvertString(commonItem.m_name);
item->text = ConvertString(commonItem.m_text);
@ -1087,7 +1084,7 @@ namespace IW4
case CommonItemFeatureType::NONE:
default:
if (item->type == ITEM_TYPE_TEXT_SCROLL)
item->typeData.scroll = m_memory->Alloc<textScrollDef_s>();
item->typeData.scroll = m_memory.Alloc<textScrollDef_s>();
break;
}
@ -1103,7 +1100,7 @@ namespace IW4
return nullptr;
}
auto* items = m_memory->Alloc<itemDef_s*>(commonMenu.m_items.size());
auto* items = m_memory.Alloc<itemDef_s*>(commonMenu.m_items.size());
for (auto i = 0u; i < commonMenu.m_items.size(); i++)
items[i] = ConvertItem(commonMenu, *commonMenu.m_items[i]);
@ -1113,98 +1110,75 @@ namespace IW4
}
public:
MenuConverterImpl(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
: AbstractMenuConverter(disableOptimizations, searchPath, memory, manager),
m_conversion_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuConversionZoneState>()),
m_parsing_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuAssetZoneState>())
MenuConverter(const bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context)
: AbstractMenuConverter(disableOptimizations, searchPath, memory, context),
m_conversion_zone_state(context.GetZoneAssetLoaderState<MenuConversionZoneState>()),
m_parsing_zone_state(context.GetZoneAssetLoaderState<MenuAssetZoneState>())
{
assert(m_conversion_zone_state);
assert(m_parsing_zone_state);
}
_NODISCARD menuDef_t* ConvertMenu(const CommonMenuDef& commonMenu) const
void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration<AssetMenu>& registration) override
{
auto* menu = m_memory->Create<menuDef_t>();
memset(menu, 0, sizeof(menuDef_t));
menu->window.name = m_memory->Dup(commonMenu.m_name.c_str());
menu->fullScreen = commonMenu.m_full_screen;
ApplyFlag(menu->window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE);
ApplyFlag(menu->window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION);
menu->window.rect = ConvertRectDef(commonMenu.m_rect);
menu->window.style = commonMenu.m_style;
menu->window.border = commonMenu.m_border;
menu->window.borderSize = static_cast<float>(commonMenu.m_border_size);
ConvertColor(menu->window.backColor, commonMenu.m_back_color);
ConvertColor(menu->window.foreColor, commonMenu.m_fore_color);
ConvertColor(menu->window.borderColor, commonMenu.m_border_color);
ConvertColor(menu->focusColor, commonMenu.m_focus_color);
menu->window.background = ConvertMaterial(commonMenu.m_background, &commonMenu);
menu->window.ownerDraw = commonMenu.m_owner_draw;
menu->window.ownerDrawFlags = commonMenu.m_owner_draw_flags;
ApplyFlag(menu->window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK);
menu->soundName = ConvertString(commonMenu.m_sound_loop);
ApplyFlag(menu->window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP);
menu->fadeClamp = static_cast<float>(commonMenu.m_fade_clamp);
menu->fadeCycle = commonMenu.m_fade_cycle;
menu->fadeAmount = static_cast<float>(commonMenu.m_fade_amount);
menu->fadeInAmount = static_cast<float>(commonMenu.m_fade_in_amount);
menu->blurRadius = static_cast<float>(commonMenu.m_blur_radius);
ApplyFlag(menu->window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE);
ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE);
ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG);
ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI);
menu->allowedBinding = ConvertString(commonMenu.m_allowed_binding);
ApplyFlag(menu->window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS);
menu->visibleExp = ConvertVisibleExpression(&menu->window, commonMenu.m_visible_expression.get(), &commonMenu);
menu->rectXExp = ConvertOrApplyStatement(menu->window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu);
menu->rectYExp = ConvertOrApplyStatement(menu->window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu);
menu->rectWExp = ConvertOrApplyStatement(menu->window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu);
menu->rectHExp = ConvertOrApplyStatement(menu->window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu);
menu->openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu);
menu->closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu);
menu->onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu);
menu->onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu);
menu->onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu);
menu->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu);
menu->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu);
menu->items = ConvertMenuItems(commonMenu, menu->itemCount);
menu->expressionData = m_conversion_zone_state->m_supporting_data;
return menu;
try
{
menu.window.name = m_memory.Dup(commonMenu.m_name.c_str());
menu.fullScreen = commonMenu.m_full_screen;
ApplyFlag(menu.window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE);
ApplyFlag(menu.window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION);
menu.window.rect = ConvertRectDef(commonMenu.m_rect);
menu.window.style = commonMenu.m_style;
menu.window.border = commonMenu.m_border;
menu.window.borderSize = static_cast<float>(commonMenu.m_border_size);
ConvertColor(menu.window.backColor, commonMenu.m_back_color);
ConvertColor(menu.window.foreColor, commonMenu.m_fore_color);
ConvertColor(menu.window.borderColor, commonMenu.m_border_color);
ConvertColor(menu.focusColor, commonMenu.m_focus_color);
menu.window.background = ConvertMaterial(commonMenu.m_background, &commonMenu);
menu.window.ownerDraw = commonMenu.m_owner_draw;
menu.window.ownerDrawFlags = commonMenu.m_owner_draw_flags;
ApplyFlag(menu.window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK);
menu.soundName = ConvertString(commonMenu.m_sound_loop);
ApplyFlag(menu.window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP);
menu.fadeClamp = static_cast<float>(commonMenu.m_fade_clamp);
menu.fadeCycle = commonMenu.m_fade_cycle;
menu.fadeAmount = static_cast<float>(commonMenu.m_fade_amount);
menu.fadeInAmount = static_cast<float>(commonMenu.m_fade_in_amount);
menu.blurRadius = static_cast<float>(commonMenu.m_blur_radius);
ApplyFlag(menu.window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE);
ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE);
ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG);
ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI);
menu.allowedBinding = ConvertString(commonMenu.m_allowed_binding);
ApplyFlag(menu.window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS);
menu.visibleExp = ConvertVisibleExpression(&menu.window, commonMenu.m_visible_expression.get(), &commonMenu);
menu.rectXExp = ConvertOrApplyStatement(menu.window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu);
menu.rectYExp = ConvertOrApplyStatement(menu.window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu);
menu.rectWExp = ConvertOrApplyStatement(menu.window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu);
menu.rectHExp = ConvertOrApplyStatement(menu.window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu);
menu.openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu);
menu.closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu);
menu.onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu);
menu.onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu);
menu.onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu);
menu.onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu);
menu.onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu);
menu.items = ConvertMenuItems(commonMenu, menu.itemCount);
menu.expressionData = m_conversion_zone_state->m_supporting_data;
}
catch (const MenuConversionException& e)
{
PrintConversionExceptionDetails(e);
}
}
std::vector<XAssetInfoGeneric*> m_dependencies;
MenuConversionZoneState* m_conversion_zone_state;
MenuAssetZoneState* m_parsing_zone_state;
};
} // namespace IW4
} // namespace
MenuConverter::MenuConverter(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
: m_disable_optimizations(disableOptimizations),
m_search_path(searchPath),
m_memory(memory),
m_manager(manager)
std::unique_ptr<IMenuConverter> IMenuConverter::Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context)
{
}
std::vector<XAssetInfoGeneric*>& MenuConverter::GetDependencies()
{
return m_dependencies;
}
menuDef_t* MenuConverter::ConvertMenu(const CommonMenuDef& commonMenu)
{
MenuConverterImpl impl(m_disable_optimizations, m_search_path, m_memory, m_manager);
try
{
auto* result = impl.ConvertMenu(commonMenu);
m_dependencies = std::move(impl.m_dependencies);
return result;
}
catch (const MenuConversionException& e)
{
MenuConverterImpl::PrintConversionExceptionDetails(e);
}
return nullptr;
return std::make_unique<MenuConverter>(disableOptimizations, searchPath, memory, context);
}

View File

@ -1,26 +1,21 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "Asset/AssetCreationContext.h"
#include "Game/IW4/IW4.h"
#include "Parsing/Menu/Domain/CommonMenuDef.h"
#include "SearchPath/ISearchPath.h"
#include "Utils/ClassUtils.h"
#include "Utils/MemoryManager.h"
namespace IW4
{
class MenuConverter
class IMenuConverter
{
bool m_disable_optimizations;
ISearchPath* m_search_path;
MemoryManager* m_memory;
IAssetLoadingManager* m_manager;
std::vector<XAssetInfoGeneric*> m_dependencies;
public:
MenuConverter(bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
IMenuConverter() = default;
virtual ~IMenuConverter() = default;
std::vector<XAssetInfoGeneric*>& GetDependencies();
_NODISCARD menuDef_t* ConvertMenu(const menu::CommonMenuDef& commonMenu);
virtual void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration<AssetMenu>& registration) = 0;
static std::unique_ptr<IMenuConverter> Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context);
};
} // namespace IW4

View File

@ -3,8 +3,24 @@
#include "Asset/GlobalAssetPoolsLoader.h"
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/IW4.h"
#include "Localize/AssetLoaderLocalizeIW4.h"
#include "Leaderboard/LoaderLeaderboardIW4.h"
#include "LightDef/LoaderLightDefIW4.h"
#include "Localize/LoaderLocalizeIW4.h"
#include "Material/LoaderMaterialIW4.h"
#include "Menu/LoaderMenuListIW4.h"
#include "ObjLoading.h"
#include "PhysPreset/GdtLoaderPhysPresetIW4.h"
#include "PhysPreset/RawLoaderPhysPresetIW4.h"
#include "RawFile/LoaderRawFileIW4.h"
#include "Shader/LoaderPixelShaderIW4.h"
#include "Shader/LoaderVertexShaderIW4.h"
#include "Sound/LoaderSoundCurveIW4.h"
#include "StringTable/LoaderStringTableIW4.h"
#include "StructuredDataDef/LoaderStructuredDataDefIW4.h"
#include "Techset/LoaderTechsetIW4.h"
#include "Techset/LoaderVertexDeclIW4.h"
#include "Weapon/GdtLoaderWeaponIW4.h"
#include "Weapon/RawLoaderWeaponIW4.h"
#include <memory>
@ -100,23 +116,24 @@ namespace
collection.AddAssetCreator(std::make_unique<GlobalAssetPoolsLoader<AssetAddonMapEnts>>(zone));
}
void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath)
void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt)
{
auto& memory = *zone.GetMemory();
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysPreset>(memory));
collection.AddAssetCreator(std::make_unique<RawLoaderPhysPreset>(memory, searchPath, zone));
collection.AddAssetCreator(std::make_unique<GdtLoaderPhysPreset>(memory, gdt, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPhysCollMap>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModelSurfs>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderXModel>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMaterial>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderPixelShader>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVertexShader>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVertexDecl>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath, gdt));
collection.AddAssetCreator(CreatePixelShaderLoader(memory, searchPath));
collection.AddAssetCreator(CreateVertexShaderLoader(memory, searchPath));
collection.AddAssetCreator(CreateVertexDeclLoader(memory));
collection.AddAssetCreator(CreateTechsetLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImage>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSound>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundCurve>(memory));
collection.AddAssetCreator(CreateSoundCurveLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLoadedSound>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderClipMapSp>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderClipMapMp>(memory));
@ -126,27 +143,28 @@ namespace
// collection.AddAssetCreator(std::make_unique<AssetLoaderMapEnts>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFxWorld>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderGfxWorld>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLightDef>(memory));
collection.AddAssetCreator(CreateLightDefLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFont>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenuList>(memory));
collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderMenu>(memory));
collection.AddAssetCreator(std::make_unique<AssetLoaderLocalize>(memory, searchPath, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderWeapon>(memory));
collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone));
collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone));
// collection.AddAssetCreator(std::make_unique<AssetLoaderFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderImpactFx>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderRawFile>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderStringTable>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderLeaderboard>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderStructuredDataDef>(memory));
collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath));
collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath));
collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath));
collection.AddAssetCreator(CreateStructuredDataDefLoader(memory, searchPath));
// collection.AddAssetCreator(std::make_unique<AssetLoaderTracer>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderVehicle>(memory));
// collection.AddAssetCreator(std::make_unique<AssetLoaderAddonMapEnts>(memory));
}
} // namespace
void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) const
void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const
{
ConfigureDefaultCreators(collection, zone);
ConfigureLoaders(collection, zone, searchPath);
ConfigureLoaders(collection, zone, searchPath, gdt);
ConfigureGlobalAssetPoolsLoaders(collection, zone);
}

View File

@ -13,6 +13,6 @@ namespace IW4
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) const override;
void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override;
};
} // namespace IW4

View File

@ -0,0 +1,35 @@
#include "GdtLoaderPhysPresetIW4.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/ObjConstantsIW4.h"
#include "InfoString/InfoString.h"
#include "InfoStringLoaderPhysPresetIW4.h"
#include <format>
#include <iostream>
using namespace IW4;
GdtLoaderPhysPreset::GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone)
: m_memory(memory),
m_gdt(gdt),
m_zone(zone)
{
}
AssetCreationResult GdtLoaderPhysPreset::CreateAsset(const std::string& assetName, AssetCreationContext& context)
{
auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName);
if (gdtEntry == nullptr)
return AssetCreationResult::NoAction();
InfoString infoString;
if (!infoString.FromGdtProperties(*gdtEntry))
{
std::cerr << std::format("Failed to read phys preset gdt entry: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone);
return infoStringLoader.CreateAsset(assetName, infoString, context);
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "Asset/IAssetCreator.h"
#include "Game/IW4/IW4.h"
#include "Gdt/IGdtQueryable.h"
#include "Utils/MemoryManager.h"
namespace IW4
{
class GdtLoaderPhysPreset final : public AssetCreator<AssetPhysPreset>
{
public:
GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone);
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override;
private:
MemoryManager& m_memory;
IGdtQueryable& m_gdt;
Zone& m_zone;
};
} // namespace IW4

View File

@ -0,0 +1,86 @@
#include "InfoStringLoaderPhysPresetIW4.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
#include "Game/IW4/PhysPreset/PhysPresetFields.h"
#include <cassert>
#include <cstring>
#include <format>
#include <iostream>
#include <limits>
using namespace IW4;
namespace
{
class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter
{
public:
InfoStringToPhysPresetConverter(const InfoString& infoString,
void* structure,
ZoneScriptStrings& zoneScriptStrings,
MemoryManager& memory,
AssetCreationContext& context,
GenericAssetRegistration& registration,
const cspField_t* fields,
size_t fieldCount)
: InfoStringToStructConverter(infoString, structure, zoneScriptStrings, memory, context, registration, fields, fieldCount)
{
}
protected:
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
{
assert(false);
return false;
}
};
void CopyFromPhysPresetInfo(const PhysPresetInfo& physPresetInfo, PhysPreset& physPreset)
{
physPreset.mass = std::clamp(physPresetInfo.mass, 1.0f, 2000.0f) * 0.001f;
physPreset.bounce = physPresetInfo.bounce;
if (physPresetInfo.isFrictionInfinity != 0)
physPreset.friction = std::numeric_limits<float>::infinity();
else
physPreset.friction = physPresetInfo.friction;
physPreset.bulletForceScale = physPresetInfo.bulletForceScale;
physPreset.explosiveForceScale = physPresetInfo.explosiveForceScale;
physPreset.sndAliasPrefix = physPresetInfo.sndAliasPrefix;
physPreset.piecesSpreadFraction = physPresetInfo.piecesSpreadFraction;
physPreset.piecesUpwardVelocity = physPresetInfo.piecesUpwardVelocity;
physPreset.tempDefaultToCylinder = physPresetInfo.tempDefaultToCylinder != 0;
physPreset.perSurfaceSndAlias = physPresetInfo.perSurfaceSndAlias != 0;
}
} // namespace
InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone)
: m_memory(memory),
m_zone(zone)
{
}
AssetCreationResult InfoStringLoaderPhysPreset::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context)
{
PhysPresetInfo presetInfo;
std::memset(&presetInfo, 0, sizeof(presetInfo));
auto* physPreset = m_memory.Alloc<PhysPreset>();
AssetRegistration<AssetPhysPreset> registration(assetName, physPreset);
InfoStringToPhysPresetConverter converter(
infoString, &presetInfo, m_zone.m_script_strings, m_memory, context, registration, phys_preset_fields, std::extent_v<decltype(phys_preset_fields)>);
if (!converter.Convert())
{
std::cerr << std::format("Failed to parse phys preset: \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
CopyFromPhysPresetInfo(presetInfo, *physPreset);
physPreset->name = m_memory.Dup(assetName.c_str());
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}

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