From 8de849dc85af577e96a8f6de8d5b38cc1f65e7ca Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 20 Jan 2024 16:32:11 +0100 Subject: [PATCH] feat: add iw3 StringTable loading via generic loader --- .../AssetLoaders/AssetLoaderStringTable.cpp | 39 ++++++++ .../IW3/AssetLoaders/AssetLoaderStringTable.h | 17 ++++ .../StringTable/StringTableLoader.h | 89 +++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp create mode 100644 src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h create mode 100644 src/ObjLoading/StringTable/StringTableLoader.h diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp new file mode 100644 index 00000000..895f2b24 --- /dev/null +++ b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp @@ -0,0 +1,39 @@ +#include "AssetLoaderStringTable.h" + +#include "Csv/CsvStream.h" +#include "Game/IW3/CommonIW3.h" +#include "ObjLoading.h" +#include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" + +#include + +using namespace IW3; + +void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +{ + auto* stringTable = memory->Create(); + 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::StringTableLoaderV1 loader; + auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); + + manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); + + return true; +} diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h new file mode 100644 index 00000000..ec7bebb1 --- /dev/null +++ b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h @@ -0,0 +1,17 @@ +#pragma once + +#include "AssetLoading/BasicAssetLoader.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" + +namespace IW3 +{ + class AssetLoaderStringTable final : public BasicAssetLoader + { + 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 IW3 diff --git a/src/ObjLoading/StringTable/StringTableLoader.h b/src/ObjLoading/StringTable/StringTableLoader.h new file mode 100644 index 00000000..b685030b --- /dev/null +++ b/src/ObjLoading/StringTable/StringTableLoader.h @@ -0,0 +1,89 @@ +#pragma once + +#include "Csv/CsvStream.h" + +#include +#include +#include +#include + +namespace string_table +{ + template class AbstractStringTableLoader + { + protected: + AbstractStringTableLoader() = default; + virtual ~AbstractStringTableLoader() = default; + AbstractStringTableLoader(const AbstractStringTableLoader& other) = default; + AbstractStringTableLoader(AbstractStringTableLoader&& other) noexcept = default; + AbstractStringTableLoader& operator=(const AbstractStringTableLoader& other) = default; + AbstractStringTableLoader& operator=(AbstractStringTableLoader&& other) noexcept = default; + + virtual void SetCellContent(CellType& cell, const char* content) = 0; + + virtual void PostProcessStringTable(StringTableType* stringTable, const unsigned cellCount, MemoryManager& memory) {} + + public: + StringTableType* LoadFromStream(const std::string& assetName, MemoryManager& memory, std::istream& stream) + { + auto* stringTable = memory.Create(); + stringTable->name = memory.Dup(assetName.c_str()); + + std::vector> csvLines; + std::vector currentLine; + auto maxCols = 0u; + const CsvInputStream csv(stream); + + while (csv.NextRow(currentLine)) + { + if (currentLine.size() > maxCols) + maxCols = currentLine.size(); + csvLines.emplace_back(std::move(currentLine)); + currentLine = std::vector(); + } + + stringTable->columnCount = static_cast(maxCols); + stringTable->rowCount = static_cast(csvLines.size()); + const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); + + if (cellCount) + { + stringTable->values = static_cast(memory.Alloc(sizeof(CellType) * cellCount)); + + for (auto row = 0u; row < csvLines.size(); row++) + { + const auto& rowValues = csvLines[row]; + for (auto col = 0u; col < maxCols; col++) + { + auto& cell = stringTable->values[row * maxCols + col]; + if (col >= rowValues.size() || rowValues[col].empty()) + SetCellContent(cell, ""); + else + SetCellContent(cell, memory.Dup(rowValues[col].c_str())); + } + } + } + else + { + stringTable->values = nullptr; + } + + PostProcessStringTable(stringTable, cellCount, memory); + + return stringTable; + } + }; + + // ================================= + // V1: IW3 + // - Cells are const char* + // ================================= + template class StringTableLoaderV1 final : public AbstractStringTableLoader + { + protected: + void SetCellContent(const char*& cell, const char* content) override + { + cell = content; + } + }; +} // namespace string_table