mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
chore: fix loading and writing code for T6
This commit is contained in:
parent
d8bc156ffd
commit
83d13aa166
@ -81,4 +81,17 @@ namespace T6
|
|||||||
{"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT },
|
{"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT },
|
||||||
{"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT },
|
{"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT },
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
inline const char* s_constraintTypeNames[]{
|
||||||
|
"none",
|
||||||
|
"point",
|
||||||
|
"distance",
|
||||||
|
"hinge",
|
||||||
|
"joint",
|
||||||
|
"actuator",
|
||||||
|
"fake_shake",
|
||||||
|
"launch",
|
||||||
|
"rope",
|
||||||
|
"light",
|
||||||
|
};
|
||||||
|
} // namespace T6
|
@ -36,4 +36,9 @@ namespace T6
|
|||||||
{"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT },
|
{"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT },
|
||||||
{"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT },
|
{"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT },
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
inline const char* tracerTypeNames[]{
|
||||||
|
"Laser",
|
||||||
|
"Smoke",
|
||||||
|
};
|
||||||
|
} // namespace T6
|
@ -561,4 +561,31 @@ namespace T6
|
|||||||
{"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL },
|
{"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL },
|
||||||
{"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL },
|
{"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL },
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
inline const char* s_vehicleClassNames[]{
|
||||||
|
"4 wheel",
|
||||||
|
"motorcycle",
|
||||||
|
"tank",
|
||||||
|
"plane",
|
||||||
|
"boat",
|
||||||
|
"artillery",
|
||||||
|
"helicopter",
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* s_vehicleCameraModes[]{
|
||||||
|
"first",
|
||||||
|
"chase",
|
||||||
|
"view",
|
||||||
|
"strafe",
|
||||||
|
"horse",
|
||||||
|
"oldtank",
|
||||||
|
"hover",
|
||||||
|
"vtol",
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* s_tractionTypeNames[]{
|
||||||
|
"TRACTION_TYPE_FRONT",
|
||||||
|
"TRACTION_TYPE_BACK",
|
||||||
|
"TRACTION_TYPE_ALL_WD",
|
||||||
|
};
|
||||||
|
} // namespace T6
|
@ -81,4 +81,4 @@ namespace T6
|
|||||||
{"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL },
|
{"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL },
|
||||||
{"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL },
|
{"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL },
|
||||||
};
|
};
|
||||||
}
|
} // namespace T6
|
@ -206,4 +206,4 @@ namespace T6
|
|||||||
{"customBool1", offsetof(WeaponAttachmentUniqueFull, attachment.customBool1), CSPFT_BOOL },
|
{"customBool1", offsetof(WeaponAttachmentUniqueFull, attachment.customBool1), CSPFT_BOOL },
|
||||||
{"customBool2", offsetof(WeaponAttachmentUniqueFull, attachment.customBool2), CSPFT_BOOL },
|
{"customBool2", offsetof(WeaponAttachmentUniqueFull, attachment.customBool2), CSPFT_BOOL },
|
||||||
};
|
};
|
||||||
}
|
} // namespace T6
|
@ -36,31 +36,11 @@ namespace T6
|
|||||||
"crosshair",
|
"crosshair",
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* szWeapInventoryTypeNames[]{
|
inline const char* penetrateTypeNames[]{
|
||||||
"primary",
|
"none",
|
||||||
"offhand",
|
"small",
|
||||||
"item",
|
"medium",
|
||||||
"altmode",
|
"large",
|
||||||
"melee",
|
|
||||||
"dwlefthand",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* szWeapClipTypeNames[]{
|
|
||||||
"bottom",
|
|
||||||
"top",
|
|
||||||
"left",
|
|
||||||
"dp28",
|
|
||||||
"ptrs",
|
|
||||||
"lmg",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* barrelTypeNames[]{
|
|
||||||
"Single",
|
|
||||||
"Dual Barrel",
|
|
||||||
"Dual Barrel Alternate",
|
|
||||||
"Quad Barrel",
|
|
||||||
"Quad Barrel Alternate",
|
|
||||||
"Quad Barrel Double Alternate",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* impactTypeNames[]{
|
inline const char* impactTypeNames[]{
|
||||||
@ -165,6 +145,37 @@ namespace T6
|
|||||||
"Turret Scope",
|
"Turret Scope",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const char* szWeapInventoryTypeNames[]{
|
||||||
|
"primary",
|
||||||
|
"offhand",
|
||||||
|
"item",
|
||||||
|
"altmode",
|
||||||
|
"melee",
|
||||||
|
"dwlefthand",
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* szWeapFireTypeNames[]{
|
||||||
|
"Full Auto",
|
||||||
|
"Single Shot",
|
||||||
|
"2-Round Burst",
|
||||||
|
"3-Round Burst",
|
||||||
|
"4-Round Burst",
|
||||||
|
"5-Round Burst",
|
||||||
|
"Stacked Fire",
|
||||||
|
"Minigun",
|
||||||
|
"Charge Shot",
|
||||||
|
"Jetgun",
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* szWeapClipTypeNames[]{
|
||||||
|
"bottom",
|
||||||
|
"top",
|
||||||
|
"left",
|
||||||
|
"dp28",
|
||||||
|
"ptrs",
|
||||||
|
"lmg",
|
||||||
|
};
|
||||||
|
|
||||||
inline const char* ammoCounterClipNames[]{
|
inline const char* ammoCounterClipNames[]{
|
||||||
"None",
|
"None",
|
||||||
"Magazine",
|
"Magazine",
|
||||||
@ -181,75 +192,13 @@ namespace T6
|
|||||||
"4:1",
|
"4:1",
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* szAttachmentTypeNames[]{
|
inline const char* barrelTypeNames[]{
|
||||||
"none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
|
"Single",
|
||||||
"fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
|
"Dual Barrel",
|
||||||
"reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
|
"Dual Barrel Alternate",
|
||||||
};
|
"Quad Barrel",
|
||||||
|
"Quad Barrel Alternate",
|
||||||
inline const char* szWeapFireTypeNames[]{
|
"Quad Barrel Double Alternate",
|
||||||
"Full Auto",
|
|
||||||
"Single Shot",
|
|
||||||
"2-Round Burst",
|
|
||||||
"3-Round Burst",
|
|
||||||
"4-Round Burst",
|
|
||||||
"5-Round Burst",
|
|
||||||
"Stacked Fire",
|
|
||||||
"Minigun",
|
|
||||||
"Charge Shot",
|
|
||||||
"Jetgun",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* penetrateTypeNames[]{
|
|
||||||
"none",
|
|
||||||
"small",
|
|
||||||
"medium",
|
|
||||||
"large",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* s_constraintTypeNames[]{
|
|
||||||
"none",
|
|
||||||
"point",
|
|
||||||
"distance",
|
|
||||||
"hinge",
|
|
||||||
"joint",
|
|
||||||
"actuator",
|
|
||||||
"fake_shake",
|
|
||||||
"launch",
|
|
||||||
"rope",
|
|
||||||
"light",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* s_vehicleClassNames[]{
|
|
||||||
"4 wheel",
|
|
||||||
"motorcycle",
|
|
||||||
"tank",
|
|
||||||
"plane",
|
|
||||||
"boat",
|
|
||||||
"artillery",
|
|
||||||
"helicopter",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* s_vehicleCameraModes[]{
|
|
||||||
"first",
|
|
||||||
"chase",
|
|
||||||
"view",
|
|
||||||
"strafe",
|
|
||||||
"horse",
|
|
||||||
"oldtank",
|
|
||||||
"hover",
|
|
||||||
"vtol",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* s_tractionTypeNames[]{
|
|
||||||
"TRACTION_TYPE_FRONT",
|
|
||||||
"TRACTION_TYPE_BACK",
|
|
||||||
"TRACTION_TYPE_ALL_WD",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const char* tracerTypeNames[]{
|
|
||||||
"Laser",
|
|
||||||
"Smoke",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* bounceSoundSuffixes[]{
|
inline const char* bounceSoundSuffixes[]{
|
||||||
@ -257,4 +206,10 @@ namespace T6
|
|||||||
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
|
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
|
||||||
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield",
|
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const char* szAttachmentTypeNames[]{
|
||||||
|
"none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
|
||||||
|
"fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
|
||||||
|
"reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
|
||||||
|
};
|
||||||
} // namespace T6
|
} // namespace T6
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderAddonMapEnts.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetAddonMapEnts::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderAddonMapEnts final : public BasicAssetLoader<AssetAddonMapEnts>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,23 +0,0 @@
|
|||||||
#include "AssetLoaderClipMap.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderClipMapBase::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<clipMap_t>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
asset_type_t AssetLoaderClipMap::GetHandlingAssetType() const
|
|
||||||
{
|
|
||||||
return ASSET_TYPE_CLIPMAP;
|
|
||||||
}
|
|
||||||
|
|
||||||
asset_type_t AssetLoaderClipMapPvs::GetHandlingAssetType() const
|
|
||||||
{
|
|
||||||
return ASSET_TYPE_CLIPMAP_PVS;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderClipMapBase : public BasicAssetLoaderWithoutType<clipMap_t>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssetLoaderClipMap final : public AssetLoaderClipMapBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
[[nodiscard]] asset_type_t GetHandlingAssetType() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssetLoaderClipMapPvs final : public AssetLoaderClipMapBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
[[nodiscard]] asset_type_t GetHandlingAssetType() const override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderComWorld.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetComWorld::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderComWorld final : public BasicAssetLoader<AssetComWorld>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderDDL.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderDDL::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetDDL::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderDDL final : public BasicAssetLoader<AssetDDL>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderDestructibleDef.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderDestructibleDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetDestructibleDef::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderDestructibleDef final : public BasicAssetLoader<AssetDestructibleDef>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderEmblemSet.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderEmblemSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
// Asset does not have a name
|
|
||||||
// So this cannot be an asset reference
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderEmblemSet final : public BasicAssetLoader<AssetEmblemSet>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderFont.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetFont::Type>();
|
|
||||||
asset->fontName = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderFont final : public BasicAssetLoader<AssetFont>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,270 +0,0 @@
|
|||||||
#include "AssetLoaderFontIcon.h"
|
|
||||||
|
|
||||||
#include "Csv/CsvStream.h"
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderFontIcon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetFontIcon::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AssetLoaderFontIcon::ErrorPrefix(const std::string& assetName, const unsigned rowIndex)
|
|
||||||
{
|
|
||||||
std::ostringstream str;
|
|
||||||
str << "FontIcon \"" << assetName << "\" Row " << rowIndex << ": ";
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderFontIcon::PreprocessRow(std::vector<std::string>& row)
|
|
||||||
{
|
|
||||||
for (auto& cell : row)
|
|
||||||
{
|
|
||||||
for (auto c : cell)
|
|
||||||
{
|
|
||||||
if (isspace(c))
|
|
||||||
continue;
|
|
||||||
if (c == '#')
|
|
||||||
cell = "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::RowIsEmpty(const std::vector<std::string>& row)
|
|
||||||
{
|
|
||||||
return std::ranges::all_of(row,
|
|
||||||
[](const std::string& cell)
|
|
||||||
{
|
|
||||||
return cell.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::ParseInt(int& value, const std::string& str)
|
|
||||||
{
|
|
||||||
char* endPtr;
|
|
||||||
value = strtol(str.c_str(), &endPtr, 0);
|
|
||||||
if (endPtr != &str[str.size()])
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::ParseFloat(float& value, const std::string& str)
|
|
||||||
{
|
|
||||||
char* endPtr;
|
|
||||||
value = strtof(str.c_str(), &endPtr);
|
|
||||||
if (endPtr != &str[str.size()])
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::ParseHashStr(int& value, const std::string& str)
|
|
||||||
{
|
|
||||||
if (!str.empty() && str[0] == '@' && str.size() > 1)
|
|
||||||
{
|
|
||||||
char* endPtr;
|
|
||||||
value = strtol(&str[1], &endPtr, 16);
|
|
||||||
|
|
||||||
if (endPtr != &str[str.size()])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = Common::Com_HashString(str.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::ReadIconRow(const std::vector<std::string>& row,
|
|
||||||
FontIconEntry& icon,
|
|
||||||
const std::string& assetName,
|
|
||||||
const unsigned rowIndex,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
std::vector<XAssetInfoGeneric*>& dependencies)
|
|
||||||
{
|
|
||||||
if (row.size() < COL_COUNT_ICON)
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for entries (" << COL_COUNT_ICON << ")\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE]))
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse size\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE]))
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse scale\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* materialDependency = manager->LoadDependency<AssetMaterial>(row[ROW_ICON_MATERIAL]);
|
|
||||||
if (materialDependency == nullptr)
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to load material \"" << row[ROW_ICON_MATERIAL] << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
icon.fontIconMaterialHandle = materialDependency->Asset();
|
|
||||||
icon.fontIconName.string = memory->Dup(row[ROW_ICON_NAME].c_str());
|
|
||||||
icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::ReadAliasRow(const std::vector<std::string>& row,
|
|
||||||
FontIconAlias& alias,
|
|
||||||
const std::string& assetName,
|
|
||||||
const unsigned rowIndex,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager)
|
|
||||||
{
|
|
||||||
if (row.size() < COL_COUNT_ALIAS)
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for aliases (" << COL_COUNT_ALIAS << ")\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME]))
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse alias \"" << row[ROW_ALIAS_NAME] << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON]))
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse button \"" << row[ROW_ALIAS_BUTTON] << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderFontIcon::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;
|
|
||||||
|
|
||||||
auto* fontIcon = memory->Create<FontIcon>();
|
|
||||||
fontIcon->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
const CsvInputStream csv(*file.m_stream);
|
|
||||||
std::vector<XAssetInfoGeneric*> dependencies;
|
|
||||||
std::vector<std::string> currentRow;
|
|
||||||
std::vector<FontIconEntry> entries;
|
|
||||||
std::vector<FontIconAlias> aliases;
|
|
||||||
auto currentRowIndex = 0u;
|
|
||||||
|
|
||||||
while (csv.NextRow(currentRow))
|
|
||||||
{
|
|
||||||
currentRowIndex++;
|
|
||||||
PreprocessRow(currentRow);
|
|
||||||
|
|
||||||
if (RowIsEmpty(currentRow))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (currentRow.size() < COL_COUNT_MIN)
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Column count lower than min column count (" << COL_COUNT_MIN << ")\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index;
|
|
||||||
if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0)
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Failed to parse index\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON)
|
|
||||||
{
|
|
||||||
FontIconEntry icon{};
|
|
||||||
if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, memory, manager, dependencies))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (static_cast<unsigned>(index) == entries.size())
|
|
||||||
{
|
|
||||||
entries.push_back(icon);
|
|
||||||
}
|
|
||||||
else if (static_cast<unsigned>(index) > entries.size())
|
|
||||||
{
|
|
||||||
entries.reserve(index + 1);
|
|
||||||
entries[index] = icon;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entries[index] = icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS)
|
|
||||||
{
|
|
||||||
FontIconAlias alias{};
|
|
||||||
if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, memory, manager))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (static_cast<unsigned>(index) == aliases.size())
|
|
||||||
{
|
|
||||||
aliases.push_back(alias);
|
|
||||||
}
|
|
||||||
else if (static_cast<unsigned>(index) > aliases.size())
|
|
||||||
{
|
|
||||||
aliases.reserve(index + 1);
|
|
||||||
aliases[index] = alias;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aliases[index] = alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << ErrorPrefix(assetName, currentRowIndex) << "Unknown row type \"" << currentRow[ROW_TYPE] << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fontIcon->numEntries = entries.size();
|
|
||||||
fontIcon->numAliasEntries = aliases.size();
|
|
||||||
|
|
||||||
if (fontIcon->numEntries > 0)
|
|
||||||
{
|
|
||||||
fontIcon->fontIconEntry = memory->Alloc<FontIconEntry>(fontIcon->numEntries);
|
|
||||||
for (auto i = 0u; i < entries.size(); i++)
|
|
||||||
fontIcon->fontIconEntry[i] = entries[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fontIcon->fontIconEntry = nullptr;
|
|
||||||
|
|
||||||
if (fontIcon->numAliasEntries > 0)
|
|
||||||
{
|
|
||||||
fontIcon->fontIconAlias = memory->Alloc<FontIconAlias>(fontIcon->numAliasEntries);
|
|
||||||
for (auto i = 0u; i < aliases.size(); i++)
|
|
||||||
fontIcon->fontIconAlias[i] = aliases[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fontIcon->fontIconAlias = nullptr;
|
|
||||||
|
|
||||||
manager->AddAsset<AssetFontIcon>(assetName, fontIcon);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderFontIcon final : public BasicAssetLoader<AssetFontIcon>
|
|
||||||
{
|
|
||||||
static constexpr unsigned ROW_INDEX = 0;
|
|
||||||
static constexpr unsigned ROW_TYPE = 1;
|
|
||||||
|
|
||||||
static constexpr unsigned ROW_ICON_NAME = 2;
|
|
||||||
static constexpr unsigned ROW_ICON_MATERIAL = 3;
|
|
||||||
static constexpr unsigned ROW_ICON_SIZE = 4;
|
|
||||||
static constexpr unsigned ROW_ICON_XSCALE = 5;
|
|
||||||
static constexpr unsigned ROW_ICON_YSCALE = 6;
|
|
||||||
|
|
||||||
static constexpr unsigned ROW_ALIAS_NAME = 2;
|
|
||||||
static constexpr unsigned ROW_ALIAS_BUTTON = 3;
|
|
||||||
|
|
||||||
static constexpr const char* VALUE_TYPE_ICON = "icon";
|
|
||||||
static constexpr const char* VALUE_TYPE_ALIAS = "alias";
|
|
||||||
|
|
||||||
static constexpr unsigned COL_COUNT_ICON = 7;
|
|
||||||
static constexpr unsigned COL_COUNT_ALIAS = 4;
|
|
||||||
static constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS);
|
|
||||||
|
|
||||||
static std::string ErrorPrefix(const std::string& assetName, unsigned rowIndex);
|
|
||||||
static void PreprocessRow(std::vector<std::string>& row);
|
|
||||||
static bool RowIsEmpty(const std::vector<std::string>& row);
|
|
||||||
|
|
||||||
static bool ParseInt(int& value, const std::string& str);
|
|
||||||
static bool ParseFloat(float& value, const std::string& str);
|
|
||||||
static bool ParseHashStr(int& value, const std::string& str);
|
|
||||||
|
|
||||||
static bool ReadIconRow(const std::vector<std::string>& row,
|
|
||||||
FontIconEntry& icon,
|
|
||||||
const std::string& assetName,
|
|
||||||
unsigned rowIndex,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
std::vector<XAssetInfoGeneric*>& dependencies);
|
|
||||||
static bool ReadAliasRow(const std::vector<std::string>& row,
|
|
||||||
FontIconAlias& alias,
|
|
||||||
const std::string& assetName,
|
|
||||||
unsigned rowIndex,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager);
|
|
||||||
|
|
||||||
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 T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderFootstepFxTable.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderFootstepFxTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetFootstepFxTable::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderFootstepFxTable final : public BasicAssetLoader<AssetFootstepFxTable>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderFootstepTable.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderFootstepTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetFootstepTable::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderFootstepTable final : public BasicAssetLoader<AssetFootstepTable>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderFx.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetFx::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderFx final : public BasicAssetLoader<AssetFx>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderGameWorldMp.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGameWorldMp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetGameWorldMp::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGameWorldMp final : public BasicAssetLoader<AssetGameWorldMp>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderGameWorldSp.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGameWorldSp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetGameWorldSp::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGameWorldSp final : public BasicAssetLoader<AssetGameWorldSp>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,70 +0,0 @@
|
|||||||
#include "AssetLoaderGfxImage.h"
|
|
||||||
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Image/IwiLoader.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetImage::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderGfxImage::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderGfxImage::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = std::format("images/{}.iwi", assetName);
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto fileSize = static_cast<size_t>(file.m_length);
|
|
||||||
const auto fileData = std::make_unique<char[]>(fileSize);
|
|
||||||
file.m_stream->read(fileData.get(), fileSize);
|
|
||||||
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), fileSize));
|
|
||||||
|
|
||||||
std::istringstream ss(std::string(fileData.get(), fileSize));
|
|
||||||
const auto texture = iwi::LoadIwi(ss);
|
|
||||||
if (!texture)
|
|
||||||
{
|
|
||||||
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* image = memory->Create<GfxImage>();
|
|
||||||
memset(image, 0, sizeof(GfxImage));
|
|
||||||
|
|
||||||
image->name = memory->Dup(assetName.c_str());
|
|
||||||
image->hash = Common::R_HashString(image->name, 0);
|
|
||||||
image->delayLoadPixels = true;
|
|
||||||
|
|
||||||
image->noPicmip = !texture->HasMipMaps();
|
|
||||||
image->width = static_cast<uint16_t>(texture->GetWidth());
|
|
||||||
image->height = static_cast<uint16_t>(texture->GetHeight());
|
|
||||||
image->depth = static_cast<uint16_t>(texture->GetDepth());
|
|
||||||
|
|
||||||
image->streaming = 1;
|
|
||||||
image->streamedParts[0].levelCount = 1;
|
|
||||||
image->streamedParts[0].levelSize = static_cast<uint32_t>(fileSize);
|
|
||||||
image->streamedParts[0].hash = dataHash & 0x1FFFFFFF;
|
|
||||||
image->streamedPartCount = 1;
|
|
||||||
|
|
||||||
manager->AddAsset<AssetImage>(assetName, image);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGfxImage final : public BasicAssetLoader<AssetImage>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
|
||||||
bool
|
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderGfxLightDef.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetLightDef::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGfxLightDef final : public BasicAssetLoader<AssetLightDef>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderGfxWorld.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetGfxWorld::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGfxWorld final : public BasicAssetLoader<AssetGfxWorld>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderGlasses.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderGlasses::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetGlasses::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderGlasses final : public BasicAssetLoader<AssetGlasses>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderImpactFx.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderImpactFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetImpactFx::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderImpactFx final : public BasicAssetLoader<AssetImpactFx>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,42 +0,0 @@
|
|||||||
#include "AssetLoaderLeaderboard.h"
|
|
||||||
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/Leaderboard/JsonLeaderboardDefLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetLeaderboard::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderMapEnts.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetMapEnts::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderMapEnts final : public BasicAssetLoader<AssetMapEnts>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,57 +0,0 @@
|
|||||||
#include "AssetLoaderMaterial.h"
|
|
||||||
|
|
||||||
#include "Game/T6/Material/JsonMaterialLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetMaterial::Type>();
|
|
||||||
asset->info.name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderMaterial::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName)
|
|
||||||
{
|
|
||||||
std::string sanitizedFileName(assetName);
|
|
||||||
if (sanitizedFileName[0] == '*')
|
|
||||||
{
|
|
||||||
std::ranges::replace(sanitizedFileName, '*', '_');
|
|
||||||
const auto parenthesisPos = sanitizedFileName.find('(');
|
|
||||||
if (parenthesisPos != std::string::npos)
|
|
||||||
sanitizedFileName.erase(parenthesisPos);
|
|
||||||
sanitizedFileName = "generated/" + sanitizedFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::format("materials/{}.json", sanitizedFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderMaterial::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto file = searchPath->Open(GetFileNameForAsset(assetName));
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto* material = memory->Alloc<Material>();
|
|
||||||
material->info.name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
std::vector<XAssetInfoGeneric*> dependencies;
|
|
||||||
if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies))
|
|
||||||
manager->AddAsset<AssetMaterial>(assetName, material, std::move(dependencies));
|
|
||||||
else
|
|
||||||
std::cerr << "Failed to load material \"" << assetName << "\"\n";
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderMaterial final : public BasicAssetLoader<AssetMaterial>
|
|
||||||
{
|
|
||||||
static std::string GetFileNameForAsset(const std::string& assetName);
|
|
||||||
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
|
||||||
bool
|
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderMemoryBlock.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderMemoryBlock::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetMemoryBlock::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderMemoryBlock final : public BasicAssetLoader<AssetMemoryBlock>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderMenu.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderMenu::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetMenu::Type>();
|
|
||||||
asset->window.name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderMenu final : public BasicAssetLoader<AssetMenu>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderMenuList.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetMenuList::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderMenuList final : public BasicAssetLoader<AssetMenuList>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,153 +0,0 @@
|
|||||||
#include "AssetLoaderPhysConstraints.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/EnumStrings.h"
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/PhysConstraintsFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class InfoStringToPhysConstraintsConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
switch (static_cast<constraintsFieldType_t>(field.iFieldType))
|
|
||||||
{
|
|
||||||
case CFT_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, s_constraintTypeNames, std::extent_v<decltype(s_constraintTypeNames)>);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToPhysConstraintsConverter(const InfoString& infoString,
|
|
||||||
PhysConstraints* physConstraints,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, physConstraints, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
void AssetLoaderPhysConstraints::CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone)
|
|
||||||
{
|
|
||||||
for (auto& constraint : physConstraints->data)
|
|
||||||
{
|
|
||||||
constraint.targetname = zone->m_script_strings.AddOrGetScriptString("");
|
|
||||||
constraint.target_ent1 = zone->m_script_strings.AddOrGetScriptString("");
|
|
||||||
constraint.target_ent2 = zone->m_script_strings.AddOrGetScriptString("");
|
|
||||||
constraint.attach_point_type1 = ATTACH_POINT_BONE;
|
|
||||||
constraint.attach_point_type2 = ATTACH_POINT_BONE;
|
|
||||||
constraint.target_bone1 = "";
|
|
||||||
constraint.target_bone2 = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// count
|
|
||||||
{
|
|
||||||
auto foundEnd = false;
|
|
||||||
for (auto i = 0u; i < std::extent_v<decltype(PhysConstraints::data)>; i++)
|
|
||||||
{
|
|
||||||
if (physConstraints->data[i].type == CONSTRAINT_NONE)
|
|
||||||
{
|
|
||||||
foundEnd = true;
|
|
||||||
physConstraints->count = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundEnd)
|
|
||||||
physConstraints->count = std::extent_v<decltype(PhysConstraints::data)>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderPhysConstraints::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* physConstraints = memory->Create<PhysConstraints>();
|
|
||||||
memset(physConstraints, 0, sizeof(PhysConstraints));
|
|
||||||
|
|
||||||
InfoStringToPhysConstraintsConverter converter(
|
|
||||||
infoString, physConstraints, zone->m_script_strings, memory, manager, phys_constraints_fields, std::extent_v<decltype(phys_constraints_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cout << "Failed to parse phys constraints: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalculatePhysConstraintsFields(physConstraints, zone);
|
|
||||||
physConstraints->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
auto scrStrings = converter.GetUsedScriptStrings();
|
|
||||||
scrStrings.push_back(zone->m_script_strings.AddOrGetScriptString(""));
|
|
||||||
manager->AddAsset<AssetPhysConstraints>(assetName, physConstraints, converter.GetDependencies(), scrStrings);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderPhysConstraints::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetPhysConstraints::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderPhysConstraints::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderPhysConstraints::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_CONSTRAINTS, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cout << "Failed to read phys constraints gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderPhysConstraints::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderPhysConstraints::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "physconstraints/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderPhysConstraints final : public BasicAssetLoader<AssetPhysConstraints>
|
|
||||||
{
|
|
||||||
static void CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone);
|
|
||||||
|
|
||||||
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 T6
|
|
@ -1,136 +0,0 @@
|
|||||||
#include "AssetLoaderPhysPreset.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/PhysPresetFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
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 T6
|
|
||||||
|
|
||||||
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->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction;
|
|
||||||
physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity;
|
|
||||||
physPreset->canFloat = physPresetInfo->canFloat;
|
|
||||||
physPreset->gravityScale = std::clamp(physPresetInfo->gravityScale, 0.01f, 10.0f);
|
|
||||||
physPreset->centerOfMassOffset = physPresetInfo->centerOfMassOffset;
|
|
||||||
physPreset->buoyancyBoxMin = physPresetInfo->buoyancyBoxMin;
|
|
||||||
physPreset->buoyancyBoxMax = physPresetInfo->buoyancyBoxMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
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* asset = memory->Alloc<AssetPhysPreset::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,42 +0,0 @@
|
|||||||
#include "AssetLoaderQdb.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderQdb::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetQdb::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderQdb::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderQdb::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;
|
|
||||||
|
|
||||||
auto* qdb = memory->Create<Qdb>();
|
|
||||||
qdb->name = memory->Dup(assetName.c_str());
|
|
||||||
qdb->len = static_cast<int>(file.m_length);
|
|
||||||
|
|
||||||
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
|
|
||||||
file.m_stream->read(fileBuffer, file.m_length);
|
|
||||||
if (file.m_stream->gcount() != file.m_length)
|
|
||||||
return false;
|
|
||||||
fileBuffer[qdb->len] = '\0';
|
|
||||||
|
|
||||||
qdb->buffer = static_cast<char16*>(fileBuffer);
|
|
||||||
manager->AddAsset<AssetQdb>(assetName, qdb);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderQdb final : public BasicAssetLoader<AssetQdb>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,114 +0,0 @@
|
|||||||
#include "AssetLoaderRawFile.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <zutil.h>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetRawFile::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderRawFile::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderRawFile::LoadAnimtree(
|
|
||||||
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
|
|
||||||
{
|
|
||||||
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 + sizeof(uint32_t) + 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[sizeof(uint32_t)]);
|
|
||||||
|
|
||||||
int ret = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -DEF_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
|
||||||
|
|
||||||
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 animtree file \"" << assetName << "\"\n";
|
|
||||||
deflateEnd(&zs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto compressedSize = compressionBufferSize + sizeof(uint32_t) - zs.avail_out;
|
|
||||||
|
|
||||||
reinterpret_cast<uint32_t*>(compressedBuffer)[0] = static_cast<uint32_t>(file.m_length); // outLen
|
|
||||||
|
|
||||||
auto* rawFile = memory->Create<RawFile>();
|
|
||||||
rawFile->name = memory->Dup(assetName.c_str());
|
|
||||||
rawFile->len = static_cast<int>(compressedSize);
|
|
||||||
rawFile->buffer = static_cast<const char*>(compressedBuffer);
|
|
||||||
|
|
||||||
deflateEnd(&zs);
|
|
||||||
|
|
||||||
manager->AddAsset<AssetRawFile>(assetName, rawFile);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderRawFile::LoadDefault(
|
|
||||||
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
|
|
||||||
{
|
|
||||||
auto* rawFile = memory->Create<RawFile>();
|
|
||||||
rawFile->name = memory->Dup(assetName.c_str());
|
|
||||||
rawFile->len = static_cast<int>(file.m_length);
|
|
||||||
|
|
||||||
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
|
|
||||||
file.m_stream->read(fileBuffer, file.m_length);
|
|
||||||
if (file.m_stream->gcount() != file.m_length)
|
|
||||||
return false;
|
|
||||||
fileBuffer[rawFile->len] = '\0';
|
|
||||||
|
|
||||||
rawFile->buffer = static_cast<char16*>(fileBuffer);
|
|
||||||
manager->AddAsset<AssetRawFile>(assetName, rawFile);
|
|
||||||
|
|
||||||
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 fs::path rawFilePath(assetName);
|
|
||||||
const auto extension = rawFilePath.extension().string();
|
|
||||||
|
|
||||||
if (extension == ".atr")
|
|
||||||
return LoadAnimtree(file, assetName, searchPath, memory, manager);
|
|
||||||
|
|
||||||
return LoadDefault(file, assetName, searchPath, memory, manager);
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderRawFile final : public BasicAssetLoader<AssetRawFile>
|
|
||||||
{
|
|
||||||
static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64;
|
|
||||||
|
|
||||||
static bool LoadAnimtree(
|
|
||||||
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
|
|
||||||
static bool LoadDefault(
|
|
||||||
const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager);
|
|
||||||
|
|
||||||
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 T6
|
|
@ -1,43 +0,0 @@
|
|||||||
#include "AssetLoaderScriptParseTree.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderScriptParseTree::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetScript::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderScriptParseTree::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderScriptParseTree::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;
|
|
||||||
|
|
||||||
auto* scriptParseTree = memory->Create<ScriptParseTree>();
|
|
||||||
scriptParseTree->name = memory->Dup(assetName.c_str());
|
|
||||||
scriptParseTree->len = static_cast<int>(file.m_length);
|
|
||||||
|
|
||||||
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
|
|
||||||
file.m_stream->read(fileBuffer, file.m_length);
|
|
||||||
if (file.m_stream->gcount() != file.m_length)
|
|
||||||
return false;
|
|
||||||
fileBuffer[scriptParseTree->len] = '\0';
|
|
||||||
|
|
||||||
scriptParseTree->buffer = static_cast<char16*>(fileBuffer);
|
|
||||||
manager->AddAsset<AssetScript>(assetName, scriptParseTree);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderScriptParseTree final : public BasicAssetLoader<AssetScript>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
|
||||||
bool
|
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderSkinnedVerts.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderSkinnedVerts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetSkinnedVerts::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderSkinnedVerts final : public BasicAssetLoader<AssetSkinnedVerts>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,42 +0,0 @@
|
|||||||
#include "AssetLoaderSlug.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderSlug::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetSlug::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderSlug::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderSlug::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;
|
|
||||||
|
|
||||||
auto* slug = memory->Create<Slug>();
|
|
||||||
slug->name = memory->Dup(assetName.c_str());
|
|
||||||
slug->len = static_cast<int>(file.m_length);
|
|
||||||
|
|
||||||
auto* fileBuffer = memory->Alloc<char>(static_cast<size_t>(file.m_length + 1));
|
|
||||||
file.m_stream->read(fileBuffer, file.m_length);
|
|
||||||
if (file.m_stream->gcount() != file.m_length)
|
|
||||||
return false;
|
|
||||||
fileBuffer[slug->len] = '\0';
|
|
||||||
|
|
||||||
slug->buffer = static_cast<char16*>(fileBuffer);
|
|
||||||
manager->AddAsset<AssetSlug>(assetName, slug);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderSlug final : public BasicAssetLoader<AssetSlug>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderSoundBank final : public BasicAssetLoader<AssetSoundBank>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderSoundDriverGlobals.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderSoundDriverGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetSoundDriverGlobals::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderSoundDriverGlobals final : public BasicAssetLoader<AssetSoundDriverGlobals>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderSoundPatch.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderSoundPatch::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetSoundPatch::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderSoundPatch final : public BasicAssetLoader<AssetSoundPatch>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,38 +0,0 @@
|
|||||||
#include "AssetLoaderStringTable.h"
|
|
||||||
|
|
||||||
#include "Csv/CsvStream.h"
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
#include "StringTable/StringTableLoader.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetStringTable::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
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::StringTableLoaderV3<StringTable, Common::Com_HashString> loader;
|
|
||||||
auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream);
|
|
||||||
|
|
||||||
manager->AddAsset<AssetStringTable>(assetName, stringTable);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderTechniqueSet.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetTechniqueSet::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderTechniqueSet final : public BasicAssetLoader<AssetTechniqueSet>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,119 +0,0 @@
|
|||||||
#include "AssetLoaderTracer.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/EnumStrings.h"
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/TracerFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class InfoStringToTracerConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
switch (static_cast<tracerFieldType_t>(field.iFieldType))
|
|
||||||
{
|
|
||||||
case TFT_TRACERTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, tracerTypeNames, std::extent_v<decltype(tracerTypeNames)>);
|
|
||||||
|
|
||||||
case TFT_NUM_FIELD_TYPES:
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToTracerConverter(const InfoString& infoString,
|
|
||||||
TracerDef* tracer,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, tracer, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
bool AssetLoaderTracer::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* tracer = memory->Create<TracerDef>();
|
|
||||||
memset(tracer, 0, sizeof(TracerDef));
|
|
||||||
|
|
||||||
InfoStringToTracerConverter converter(infoString, tracer, zone->m_script_strings, memory, manager, tracer_fields, std::extent_v<decltype(tracer_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cout << "Failed to parse tracer: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tracer->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
manager->AddAsset<AssetTracer>(assetName, tracer, converter.GetDependencies(), converter.GetUsedScriptStrings());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderTracer::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetTracer::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderTracer::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderTracer::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_TRACER, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cout << "Failed to read tracer gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderTracer::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderTracer::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "tracer/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_TRACER, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderTracer final : public BasicAssetLoader<AssetTracer>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderVehicle final : public BasicAssetLoader<AssetVehicle>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,683 +0,0 @@
|
|||||||
#include "AssetLoaderWeapon.h"
|
|
||||||
|
|
||||||
#include "AssetLoaderWeaponAttachmentUnique.h"
|
|
||||||
#include "Game/T6/InfoString/EnumStrings.h"
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/WeaponFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "Utils/ClassUtils.h"
|
|
||||||
#include "Utils/StringUtils.h"
|
|
||||||
#include "Weapon/AccuracyGraphLoader.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class InfoStringToWeaponConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
bool ConvertHideTags(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
std::vector<std::string> valueArray;
|
|
||||||
if (!ParseAsArray(value, valueArray))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse hide tags as array\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::hideTags)> << " hide tags!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
|
|
||||||
if (valueArray.size() < std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
|
||||||
{
|
|
||||||
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto currentHideTag = 0u;
|
|
||||||
for (; currentHideTag < valueArray.size(); currentHideTag++)
|
|
||||||
{
|
|
||||||
const auto& currentValue = valueArray[currentHideTag];
|
|
||||||
const auto scrString =
|
|
||||||
!currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr);
|
|
||||||
hideTags[currentHideTag] = scrString;
|
|
||||||
m_used_script_string_list.emplace(scrString);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; currentHideTag < std::extent_v<decltype(WeaponFullDef::hideTags)>; currentHideTag++)
|
|
||||||
{
|
|
||||||
hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertBounceSounds(const cspField_t& field, const std::string& value) const
|
|
||||||
{
|
|
||||||
auto*** bounceSound = reinterpret_cast<const char***>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
if (value.empty())
|
|
||||||
{
|
|
||||||
*bounceSound = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(std::extent_v<decltype(bounceSoundSuffixes)> == SURF_TYPE_NUM);
|
|
||||||
*bounceSound = m_memory->Alloc<const char*>(SURF_TYPE_NUM);
|
|
||||||
for (auto i = 0u; i < SURF_TYPE_NUM; i++)
|
|
||||||
{
|
|
||||||
const auto currentBounceSound = value + bounceSoundSuffixes[i];
|
|
||||||
(*bounceSound)[i] = m_memory->Dup(currentBounceSound.c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
std::vector<std::array<std::string, 2>> pairs;
|
|
||||||
if (!ParseAsArray(value, pairs))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse notetracksoundmap as pairs\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pairs.size() > std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)> << " notetracksoundmap entries!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* keys = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
auto* values = &keys[std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>];
|
|
||||||
auto currentEntryNum = 0u;
|
|
||||||
|
|
||||||
if (pairs.size() < std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
|
|
||||||
{
|
|
||||||
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
|
||||||
{
|
|
||||||
const auto& currentValue = pairs[currentEntryNum];
|
|
||||||
const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0])
|
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
|
||||||
const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1])
|
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
|
||||||
|
|
||||||
keys[currentEntryNum] = keyScriptString;
|
|
||||||
m_used_script_string_list.emplace(keyScriptString);
|
|
||||||
|
|
||||||
values[currentEntryNum] = valueScriptString;
|
|
||||||
m_used_script_string_list.emplace(valueScriptString);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; currentEntryNum < std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>; currentEntryNum++)
|
|
||||||
{
|
|
||||||
const auto emptyScr = m_zone_script_strings.GetScriptString(nullptr);
|
|
||||||
keys[currentEntryNum] = emptyScr;
|
|
||||||
values[currentEntryNum] = emptyScr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
if (value.empty())
|
|
||||||
{
|
|
||||||
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* camo = m_loading_manager->LoadDependency<AssetWeaponCamo>(value);
|
|
||||||
|
|
||||||
if (camo == nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to load camo asset \"" << value << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dependencies.emplace(camo);
|
|
||||||
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = camo->Asset();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertAttachments(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
std::vector<std::string> valueArray;
|
|
||||||
if (!ParseAsArray(value, valueArray))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse attachments as array\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto** attachments = reinterpret_cast<WeaponAttachment**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
|
|
||||||
for (const auto& attachmentName : valueArray)
|
|
||||||
{
|
|
||||||
auto* attachmentAssetInfo = m_loading_manager->LoadDependency<AssetAttachment>(attachmentName);
|
|
||||||
if (attachmentAssetInfo == nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to load attachment asset \"" << attachmentName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* attachmentAsset = attachmentAssetInfo->Asset();
|
|
||||||
|
|
||||||
if (static_cast<unsigned>(attachmentAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT)
|
|
||||||
{
|
|
||||||
std::cerr << "Invalid attachment type " << attachmentAsset->attachmentType << " for attachment asset \"" << attachmentName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachments[attachmentAsset->attachmentType] != nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Already loaded attachment with same type " << attachmentAsset->attachmentType << ": \""
|
|
||||||
<< attachments[attachmentAsset->attachmentType]->szInternalName << "\", \"" << attachmentName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachments[attachmentAsset->attachmentType] = attachmentAsset;
|
|
||||||
m_dependencies.emplace(attachmentAssetInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD static bool HasMoreThanOneAttachmentSetInMask(const int mask)
|
|
||||||
{
|
|
||||||
// Check if int has more than 1 bit set
|
|
||||||
return (mask & (mask - 1)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertAttachmentUniques(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
std::vector<std::string> valueArray;
|
|
||||||
if (!ParseAsArray(value, valueArray))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse attachment uniques as array\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto** attachmentUniques = reinterpret_cast<WeaponAttachmentUnique**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
auto attachmentCombinationIndex = std::extent_v<decltype(WeaponFullDef::attachments)>;
|
|
||||||
|
|
||||||
for (const auto& attachmentUniqueName : valueArray)
|
|
||||||
{
|
|
||||||
auto* attachmentUniqueAssetInfo = m_loading_manager->LoadDependency<AssetAttachmentUnique>(attachmentUniqueName);
|
|
||||||
if (attachmentUniqueAssetInfo == nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to load attachment unique asset \"" << attachmentUniqueName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* attachmentUniqueAsset = attachmentUniqueAssetInfo->Asset();
|
|
||||||
|
|
||||||
if (HasMoreThanOneAttachmentSetInMask(attachmentUniqueAsset->combinedAttachmentTypeMask))
|
|
||||||
{
|
|
||||||
if (attachmentCombinationIndex >= std::extent_v<decltype(WeaponFullDef::attachmentUniques)>)
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot have more than "
|
|
||||||
<< (std::extent_v<decltype(WeaponFullDef::attachmentUniques)> - std::extent_v<decltype(WeaponFullDef::attachments)>)
|
|
||||||
<< " combined attachment attachment unique entries!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentUniques[attachmentCombinationIndex++] = attachmentUniqueAsset;
|
|
||||||
m_dependencies.emplace(attachmentUniqueAssetInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (static_cast<unsigned>(attachmentUniqueAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT)
|
|
||||||
{
|
|
||||||
std::cerr << "Invalid attachment type " << attachmentUniqueAsset->attachmentType << " for attachment unique asset \""
|
|
||||||
<< attachmentUniqueName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachmentUniques[attachmentUniqueAsset->attachmentType] != nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Already loaded attachment unique with same type " << attachmentUniqueAsset->attachmentType << ": \""
|
|
||||||
<< attachmentUniques[attachmentUniqueAsset->attachmentType]->szInternalName << "\", \"" << attachmentUniqueName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentUniques[attachmentUniqueAsset->attachmentType] = attachmentUniqueAsset;
|
|
||||||
m_dependencies.emplace(attachmentUniqueAssetInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConvertAnimName(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
if (ConvertString(value, field.iOffset))
|
|
||||||
{
|
|
||||||
if (!value.empty())
|
|
||||||
m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference<AssetXAnim>(value));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
switch (static_cast<weapFieldType_t>(field.iFieldType))
|
|
||||||
{
|
|
||||||
case WFT_WEAPONTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapTypeNames, std::extent_v<decltype(szWeapTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_WEAPONCLASS:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClassNames, std::extent_v<decltype(szWeapClassNames)>);
|
|
||||||
|
|
||||||
case WFT_OVERLAYRETICLE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v<decltype(szWeapOverlayReticleNames)>);
|
|
||||||
|
|
||||||
case WFT_PENETRATE_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v<decltype(penetrateTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_IMPACT_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, impactTypeNames, std::extent_v<decltype(impactTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_STANCE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapStanceNames, std::extent_v<decltype(szWeapStanceNames)>);
|
|
||||||
|
|
||||||
case WFT_PROJ_EXPLOSION:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szProjectileExplosionNames, std::extent_v<decltype(szProjectileExplosionNames)>);
|
|
||||||
|
|
||||||
case WFT_OFFHAND_CLASS:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, offhandClassNames, std::extent_v<decltype(offhandClassNames)>);
|
|
||||||
|
|
||||||
case WFT_OFFHAND_SLOT:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, offhandSlotNames, std::extent_v<decltype(offhandSlotNames)>);
|
|
||||||
|
|
||||||
case WFT_ANIMTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, playerAnimTypeNames, std::extent_v<decltype(playerAnimTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_ACTIVE_RETICLE_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, activeReticleNames, std::extent_v<decltype(activeReticleNames)>);
|
|
||||||
|
|
||||||
case WFT_GUIDED_MISSILE_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, guidedMissileNames, std::extent_v<decltype(guidedMissileNames)>);
|
|
||||||
|
|
||||||
case WFT_BOUNCE_SOUND:
|
|
||||||
return ConvertBounceSounds(field, value);
|
|
||||||
|
|
||||||
case WFT_STICKINESS:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, stickinessNames, std::extent_v<decltype(stickinessNames)>);
|
|
||||||
|
|
||||||
case WFT_ROTATETYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, rotateTypeNames, std::extent_v<decltype(rotateTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_OVERLAYINTERFACE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, overlayInterfaceNames, std::extent_v<decltype(overlayInterfaceNames)>);
|
|
||||||
|
|
||||||
case WFT_INVENTORYTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapInventoryTypeNames, std::extent_v<decltype(szWeapInventoryTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_FIRETYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v<decltype(szWeapFireTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_CLIPTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClipTypeNames, std::extent_v<decltype(szWeapClipTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_AMMOCOUNTER_CLIPTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, ammoCounterClipNames, std::extent_v<decltype(ammoCounterClipNames)>);
|
|
||||||
|
|
||||||
case WFT_ICONRATIO_HUD:
|
|
||||||
case WFT_ICONRATIO_AMMOCOUNTER:
|
|
||||||
case WFT_ICONRATIO_KILL:
|
|
||||||
case WFT_ICONRATIO_DPAD:
|
|
||||||
case WFT_ICONRATIO_INDICATOR:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, weapIconRatioNames, std::extent_v<decltype(weapIconRatioNames)>);
|
|
||||||
|
|
||||||
case WFT_BARRELTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, barrelTypeNames, std::extent_v<decltype(barrelTypeNames)>);
|
|
||||||
|
|
||||||
case WFT_HIDETAGS:
|
|
||||||
return ConvertHideTags(field, value);
|
|
||||||
|
|
||||||
case WFT_EXPLOSION_TAG:
|
|
||||||
return ConvertScriptString(value, field.iOffset);
|
|
||||||
|
|
||||||
case WFT_NOTETRACKSOUNDMAP:
|
|
||||||
return ConvertNotetrackSoundMap(field, value);
|
|
||||||
|
|
||||||
case WFT_WEAPON_CAMO:
|
|
||||||
return ConvertWeaponCamo(field, value);
|
|
||||||
|
|
||||||
case WFT_ATTACHMENTS:
|
|
||||||
return ConvertAttachments(field, value);
|
|
||||||
|
|
||||||
case WFT_ATTACHMENT_UNIQUES:
|
|
||||||
return ConvertAttachmentUniques(field, value);
|
|
||||||
|
|
||||||
case WFT_ANIM_NAME:
|
|
||||||
return ConvertAnimName(field, value);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToWeaponConverter(const InfoString& infoString,
|
|
||||||
WeaponFullDef* weaponFullDef,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void ConvertAccuracyGraph(
|
|
||||||
const GenericGraph2D& graph, vec2_t*& originalGraphKnots, int& originalGraphKnotCount, vec2_t*& graphKnots, int& graphKnotCount, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
originalGraphKnotCount = static_cast<int>(graph.knots.size());
|
|
||||||
originalGraphKnots = memory->Alloc<vec2_t>(originalGraphKnotCount);
|
|
||||||
|
|
||||||
for (auto i = 0; i < originalGraphKnotCount; i++)
|
|
||||||
{
|
|
||||||
const auto& commonKnot = graph.knots[i];
|
|
||||||
originalGraphKnots[i].x = static_cast<float>(commonKnot.x);
|
|
||||||
originalGraphKnots[i].y = static_cast<float>(commonKnot.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphKnots = originalGraphKnots;
|
|
||||||
graphKnotCount = originalGraphKnotCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager)
|
|
||||||
{
|
|
||||||
auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<AccuracyGraphLoader>();
|
|
||||||
|
|
||||||
if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0])
|
|
||||||
{
|
|
||||||
const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName);
|
|
||||||
if (!graph)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ConvertAccuracyGraph(*graph,
|
|
||||||
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots,
|
|
||||||
weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount,
|
|
||||||
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnots,
|
|
||||||
weaponFullDef->weapDef.aiVsAiAccuracyGraphKnotCount,
|
|
||||||
memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0])
|
|
||||||
{
|
|
||||||
const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName);
|
|
||||||
if (!graph)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ConvertAccuracyGraph(*graph,
|
|
||||||
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots,
|
|
||||||
weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount,
|
|
||||||
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnots,
|
|
||||||
weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnotCount,
|
|
||||||
memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::LinkWeaponFullDefSubStructs(WeaponFullDef* weapon)
|
|
||||||
{
|
|
||||||
weapon->weapVariantDef.weapDef = &weapon->weapDef;
|
|
||||||
weapon->weapVariantDef.attachments = weapon->attachments;
|
|
||||||
weapon->weapVariantDef.attachmentUniques = weapon->attachmentUniques;
|
|
||||||
weapon->weapDef.gunXModel = weapon->gunXModel;
|
|
||||||
weapon->weapVariantDef.szXAnims = weapon->szXAnims;
|
|
||||||
weapon->weapVariantDef.hideTags = weapon->hideTags;
|
|
||||||
weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys;
|
|
||||||
weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues;
|
|
||||||
weapon->weapDef.worldModel = weapon->worldModel;
|
|
||||||
weapon->weapVariantDef.attachViewModel = weapon->attachViewModel;
|
|
||||||
weapon->weapVariantDef.attachWorldModel = weapon->attachWorldModel;
|
|
||||||
weapon->weapVariantDef.attachViewModelTag = weapon->attachViewModelTag;
|
|
||||||
weapon->weapVariantDef.attachWorldModelTag = weapon->attachWorldModelTag;
|
|
||||||
weapon->weapDef.parallelBounce = weapon->parallelBounce;
|
|
||||||
weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce;
|
|
||||||
weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::CalculateWeaponFields(WeaponFullDef* weapon)
|
|
||||||
{
|
|
||||||
// iAttachments
|
|
||||||
weapon->weapVariantDef.iAttachments = 0;
|
|
||||||
for (auto i = 1u; i < sizeof(WeaponVariantDef::iAttachments) * 8; i++) // Bit for default attachment always 0
|
|
||||||
{
|
|
||||||
if (weapon->attachments[i])
|
|
||||||
weapon->weapVariantDef.iAttachments |= 1 << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weapon->weapVariantDef.iAdsTransInTime <= 0)
|
|
||||||
weapon->weapVariantDef.fOOPosAnimLength[0] = 0.0033333334f;
|
|
||||||
else
|
|
||||||
weapon->weapVariantDef.fOOPosAnimLength[0] = 1.0f / static_cast<float>(weapon->weapVariantDef.iAdsTransInTime);
|
|
||||||
|
|
||||||
if (weapon->weapVariantDef.iAdsTransOutTime <= 0)
|
|
||||||
weapon->weapVariantDef.fOOPosAnimLength[1] = 0.0020000001f;
|
|
||||||
else
|
|
||||||
weapon->weapVariantDef.fOOPosAnimLength[1] = 1.0f / static_cast<float>(weapon->weapVariantDef.iAdsTransOutTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::IsStringOverride(const char* baseString, const char* overrideString)
|
|
||||||
{
|
|
||||||
if (overrideString == nullptr || overrideString[0] == '\0')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (baseString == nullptr || baseString[0] == '\0')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return strcmp(baseString, overrideString) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect)
|
|
||||||
{
|
|
||||||
if (overrideEffect == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (baseEffect == nullptr)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return strcmp(baseEffect->name, overrideEffect->name) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique,
|
|
||||||
const char* snd1,
|
|
||||||
const char* snd2,
|
|
||||||
const eAttachmentOverrideSounds sndOverrideIndex)
|
|
||||||
{
|
|
||||||
if (IsStringOverride(snd1, snd2))
|
|
||||||
attachmentUnique->soundOverrides |= 1 << static_cast<unsigned>(sndOverrideIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::HandleFxOverride(WeaponAttachmentUnique* attachmentUnique,
|
|
||||||
const FxEffectDef* effect1,
|
|
||||||
const FxEffectDef* effect2,
|
|
||||||
const eAttachmentOverrideEffects fxOverrideIndex)
|
|
||||||
{
|
|
||||||
if (IsFxOverride(effect1, effect2))
|
|
||||||
attachmentUnique->effectOverrides |= 1 << static_cast<unsigned>(fxOverrideIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique)
|
|
||||||
{
|
|
||||||
for (auto& val : attachmentUnique->animationOverrides)
|
|
||||||
val = 0;
|
|
||||||
|
|
||||||
for (auto animIndex = 0u; animIndex < std::extent_v<decltype(WeaponFullDef::szXAnims)>; animIndex++)
|
|
||||||
{
|
|
||||||
if (IsStringOverride(weapon->szXAnims[animIndex], attachmentUnique->szXAnims[animIndex]))
|
|
||||||
attachmentUnique->animationOverrides[animIndex / 32] |= 1 << (animIndex % 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentUnique->soundOverrides = 0;
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSound, attachmentUnique->fireSound, ATTACHMENT_OVERRIDE_SOUND_FIRE);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSoundPlayer, attachmentUnique->fireSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_PLAYER);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopSound, attachmentUnique->fireLoopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP);
|
|
||||||
HandleSoundOverride(
|
|
||||||
attachmentUnique, weapon->weapDef.fireLoopSoundPlayer, attachmentUnique->fireLoopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_PLAYER);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopEndSound, attachmentUnique->fireLoopEndSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END);
|
|
||||||
HandleSoundOverride(
|
|
||||||
attachmentUnique, weapon->weapDef.fireLoopEndSoundPlayer, attachmentUnique->fireLoopEndSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END_PLAYER);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStartSound, attachmentUnique->fireStartSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_START);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStopSound, attachmentUnique->fireStopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP);
|
|
||||||
HandleSoundOverride(
|
|
||||||
attachmentUnique, weapon->weapDef.fireStartSoundPlayer, attachmentUnique->fireStartSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_START_PLAYER);
|
|
||||||
HandleSoundOverride(
|
|
||||||
attachmentUnique, weapon->weapDef.fireStopSoundPlayer, attachmentUnique->fireStopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP_PLAYER);
|
|
||||||
HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLastSound, attachmentUnique->fireLastSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST);
|
|
||||||
HandleSoundOverride(
|
|
||||||
attachmentUnique, weapon->weapDef.fireLastSoundPlayer, attachmentUnique->fireLastSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST_PLAYER);
|
|
||||||
|
|
||||||
attachmentUnique->effectOverrides = 0;
|
|
||||||
HandleFxOverride(attachmentUnique, weapon->weapDef.viewFlashEffect, attachmentUnique->viewFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_VIEW_FLASH);
|
|
||||||
HandleFxOverride(attachmentUnique, weapon->weapDef.worldFlashEffect, attachmentUnique->worldFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_WORLD_FLASH);
|
|
||||||
|
|
||||||
attachmentUnique->childLink = 0;
|
|
||||||
if (attachmentUnique->combinedAttachmentTypeMask == 0)
|
|
||||||
{
|
|
||||||
WeaponAttachmentUnique* lastSibling = nullptr;
|
|
||||||
for (auto attachmentUniqueIndex = std::extent_v<decltype(WeaponFullDef::attachments)>;
|
|
||||||
attachmentUniqueIndex < std::extent_v<decltype(WeaponFullDef::attachmentUniques)>;
|
|
||||||
attachmentUniqueIndex++)
|
|
||||||
{
|
|
||||||
if (weapon->attachmentUniques[attachmentUniqueIndex] != nullptr
|
|
||||||
&& weapon->attachmentUniques[attachmentUniqueIndex]->combinedAttachmentTypeMask & (1 << static_cast<unsigned>(attachmentUnique->attachmentType))
|
|
||||||
&& weapon->attachmentUniques[attachmentUniqueIndex]->attachmentType != attachmentUnique->attachmentType)
|
|
||||||
{
|
|
||||||
std::vector<eAttachment> attachments;
|
|
||||||
if (AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(weapon->attachmentUniques[attachmentUniqueIndex]->szInternalName,
|
|
||||||
attachments)
|
|
||||||
&& attachments.front() == attachmentUnique->attachmentType)
|
|
||||||
{
|
|
||||||
if (lastSibling == nullptr)
|
|
||||||
{
|
|
||||||
attachmentUnique->childLink = attachmentUniqueIndex;
|
|
||||||
lastSibling = weapon->attachmentUniques[attachmentUniqueIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastSibling->siblingLink = attachmentUniqueIndex;
|
|
||||||
lastSibling = weapon->attachmentUniques[attachmentUniqueIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon)
|
|
||||||
{
|
|
||||||
for (auto attachmentUniqueIndex = 0u; attachmentUniqueIndex < std::extent_v<decltype(WeaponFullDef::attachmentUniques)>; attachmentUniqueIndex++)
|
|
||||||
{
|
|
||||||
if (weapon->attachmentUniques[attachmentUniqueIndex] == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CalculateAttachmentFields(weapon, attachmentUniqueIndex, weapon->attachmentUniques[attachmentUniqueIndex]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* weaponFullDef = memory->Create<WeaponFullDef>();
|
|
||||||
memset(weaponFullDef, 0, sizeof(WeaponFullDef));
|
|
||||||
LinkWeaponFullDefSubStructs(weaponFullDef);
|
|
||||||
|
|
||||||
InfoStringToWeaponConverter converter(
|
|
||||||
infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v<decltype(weapon_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
// TODO: Load flametable
|
|
||||||
CalculateWeaponFields(weaponFullDef);
|
|
||||||
CalculateAttachmentFields(weaponFullDef);
|
|
||||||
|
|
||||||
LoadAccuracyGraphs(weaponFullDef, memory, manager);
|
|
||||||
|
|
||||||
manager->AddAsset<AssetWeapon>(
|
|
||||||
assetName, &weaponFullDef->weapVariantDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* weaponFullDef = memory->Alloc<WeaponFullDef>();
|
|
||||||
LinkWeaponFullDefSubStructs(weaponFullDef);
|
|
||||||
CalculateWeaponFields(weaponFullDef);
|
|
||||||
weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
return weaponFullDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeapon::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "weapons/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderWeapon final : public BasicAssetLoader<AssetWeapon>
|
|
||||||
{
|
|
||||||
static void LinkWeaponFullDefSubStructs(WeaponFullDef* weapon);
|
|
||||||
|
|
||||||
static bool IsStringOverride(const char* baseString, const char* overrideString);
|
|
||||||
static bool IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect);
|
|
||||||
static void
|
|
||||||
HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique, const char* snd1, const char* snd2, eAttachmentOverrideSounds sndOverrideIndex);
|
|
||||||
static void HandleFxOverride(WeaponAttachmentUnique* attachmentUnique,
|
|
||||||
const FxEffectDef* effect1,
|
|
||||||
const FxEffectDef* effect2,
|
|
||||||
eAttachmentOverrideEffects fxOverrideIndex);
|
|
||||||
|
|
||||||
static void CalculateWeaponFields(WeaponFullDef* weapon);
|
|
||||||
static void CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique);
|
|
||||||
static void CalculateAttachmentFields(const WeaponFullDef* weapon);
|
|
||||||
|
|
||||||
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 T6
|
|
@ -1,172 +0,0 @@
|
|||||||
#include "AssetLoaderWeaponAttachment.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/EnumStrings.h"
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/WeaponAttachmentFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
eAttachmentPoint attachmentPointByAttachmentTable[]{
|
|
||||||
ATTACHMENT_POINT_NONE, // none
|
|
||||||
ATTACHMENT_POINT_TOP, // acog
|
|
||||||
ATTACHMENT_POINT_TRIGGER, // dualclip
|
|
||||||
ATTACHMENT_POINT_TOP, // dualoptic
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // dw
|
|
||||||
ATTACHMENT_POINT_MUZZLE, // extbarrel
|
|
||||||
ATTACHMENT_POINT_TRIGGER, // extclip
|
|
||||||
ATTACHMENT_POINT_TRIGGER, // extramags
|
|
||||||
ATTACHMENT_POINT_GUNPERK, // fastads
|
|
||||||
ATTACHMENT_POINT_TOP, // fastreload
|
|
||||||
ATTACHMENT_POINT_TRIGGER, // fmj
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // gl
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // grip
|
|
||||||
ATTACHMENT_POINT_TOP, // holo
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // ir
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // is
|
|
||||||
ATTACHMENT_POINT_GUNPERK, // longbreath
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // mk
|
|
||||||
ATTACHMENT_POINT_TOP, // mms
|
|
||||||
ATTACHMENT_POINT_TOP, // rangefinder
|
|
||||||
ATTACHMENT_POINT_TOP, // reflex
|
|
||||||
ATTACHMENT_POINT_MUZZLE, // rf
|
|
||||||
ATTACHMENT_POINT_BOTTOM, // sf
|
|
||||||
ATTACHMENT_POINT_MUZZLE, // silencer
|
|
||||||
ATTACHMENT_POINT_TRIGGER, // stackfire
|
|
||||||
ATTACHMENT_POINT_GUNPERK, // stalker
|
|
||||||
ATTACHMENT_POINT_GUNPERK, // steadyaim
|
|
||||||
ATTACHMENT_POINT_GUNPERK, // swayreduc
|
|
||||||
ATTACHMENT_POINT_TOP, // tacknife
|
|
||||||
ATTACHMENT_POINT_TOP, // vzoom
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(std::extent_v<decltype(attachmentPointByAttachmentTable)> == ATTACHMENT_TYPE_COUNT);
|
|
||||||
|
|
||||||
class InfoStringToWeaponAttachmentConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
switch (static_cast<attachmentFieldType_t>(field.iFieldType))
|
|
||||||
{
|
|
||||||
case AFT_ATTACHMENTTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v<decltype(szAttachmentTypeNames)>);
|
|
||||||
|
|
||||||
case AFT_PENETRATE_TYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v<decltype(penetrateTypeNames)>);
|
|
||||||
|
|
||||||
case AFT_FIRETYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v<decltype(szWeapFireTypeNames)>);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToWeaponAttachmentConverter(const InfoString& infoString,
|
|
||||||
WeaponAttachment* weaponAttachment,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, weaponAttachment, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
void AssetLoaderWeaponAttachment::CalculateAttachmentFields(WeaponAttachment* attachment)
|
|
||||||
{
|
|
||||||
// attachmentPoint
|
|
||||||
if (static_cast<unsigned>(attachment->attachmentType) < ATTACHMENT_TYPE_COUNT)
|
|
||||||
{
|
|
||||||
attachment->attachmentPoint = attachmentPointByAttachmentTable[attachment->attachmentType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachment::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* attachment = memory->Create<WeaponAttachment>();
|
|
||||||
memset(attachment, 0, sizeof(WeaponAttachment));
|
|
||||||
|
|
||||||
InfoStringToWeaponAttachmentConverter converter(
|
|
||||||
infoString, attachment, zone->m_script_strings, memory, manager, attachment_fields, std::extent_v<decltype(attachment_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse attachment: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalculateAttachmentFields(attachment);
|
|
||||||
attachment->szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
manager->AddAsset<AssetAttachment>(
|
|
||||||
assetName, attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderWeaponAttachment::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* attachment = memory->Alloc<WeaponAttachment>();
|
|
||||||
CalculateAttachmentFields(attachment);
|
|
||||||
attachment->szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
return attachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachment::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachment::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to read attachment gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachment::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachment::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "attachment/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderWeaponAttachment final : public BasicAssetLoader<AssetAttachment>
|
|
||||||
{
|
|
||||||
static void CalculateAttachmentFields(WeaponAttachment* attachment);
|
|
||||||
|
|
||||||
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 T6
|
|
@ -1,292 +0,0 @@
|
|||||||
#include "AssetLoaderWeaponAttachmentUnique.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/EnumStrings.h"
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/WeaponAttachmentUniqueFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "Utils/ClassUtils.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class InfoStringToWeaponAttachmentUniqueConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
bool ConvertHideTags(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
std::vector<std::string> valueArray;
|
|
||||||
if (!ParseAsArray(value, valueArray))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse hide tags as array\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::hideTags)> << " hide tags!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
|
||||||
|
|
||||||
if (valueArray.size() < std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
|
||||||
{
|
|
||||||
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto currentHideTag = 0u;
|
|
||||||
for (; currentHideTag < valueArray.size(); currentHideTag++)
|
|
||||||
{
|
|
||||||
const auto& currentValue = valueArray[currentHideTag];
|
|
||||||
const auto scrString =
|
|
||||||
!currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr);
|
|
||||||
hideTags[currentHideTag] = scrString;
|
|
||||||
m_used_script_string_list.emplace(scrString);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; currentHideTag < std::extent_v<decltype(WeaponFullDef::hideTags)>; currentHideTag++)
|
|
||||||
{
|
|
||||||
hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
if (value.empty())
|
|
||||||
{
|
|
||||||
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* camo = m_loading_manager->LoadDependency<AssetWeaponCamo>(value);
|
|
||||||
|
|
||||||
if (camo == nullptr)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to load camo asset \"" << value << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dependencies.emplace(camo);
|
|
||||||
*reinterpret_cast<WeaponCamo**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = camo->Asset();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConvertAnimName(const cspField_t& field, const std::string& value)
|
|
||||||
{
|
|
||||||
if (ConvertString(value, field.iOffset))
|
|
||||||
{
|
|
||||||
if (!value.empty())
|
|
||||||
m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference<AssetXAnim>(value));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
switch (static_cast<attachmentUniqueFieldType_t>(field.iFieldType))
|
|
||||||
{
|
|
||||||
case AUFT_ATTACHMENTTYPE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v<decltype(szAttachmentTypeNames)>);
|
|
||||||
|
|
||||||
case AUFT_HIDETAGS:
|
|
||||||
return ConvertHideTags(field, value);
|
|
||||||
|
|
||||||
case AUFT_OVERLAYRETICLE:
|
|
||||||
return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v<decltype(szWeapOverlayReticleNames)>);
|
|
||||||
|
|
||||||
case AUFT_CAMO:
|
|
||||||
return ConvertWeaponCamo(field, value);
|
|
||||||
|
|
||||||
case AUFT_ANIM_NAME:
|
|
||||||
return ConvertAnimName(field, value);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToWeaponAttachmentUniqueConverter(const InfoString& infoString,
|
|
||||||
WeaponAttachmentUniqueFull* attachmentUniqueFull,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, attachmentUniqueFull, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector<eAttachment>& attachmentList)
|
|
||||||
{
|
|
||||||
std::vector<std::string> parts;
|
|
||||||
|
|
||||||
auto attachCount = 1u;
|
|
||||||
auto partStart = 0u;
|
|
||||||
for (auto ci = 0u; ci < assetName.size(); ci++)
|
|
||||||
{
|
|
||||||
if (assetName[ci] == '_')
|
|
||||||
{
|
|
||||||
parts.emplace_back(assetName, partStart, ci - partStart);
|
|
||||||
partStart = ci + 1;
|
|
||||||
}
|
|
||||||
else if (assetName[ci] == '+')
|
|
||||||
{
|
|
||||||
attachCount++;
|
|
||||||
parts.emplace_back(assetName, partStart, ci - partStart);
|
|
||||||
partStart = ci + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partStart < assetName.size())
|
|
||||||
parts.emplace_back(assetName, partStart, assetName.size() - partStart);
|
|
||||||
|
|
||||||
for (auto attachPartOffset = parts.size() - attachCount; attachPartOffset < parts.size(); attachPartOffset++)
|
|
||||||
{
|
|
||||||
auto& specifiedAttachName = parts[attachPartOffset];
|
|
||||||
|
|
||||||
for (auto& c : specifiedAttachName)
|
|
||||||
c = static_cast<char>(tolower(c));
|
|
||||||
|
|
||||||
auto foundAttachment = false;
|
|
||||||
for (auto attachIndex = 0u; attachIndex < std::extent_v<decltype(szAttachmentTypeNames)>; attachIndex++)
|
|
||||||
{
|
|
||||||
if (specifiedAttachName == szAttachmentTypeNames[attachIndex])
|
|
||||||
{
|
|
||||||
attachmentList.push_back(static_cast<eAttachment>(attachIndex));
|
|
||||||
foundAttachment = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundAttachment)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetLoaderWeaponAttachmentUnique::LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique)
|
|
||||||
{
|
|
||||||
attachmentUnique->attachment.hideTags = attachmentUnique->hideTags;
|
|
||||||
attachmentUnique->attachment.szXAnims = attachmentUnique->szXAnims;
|
|
||||||
attachmentUnique->attachment.locationDamageMultipliers = attachmentUnique->locationDamageMultipliers;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique)
|
|
||||||
{
|
|
||||||
// combinedAttachmentTypeMask
|
|
||||||
std::vector<eAttachment> attachmentsFromName;
|
|
||||||
if (!ExtractAttachmentsFromAssetName(assetName, attachmentsFromName))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to determine attachments from attachment unique name \"" << assetName << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachmentsFromName.size() > 1)
|
|
||||||
{
|
|
||||||
for (const auto attachment : attachmentsFromName)
|
|
||||||
{
|
|
||||||
attachmentUnique->attachment.combinedAttachmentTypeMask |= 1 << attachment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
|
|
||||||
auto* attachmentUniqueFull = memory->Create<WeaponAttachmentUniqueFull>();
|
|
||||||
memset(attachmentUniqueFull, 0, sizeof(WeaponAttachmentUniqueFull));
|
|
||||||
LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull);
|
|
||||||
|
|
||||||
InfoStringToWeaponAttachmentUniqueConverter converter(
|
|
||||||
infoString, attachmentUniqueFull, zone->m_script_strings, memory, manager, attachment_unique_fields, std::extent_v<decltype(attachment_unique_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse attachment unique: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
manager->AddAsset<AssetAttachmentUnique>(
|
|
||||||
assetName, &attachmentUniqueFull->attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderWeaponAttachmentUnique::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* attachmentUniqueFull = memory->Alloc<WeaponAttachmentUniqueFull>();
|
|
||||||
LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull);
|
|
||||||
CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull);
|
|
||||||
attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str());
|
|
||||||
return attachmentUniqueFull;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to read attachment unique gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponAttachmentUnique::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "attachmentunique/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderWeaponAttachmentUnique final : public BasicAssetLoader<AssetAttachmentUnique>
|
|
||||||
{
|
|
||||||
static void LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique);
|
|
||||||
static bool CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique);
|
|
||||||
|
|
||||||
static bool
|
|
||||||
LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static bool ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector<eAttachment>& attachmentList);
|
|
||||||
|
|
||||||
_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 T6
|
|
@ -1,43 +0,0 @@
|
|||||||
#include "AssetLoaderWeaponCamo.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Game/T6/WeaponCamo/JsonWeaponCamoLoader.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderWeaponCamo::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetWeaponCamo::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponCamo::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderWeaponCamo::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = std::format("camo/{}.json", assetName);
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto* weaponCamo = memory->Alloc<WeaponCamo>();
|
|
||||||
weaponCamo->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
std::vector<XAssetInfoGeneric*> dependencies;
|
|
||||||
if (LoadWeaponCamoAsJson(*file.m_stream, *weaponCamo, memory, manager, dependencies))
|
|
||||||
manager->AddAsset<AssetWeaponCamo>(assetName, weaponCamo, std::move(dependencies));
|
|
||||||
else
|
|
||||||
std::cerr << "Failed to load weapon camo \"" << assetName << "\"\n";
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderWeaponCamo final : public BasicAssetLoader<AssetWeaponCamo>
|
|
||||||
{
|
|
||||||
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 T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderXAnim.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetXAnim::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderXAnim final : public BasicAssetLoader<AssetXAnim>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,13 +0,0 @@
|
|||||||
#include "AssetLoaderXGlobals.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderXGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetXGlobals::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderXGlobals final : public BasicAssetLoader<AssetXGlobals>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,47 +0,0 @@
|
|||||||
#include "AssetLoaderXModel.h"
|
|
||||||
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Game/T6/XModel/XModelLoaderT6.h"
|
|
||||||
#include "Pool/GlobalAssetPool.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* asset = memory->Alloc<AssetXModel::Type>();
|
|
||||||
asset->name = memory->Dup(assetName.c_str());
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderXModel::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderXModel::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName));
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto* xmodel = memory->Alloc<XModel>();
|
|
||||||
xmodel->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
std::vector<XAssetInfoGeneric*> dependencies;
|
|
||||||
if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies))
|
|
||||||
{
|
|
||||||
manager->AddAsset<AssetXModel>(assetName, xmodel, std::move(dependencies));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderXModel final : public BasicAssetLoader<AssetXModel>
|
|
||||||
{
|
|
||||||
static std::string GetFileNameForAsset(const std::string& assetName);
|
|
||||||
|
|
||||||
public:
|
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
|
||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
|
||||||
bool
|
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
@ -1,133 +0,0 @@
|
|||||||
#include "AssetLoaderZBarrier.h"
|
|
||||||
|
|
||||||
#include "Game/T6/InfoString/InfoStringToStructConverter.h"
|
|
||||||
#include "Game/T6/InfoString/ZBarrierFields.h"
|
|
||||||
#include "Game/T6/ObjConstantsT6.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class InfoStringToZBarrierConverter final : public InfoStringToStructConverter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
InfoStringToZBarrierConverter(const InfoString& infoString,
|
|
||||||
ZBarrierDef* zbarrier,
|
|
||||||
ZoneScriptStrings& zoneScriptStrings,
|
|
||||||
MemoryManager* memory,
|
|
||||||
IAssetLoadingManager* manager,
|
|
||||||
const cspField_t* fields,
|
|
||||||
const size_t fieldCount)
|
|
||||||
: InfoStringToStructConverter(infoString, zbarrier, zoneScriptStrings, memory, manager, fields, fieldCount)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace T6
|
|
||||||
|
|
||||||
void AssetLoaderZBarrier::CalculateZBarrierFields(ZBarrierDef* zbarrier)
|
|
||||||
{
|
|
||||||
// numBoardsInBarrier
|
|
||||||
{
|
|
||||||
auto foundEnd = false;
|
|
||||||
for (auto i = 0u; i < std::extent_v<decltype(ZBarrierDef::boards)>; i++)
|
|
||||||
{
|
|
||||||
if (zbarrier->boards[i].pBoardModel == nullptr)
|
|
||||||
{
|
|
||||||
foundEnd = true;
|
|
||||||
zbarrier->numBoardsInBarrier = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundEnd)
|
|
||||||
zbarrier->numBoardsInBarrier = std::extent_v<decltype(ZBarrierDef::boards)>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderZBarrier::LoadFromInfoString(
|
|
||||||
const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* zbarrier = memory->Create<ZBarrierDef>();
|
|
||||||
memset(zbarrier, 0, sizeof(ZBarrierDef));
|
|
||||||
|
|
||||||
InfoStringToZBarrierConverter converter(
|
|
||||||
infoString, zbarrier, zone->m_script_strings, memory, manager, zbarrier_fields, std::extent_v<decltype(zbarrier_fields)>);
|
|
||||||
if (!converter.Convert())
|
|
||||||
{
|
|
||||||
std::cout << "Failed to parse zbarrier: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalculateZBarrierFields(zbarrier);
|
|
||||||
zbarrier->name = memory->Dup(assetName.c_str());
|
|
||||||
|
|
||||||
manager->AddAsset<AssetZBarrier>(assetName, zbarrier, converter.GetDependencies(), converter.GetUsedScriptStrings());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderZBarrier::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
|
||||||
{
|
|
||||||
auto* zbarrier = memory->Alloc<ZBarrierDef>();
|
|
||||||
CalculateZBarrierFields(zbarrier);
|
|
||||||
zbarrier->name = memory->Dup(assetName.c_str());
|
|
||||||
return zbarrier;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderZBarrier::CanLoadFromGdt() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderZBarrier::LoadFromGdt(
|
|
||||||
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_ZBARRIER, assetName);
|
|
||||||
if (gdtEntry == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromGdtProperties(*gdtEntry))
|
|
||||||
{
|
|
||||||
std::cout << "Failed to read zbarrier gdt entry: \"" << assetName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderZBarrier::CanLoadFromRaw() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetLoaderZBarrier::LoadFromRaw(
|
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
|
||||||
{
|
|
||||||
const auto fileName = "zbarrier/" + assetName;
|
|
||||||
const auto file = searchPath->Open(fileName);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InfoString infoString;
|
|
||||||
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, *file.m_stream))
|
|
||||||
{
|
|
||||||
std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetLoading/BasicAssetLoader.h"
|
|
||||||
#include "AssetLoading/IAssetLoadingManager.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "InfoString/InfoString.h"
|
|
||||||
#include "SearchPath/ISearchPath.h"
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
class AssetLoaderZBarrier final : public BasicAssetLoader<AssetZBarrier>
|
|
||||||
{
|
|
||||||
static void CalculateZBarrierFields(ZBarrierDef* zbarrier);
|
|
||||||
|
|
||||||
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 T6
|
|
292
src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.cpp
Normal file
292
src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.cpp
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
#include "LoaderFontIconT6.h"
|
||||||
|
|
||||||
|
#include "Csv/CsvStream.h"
|
||||||
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace T6;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr unsigned ROW_INDEX = 0;
|
||||||
|
constexpr unsigned ROW_TYPE = 1;
|
||||||
|
|
||||||
|
constexpr unsigned ROW_ICON_NAME = 2;
|
||||||
|
constexpr unsigned ROW_ICON_MATERIAL = 3;
|
||||||
|
constexpr unsigned ROW_ICON_SIZE = 4;
|
||||||
|
constexpr unsigned ROW_ICON_XSCALE = 5;
|
||||||
|
constexpr unsigned ROW_ICON_YSCALE = 6;
|
||||||
|
|
||||||
|
constexpr unsigned ROW_ALIAS_NAME = 2;
|
||||||
|
constexpr unsigned ROW_ALIAS_BUTTON = 3;
|
||||||
|
|
||||||
|
constexpr const char* VALUE_TYPE_ICON = "icon";
|
||||||
|
constexpr const char* VALUE_TYPE_ALIAS = "alias";
|
||||||
|
|
||||||
|
constexpr unsigned COL_COUNT_ICON = 7;
|
||||||
|
constexpr unsigned COL_COUNT_ALIAS = 4;
|
||||||
|
constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS);
|
||||||
|
|
||||||
|
class FontIconLoader final : public AssetCreator<AssetFontIcon>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FontIconLoader(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(assetName);
|
||||||
|
if (!file.IsOpen())
|
||||||
|
return AssetCreationResult::NoAction();
|
||||||
|
|
||||||
|
auto* fontIcon = m_memory.Alloc<FontIcon>();
|
||||||
|
fontIcon->name = m_memory.Dup(assetName.c_str());
|
||||||
|
AssetRegistration<AssetFontIcon> registration(assetName, fontIcon);
|
||||||
|
|
||||||
|
const CsvInputStream csv(*file.m_stream);
|
||||||
|
std::vector<std::string> currentRow;
|
||||||
|
std::vector<FontIconEntry> entries;
|
||||||
|
std::vector<FontIconAlias> aliases;
|
||||||
|
auto currentRowIndex = 0u;
|
||||||
|
|
||||||
|
while (csv.NextRow(currentRow))
|
||||||
|
{
|
||||||
|
currentRowIndex++;
|
||||||
|
PreprocessRow(currentRow);
|
||||||
|
|
||||||
|
if (RowIsEmpty(currentRow))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (currentRow.size() < COL_COUNT_MIN)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Column count lower than min column count ({})\n", ErrorPrefix(assetName, currentRowIndex), COL_COUNT_MIN);
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to parse index\n", ErrorPrefix(assetName, currentRowIndex));
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON)
|
||||||
|
{
|
||||||
|
FontIconEntry icon{};
|
||||||
|
if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, context, registration))
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
|
||||||
|
if (static_cast<unsigned>(index) == entries.size())
|
||||||
|
{
|
||||||
|
entries.push_back(icon);
|
||||||
|
}
|
||||||
|
else if (static_cast<unsigned>(index) > entries.size())
|
||||||
|
{
|
||||||
|
entries.reserve(index + 1);
|
||||||
|
entries[index] = icon;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entries[index] = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS)
|
||||||
|
{
|
||||||
|
FontIconAlias alias{};
|
||||||
|
if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, context))
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
|
||||||
|
if (static_cast<unsigned>(index) == aliases.size())
|
||||||
|
{
|
||||||
|
aliases.push_back(alias);
|
||||||
|
}
|
||||||
|
else if (static_cast<unsigned>(index) > aliases.size())
|
||||||
|
{
|
||||||
|
aliases.reserve(index + 1);
|
||||||
|
aliases[index] = alias;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aliases[index] = alias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Unknown row type \"{}\"\n", ErrorPrefix(assetName, currentRowIndex), currentRow[ROW_TYPE]);
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fontIcon->numEntries = entries.size();
|
||||||
|
fontIcon->numAliasEntries = aliases.size();
|
||||||
|
|
||||||
|
if (fontIcon->numEntries > 0)
|
||||||
|
{
|
||||||
|
fontIcon->fontIconEntry = m_memory.Alloc<FontIconEntry>(fontIcon->numEntries);
|
||||||
|
for (auto i = 0u; i < entries.size(); i++)
|
||||||
|
fontIcon->fontIconEntry[i] = entries[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fontIcon->fontIconEntry = nullptr;
|
||||||
|
|
||||||
|
if (fontIcon->numAliasEntries > 0)
|
||||||
|
{
|
||||||
|
fontIcon->fontIconAlias = m_memory.Alloc<FontIconAlias>(fontIcon->numAliasEntries);
|
||||||
|
for (auto i = 0u; i < aliases.size(); i++)
|
||||||
|
fontIcon->fontIconAlias[i] = aliases[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fontIcon->fontIconAlias = nullptr;
|
||||||
|
|
||||||
|
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::string ErrorPrefix(const std::string& assetName, const unsigned rowIndex)
|
||||||
|
{
|
||||||
|
return std::format("FontIcon \"{}\" Row {}:", assetName, rowIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PreprocessRow(std::vector<std::string>& row)
|
||||||
|
{
|
||||||
|
for (auto& cell : row)
|
||||||
|
{
|
||||||
|
for (auto c : cell)
|
||||||
|
{
|
||||||
|
if (isspace(c))
|
||||||
|
continue;
|
||||||
|
if (c == '#')
|
||||||
|
cell = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RowIsEmpty(const std::vector<std::string>& row)
|
||||||
|
{
|
||||||
|
return std::ranges::all_of(row,
|
||||||
|
[](const std::string& cell)
|
||||||
|
{
|
||||||
|
return cell.empty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseInt(int& value, const std::string& str)
|
||||||
|
{
|
||||||
|
char* endPtr;
|
||||||
|
value = strtol(str.c_str(), &endPtr, 0);
|
||||||
|
if (endPtr != &str[str.size()])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseFloat(float& value, const std::string& str)
|
||||||
|
{
|
||||||
|
char* endPtr;
|
||||||
|
value = strtof(str.c_str(), &endPtr);
|
||||||
|
if (endPtr != &str[str.size()])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseHashStr(int& value, const std::string& str)
|
||||||
|
{
|
||||||
|
if (!str.empty() && str[0] == '@' && str.size() > 1)
|
||||||
|
{
|
||||||
|
char* endPtr;
|
||||||
|
value = strtol(&str[1], &endPtr, 16);
|
||||||
|
|
||||||
|
if (endPtr != &str[str.size()])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = Common::Com_HashString(str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadIconRow(const std::vector<std::string>& row,
|
||||||
|
FontIconEntry& icon,
|
||||||
|
const std::string& assetName,
|
||||||
|
const unsigned rowIndex,
|
||||||
|
AssetCreationContext& context,
|
||||||
|
AssetRegistration<AssetFontIcon>& registration)
|
||||||
|
{
|
||||||
|
if (row.size() < COL_COUNT_ICON)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Column count lower than min column count for entries ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ICON);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE]))
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to parse size\n", ErrorPrefix(assetName, rowIndex));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE]))
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to parse scale\n", ErrorPrefix(assetName, rowIndex));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* materialDependency = context.LoadDependency<AssetMaterial>(row[ROW_ICON_MATERIAL]);
|
||||||
|
if (materialDependency == nullptr)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to load material \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ICON_MATERIAL]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
icon.fontIconMaterialHandle = materialDependency->Asset();
|
||||||
|
icon.fontIconName.string = m_memory.Dup(row[ROW_ICON_NAME].c_str());
|
||||||
|
icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadAliasRow(
|
||||||
|
const std::vector<std::string>& row, FontIconAlias& alias, const std::string& assetName, const unsigned rowIndex, AssetCreationContext& context)
|
||||||
|
{
|
||||||
|
if (row.size() < COL_COUNT_ALIAS)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Column count lower than min column count for aliases ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ALIAS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME]))
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to parse alias \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_NAME]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON]))
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} Failed to parse button \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_BUTTON]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager& m_memory;
|
||||||
|
ISearchPath& m_search_path;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
std::unique_ptr<AssetCreator<AssetFontIcon>> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||||
|
{
|
||||||
|
return std::make_unique<FontIconLoader>(memory, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace T6
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user