#include "AssetLoaderStructuredDataDefSet.h" #include "Game/IW4/IW4.h" #include "ObjLoading.h" #include "Pool/GlobalAssetPool.h" #include "StructuredDataDef/StructuredDataDefReader.h" #include "Utils/Alignment.h" #include using namespace IW4; void* AssetLoaderStructuredDataDefSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) { auto* structuredDataDefSet = memory->Create(); 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(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 = static_cast(memory->Alloc(sizeof(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(inputEntry.m_value); } } else outputEnum->entries = nullptr; } void AssetLoaderStructuredDataDefSet::ConvertStruct(StructuredDataStruct* outputStruct, CommonStructuredDataStruct* inputStruct, MemoryManager* memory) { outputStruct->size = static_cast(inputStruct->m_size_in_byte); outputStruct->bitOffset = inputStruct->m_bit_offset; outputStruct->propertyCount = static_cast(inputStruct->m_properties.size()); inputStruct->SortPropertiesByName(); if (!inputStruct->m_properties.empty()) { outputStruct->properties = static_cast(memory->Alloc(sizeof(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(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(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(inputDef->m_enums.size()); if (!inputDef->m_enums.empty()) { outputDef->enums = static_cast(memory->Alloc(sizeof(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(inputDef->m_structs.size()); if (!inputDef->m_structs.empty()) { outputDef->structs = static_cast(memory->Alloc(sizeof(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(inputDef->m_indexed_arrays.size()); if (!inputDef->m_indexed_arrays.empty()) { outputDef->indexedArrays = static_cast(memory->Alloc(sizeof(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(inputDef->m_enumed_arrays.size()); if (!inputDef->m_enumed_arrays.empty()) { outputDef->enumedArrays = static_cast(memory->Alloc(sizeof(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>& defs, MemoryManager* memory) { auto* set = memory->Create(); set->name = memory->Dup(assetName.c_str()); set->defCount = defs.size(); set->defs = static_cast(memory->Alloc(sizeof(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 { 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(ASSET_TYPE_STRUCTURED_DATA_DEF, assetName, ConvertSet(assetName, defs, memory)); return true; }