Add AssetLoaders for linker that handle asset types for their specific game

This commit is contained in:
Jan 2021-03-12 10:55:55 +01:00
parent 792509d11d
commit b360816190
11 changed files with 223 additions and 9 deletions

View File

@ -0,0 +1,12 @@
#include "AssetLoadingContext.h"
AssetLoadingContext::AssetLoadingContext()
: m_asset_search_path(nullptr)
{
}
AssetLoadingContext::AssetLoadingContext(std::string zoneName, ISearchPath* assetSearchPath)
: m_asset_search_path(assetSearchPath),
m_zone_name(std::move(zoneName))
{
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include "SearchPath/ISearchPath.h"
#include "Obj/Gdt/Gdt.h"
class AssetLoadingContext
{
public:
ISearchPath* m_asset_search_path;
std::string m_zone_name;
std::string m_game_name;
std::vector<std::unique_ptr<Gdt>> m_gdt_files;
AssetLoadingContext();
AssetLoadingContext(std::string zoneName, ISearchPath* assetSearchPath);
};

View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
#include "Utils/ClassUtils.h"
#include "AssetLoadingContext.h"
#include "Zone/Zone.h"
class IAssetLoader
{
public:
IAssetLoader() = default;
virtual ~IAssetLoader() = default;
IAssetLoader(const IAssetLoader& other) = default;
IAssetLoader(IAssetLoader&& other) noexcept = default;
IAssetLoader& operator=(const IAssetLoader& other) = default;
IAssetLoader& operator=(IAssetLoader&& other) noexcept = default;
_NODISCARD virtual bool SupportsGame(const std::string& gameName) const = 0;
_NODISCARD virtual std::unique_ptr<Zone> CreateZoneForDefinition(AssetLoadingContext& context) const = 0;
};

View File

@ -0,0 +1,22 @@
#include "AssetLoaderIW4.h"
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/GameAssetPoolIW4.h"
using namespace IW4;
bool AssetLoader::SupportsGame(const std::string& gameName) const
{
return gameName == g_GameIW4.GetShortName();
}
std::unique_ptr<Zone> AssetLoader::CreateZoneForDefinition(AssetLoadingContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_zone_name, 0, &g_GameIW4);
zone->m_pools = std::make_unique<GameAssetPoolIW4>(zone.get(), zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
return zone;
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
namespace IW4
{
class AssetLoader final : public IAssetLoader
{
public:
_NODISCARD bool SupportsGame(const std::string& gameName) const override;
_NODISCARD std::unique_ptr<Zone> CreateZoneForDefinition(AssetLoadingContext& context) const override;
};
}

View File

@ -0,0 +1,23 @@
#include "AssetLoaderT6.h"
#include "Game/T6/T6.h"
#include "Game/T6/GameT6.h"
#include "Game/T6/GameAssetPoolT6.h"
using namespace T6;
bool AssetLoader::SupportsGame(const std::string& gameName) const
{
return gameName == g_GameT6.GetShortName();
}
std::unique_ptr<Zone> AssetLoader::CreateZoneForDefinition(AssetLoadingContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_zone_name, 0, &g_GameT6);
zone->m_pools = std::make_unique<GameAssetPoolT6>(zone.get(), zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
return zone;
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
namespace T6
{
class AssetLoader final : public IAssetLoader
{
public:
_NODISCARD bool SupportsGame(const std::string& gameName) const override;
_NODISCARD std::unique_ptr<Zone> CreateZoneForDefinition(AssetLoadingContext& context) const override;
};
}

View File

@ -15,6 +15,10 @@
#include "SearchPath/SearchPathFilesystem.h"
#include "ObjContainer/IWD/IWD.h"
#include "LinkerArgs.h"
#include "AssetLoading/AssetLoadingContext.h"
#include "AssetLoading/IAssetLoader.h"
#include "Game/IW4/AssetLoaderIW4.h"
#include "Game/T6/AssetLoaderT6.h"
#include "Utils/ObjFileStream.h"
#include "Zone/AssetList/AssetList.h"
@ -23,8 +27,17 @@
namespace fs = std::filesystem;
const IAssetLoader* const ASSET_LOADERS[]
{
new IW4::AssetLoader(),
new T6::AssetLoader()
};
class Linker::Impl
{
static constexpr const char* METADATA_GAME = "game";
static constexpr const char* METADATA_GDT = "gdt";
LinkerArgs m_args;
std::vector<std::unique_ptr<ISearchPath>> m_loaded_zone_search_paths;
SearchPaths m_asset_search_paths;
@ -356,10 +369,91 @@ class Linker::Impl
return true;
}
std::unique_ptr<Zone> CreateZoneForDefinition(const std::string& zoneName, ZoneDefinition& zoneDefinition)
static bool GetGameNameFromZoneDefinition(std::string& gameName, const std::string& zoneName, const ZoneDefinition& zoneDefinition)
{
auto firstGameEntry = true;
const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata.equal_range(METADATA_GAME);
for (auto i = rangeBegin; i != rangeEnd; ++i)
{
if (firstGameEntry)
{
gameName = i->second;
firstGameEntry = false;
}
else
{
if (gameName != i->second)
{
std::cout << "Conflicting game names in zone \"" << zoneName << "\": " << gameName << " != " << i->second << std::endl;
return false;
}
}
}
if (firstGameEntry)
{
std::cout << "No game name was specified for zone \"" << zoneName << "\"" << std::endl;
return false;
}
return true;
}
static bool LoadGdtFilesFromZoneDefinition(std::vector<std::unique_ptr<Gdt>>& gdtList, const std::string& zoneName, const ZoneDefinition& zoneDefinition, ISearchPath* gdtSearchPath)
{
const auto [rangeBegin, rangeEnd] = zoneDefinition.m_metadata.equal_range(METADATA_GDT);
for (auto i = rangeBegin; i != rangeEnd; ++i)
{
const auto gdtFile = gdtSearchPath->Open(i->second + ".gdt");
if(!gdtFile)
{
std::cout << "Failed to open file for gdt \"" << i->second << "\"" << std::endl;
return false;
}
GdtReader gdtReader(*gdtFile);
auto gdt = std::make_unique<Gdt>();
if(!gdtReader.Read(*gdt))
{
std::cout << "Failed to read gdt file \"" << i->second << "\"" << std::endl;
return false;
}
gdtList.emplace_back(std::move(gdt));
}
return true;
}
std::unique_ptr<Zone> CreateZoneForDefinition(const std::string& zoneName, ZoneDefinition& zoneDefinition, ISearchPath* assetSearchPath, ISearchPath* gdtSearchPath) const
{
auto context = std::make_unique<AssetLoadingContext>(zoneName, assetSearchPath);
if (!GetGameNameFromZoneDefinition(context->m_game_name, zoneName, zoneDefinition))
return nullptr;
if (!LoadGdtFilesFromZoneDefinition(context->m_gdt_files, zoneName, zoneDefinition, gdtSearchPath))
return nullptr;
for(const auto* assetLoader : ASSET_LOADERS)
{
if(assetLoader->SupportsGame(context->m_game_name))
return assetLoader->CreateZoneForDefinition(*context);
}
return nullptr;
}
bool WriteZoneToFile(Zone* zone)
{
fs::path zoneFilePath(m_args.GetOutputFolderPathForZone(zone->m_name));
zoneFilePath.append(zone->m_name + ".ff");
std::ifstream stream(zoneFilePath);
if (!stream.is_open())
return false;
stream.close();
return true;
}
bool BuildZone(const std::string& zoneName)
{
@ -374,7 +468,10 @@ class Linker::Impl
return false;
}
const auto zone = CreateZoneForDefinition(zoneName, *zoneDefinition);
const auto zone = CreateZoneForDefinition(zoneName, *zoneDefinition, &assetSearchPaths, &gdtSearchPaths);
auto result = zone != nullptr;
if (zone)
result = WriteZoneToFile(zone.get());
for(const auto& loadedSearchPath : m_loaded_zone_search_paths)
{
@ -382,7 +479,7 @@ class Linker::Impl
}
m_loaded_zone_search_paths.clear();
return true;
return result;
}
public:

View File

@ -20,5 +20,5 @@ SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData()
void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinition* state, SequenceResult<SimpleParserValue>& result) const
{
state->m_metadata[result.NextCapture(CAPTURE_KEY).IdentifierValue()] = result.NextCapture(CAPTURE_VALUE).IdentifierValue();
state->m_metadata.insert(std::make_pair(result.NextCapture(CAPTURE_KEY).IdentifierValue(), result.NextCapture(CAPTURE_VALUE).IdentifierValue()));
}

View File

@ -16,10 +16,7 @@ void ZoneDefinition::Include(ZoneDefinition& definitionToInclude)
{
for(const auto& [key, value] : definitionToInclude.m_metadata)
{
if(m_metadata.find(key) == m_metadata.end())
{
m_metadata.emplace(std::make_pair(key, value));
}
m_metadata.emplace(std::make_pair(key, value));
}
for(const auto& ignore : definitionToInclude.m_ignores)

View File

@ -17,7 +17,7 @@ public:
class ZoneDefinition
{
public:
std::unordered_map<std::string, std::string> m_metadata;
std::unordered_multimap<std::string, std::string> m_metadata;
std::vector<std::string> m_includes;
std::vector<std::string> m_ignores;
std::vector<ZoneDefinitionEntry> m_assets;