mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
feat: load materials from json
This commit is contained in:
parent
1f6d0ab51a
commit
0bb17a33bd
@ -2913,9 +2913,7 @@ namespace T6
|
|||||||
GFXS_POLYGON_OFFSET_0 = 0,
|
GFXS_POLYGON_OFFSET_0 = 0,
|
||||||
GFXS_POLYGON_OFFSET_1 = 1,
|
GFXS_POLYGON_OFFSET_1 = 1,
|
||||||
GFXS_POLYGON_OFFSET_2 = 2,
|
GFXS_POLYGON_OFFSET_2 = 2,
|
||||||
GFXS_POLYGON_OFFSET_SHADOWMAP = 3,
|
GFXS_POLYGON_OFFSET_SHADOWMAP = 3
|
||||||
|
|
||||||
GFXS_POLYGON_OFFSET_COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GfxStencilOp
|
enum GfxStencilOp
|
||||||
@ -2927,9 +2925,7 @@ namespace T6
|
|||||||
GFXS_STENCILOP_DECRSAT = 0x4,
|
GFXS_STENCILOP_DECRSAT = 0x4,
|
||||||
GFXS_STENCILOP_INVERT = 0x5,
|
GFXS_STENCILOP_INVERT = 0x5,
|
||||||
GFXS_STENCILOP_INCR = 0x6,
|
GFXS_STENCILOP_INCR = 0x6,
|
||||||
GFXS_STENCILOP_DECR = 0x7,
|
GFXS_STENCILOP_DECR = 0x7
|
||||||
|
|
||||||
GFXS_STENCILOP_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GfxStencilFunc
|
enum GfxStencilFunc
|
||||||
@ -2941,9 +2937,7 @@ namespace T6
|
|||||||
GFXS_STENCILFUNC_GREATER = 0x4,
|
GFXS_STENCILFUNC_GREATER = 0x4,
|
||||||
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
|
GFXS_STENCILFUNC_NOTEQUAL = 0x5,
|
||||||
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
|
GFXS_STENCILFUNC_GREATEREQUAL = 0x6,
|
||||||
GFXS_STENCILFUNC_ALWAYS = 0x7,
|
GFXS_STENCILFUNC_ALWAYS = 0x7
|
||||||
|
|
||||||
GFXS_STENCILFUNC_COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GfxStateBitsLoadBitsStructured
|
struct GfxStateBitsLoadBitsStructured
|
||||||
|
@ -199,9 +199,9 @@ namespace T6
|
|||||||
|
|
||||||
inline void from_json(const nlohmann::json& in, JsonConstant& out)
|
inline void from_json(const nlohmann::json& in, JsonConstant& out)
|
||||||
{
|
{
|
||||||
in.at("name").get_to(out.name);
|
in.value("name", nlohmann::json()).get_to(out.name);
|
||||||
in.at("nameFragment").get_to(out.nameFragment);
|
in.value("nameFragment", nlohmann::json()).get_to(out.nameFragment);
|
||||||
in.at("nameHash").get_to(out.nameHash);
|
in.value("nameHash", nlohmann::json()).get_to(out.nameHash);
|
||||||
in.at("literal").get_to(out.literal);
|
in.at("literal").get_to(out.literal);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -301,10 +301,10 @@ namespace T6
|
|||||||
|
|
||||||
inline void from_json(const nlohmann::json& in, JsonTexture& out)
|
inline void from_json(const nlohmann::json& in, JsonTexture& out)
|
||||||
{
|
{
|
||||||
in.at("name").get_to(out.name);
|
in.value("name", nlohmann::json()).get_to(out.name);
|
||||||
in.at("nameHash").get_to(out.nameHash);
|
in.value("nameHash", nlohmann::json()).get_to(out.nameHash);
|
||||||
in.at("nameStart").get_to(out.nameStart);
|
in.value("nameStart", nlohmann::json()).get_to(out.nameStart);
|
||||||
in.at("nameEnd").get_to(out.nameEnd);
|
in.value("nameEnd", nlohmann::json()).get_to(out.nameEnd);
|
||||||
in.at("semantic").get_to(out.semantic);
|
in.at("semantic").get_to(out.semantic);
|
||||||
in.at("isMatureContent").get_to(out.isMatureContent);
|
in.at("isMatureContent").get_to(out.isMatureContent);
|
||||||
in.at("samplerState").get_to(out.samplerState);
|
in.at("samplerState").get_to(out.samplerState);
|
||||||
|
@ -36,6 +36,11 @@ public:
|
|||||||
return AddAsset(assetType, assetName, asset, std::vector<XAssetInfoGeneric*>(), std::vector<scr_string_t>());
|
return AddAsset(assetType, assetName, asset, std::vector<XAssetInfoGeneric*>(), std::vector<scr_string_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XAssetInfoGeneric* AddAsset(const asset_type_t assetType, const std::string& assetName, void* asset, std::vector<XAssetInfoGeneric*> dependencies)
|
||||||
|
{
|
||||||
|
return AddAsset(assetType, assetName, asset, std::move(dependencies), std::vector<scr_string_t>());
|
||||||
|
}
|
||||||
|
|
||||||
virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0;
|
virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0;
|
||||||
virtual IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) = 0;
|
virtual IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) = 0;
|
||||||
};
|
};
|
||||||
|
59
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp
Normal file
59
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "AssetLoaderMaterial.h"
|
||||||
|
|
||||||
|
#include "Game/T6/Material/JsonMaterialLoader.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace T6;
|
||||||
|
|
||||||
|
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
|
{
|
||||||
|
auto* material = memory->Create<Material>();
|
||||||
|
memset(material, 0, sizeof(Material));
|
||||||
|
material->info.name = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderMaterial::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 = static_cast<Material*>(memory->Alloc(sizeof(Material)));
|
||||||
|
memset(material, 0, sizeof(Material));
|
||||||
|
material->info.name = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
std::vector<XAssetInfoGeneric*> dependencies;
|
||||||
|
if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies))
|
||||||
|
manager->AddAsset(ASSET_TYPE_MATERIAL, assetName, material, std::move(dependencies));
|
||||||
|
else
|
||||||
|
std::cerr << "Failed to load material \"" << assetName << "\"\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
19
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h
Normal file
19
src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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<ASSET_TYPE_MATERIAL, Material>
|
||||||
|
{
|
||||||
|
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
|
@ -0,0 +1,372 @@
|
|||||||
|
#include "JsonMaterialLoader.h"
|
||||||
|
|
||||||
|
#include "Game/T6/CommonT6.h"
|
||||||
|
#include "Game/T6/Material/JsonMaterial.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
class JsonLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector<XAssetInfoGeneric*>& dependencies)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_memory(memory),
|
||||||
|
m_manager(manager),
|
||||||
|
m_dependencies(dependencies)
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load(Material& material) const
|
||||||
|
{
|
||||||
|
const auto jRoot = json::parse(m_stream);
|
||||||
|
std::string type;
|
||||||
|
unsigned version;
|
||||||
|
|
||||||
|
jRoot.at("_type").get_to(type);
|
||||||
|
jRoot.at("_version").get_to(version);
|
||||||
|
|
||||||
|
if (type != "material" || version != 1u)
|
||||||
|
{
|
||||||
|
std::cerr << "Tried to load material \"" << material.info.name << "\" but did not find expected type material of version 1\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto jMaterial = jRoot.get<JsonMaterial>();
|
||||||
|
return CreateMaterialFromJson(jMaterial, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void PrintError(const Material& material, const std::string& message)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot load material \"" << material.info.name << "\": " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
|
||||||
|
{
|
||||||
|
for (const auto gameFlag : jMaterial.gameFlags)
|
||||||
|
gameFlags |= gameFlag;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateTextureDefFromJson(const JsonTexture& jTexture, MaterialTextureDef& textureDef, const Material& material) const
|
||||||
|
{
|
||||||
|
if (jTexture.name)
|
||||||
|
{
|
||||||
|
if (jTexture.name->empty())
|
||||||
|
{
|
||||||
|
PrintError(material, "textureDef name cannot be empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.nameStart = jTexture.name.value()[0];
|
||||||
|
textureDef.nameEnd = jTexture.name.value()[jTexture.name->size() - 1];
|
||||||
|
textureDef.nameHash = Common::R_HashString(jTexture.name.value().c_str(), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!jTexture.nameStart || !jTexture.nameEnd || !jTexture.nameHash)
|
||||||
|
{
|
||||||
|
PrintError(material, "textureDefs without name must have nameStart, nameEnd and nameHash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jTexture.nameStart->size() != 1 || jTexture.nameEnd->size() != 1)
|
||||||
|
{
|
||||||
|
PrintError(material, "nameStart and nameEnd must be a string of exactly one character");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.nameStart = jTexture.nameStart.value()[0];
|
||||||
|
textureDef.nameEnd = jTexture.nameEnd.value()[0];
|
||||||
|
textureDef.nameHash = jTexture.nameHash.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
textureDef.samplerState.filter = jTexture.samplerState.filter;
|
||||||
|
textureDef.samplerState.mipMap = jTexture.samplerState.mipMap;
|
||||||
|
textureDef.samplerState.clampU = jTexture.samplerState.clampU;
|
||||||
|
textureDef.samplerState.clampV = jTexture.samplerState.clampV;
|
||||||
|
textureDef.samplerState.clampW = jTexture.samplerState.clampW;
|
||||||
|
|
||||||
|
textureDef.semantic = jTexture.semantic;
|
||||||
|
textureDef.isMatureContent = jTexture.isMatureContent;
|
||||||
|
|
||||||
|
auto* image = static_cast<XAssetInfo<GfxImage>*>(m_manager.LoadDependency(ASSET_TYPE_IMAGE, jTexture.image));
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(image);
|
||||||
|
textureDef.image = image->Asset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CreateConstantDefFromJson(const JsonConstant& jConstant, MaterialConstantDef& constantDef, const Material& material)
|
||||||
|
{
|
||||||
|
if (jConstant.name)
|
||||||
|
{
|
||||||
|
const auto copyCount = std::min(jConstant.name->size() + 1, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
strncpy(constantDef.name, jConstant.name->c_str(), copyCount);
|
||||||
|
if (copyCount < std::extent_v<decltype(MaterialConstantDef::name)>)
|
||||||
|
memset(&constantDef.name[copyCount], 0, std::extent_v<decltype(MaterialConstantDef::name)> - copyCount);
|
||||||
|
constantDef.nameHash = Common::R_HashString(jConstant.name->c_str(), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!jConstant.nameFragment || !jConstant.nameHash)
|
||||||
|
{
|
||||||
|
PrintError(material, "constantDefs without name must have nameFragment and nameHash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto copyCount = std::min(jConstant.nameFragment->size() + 1, std::extent_v<decltype(MaterialConstantDef::name)>);
|
||||||
|
strncpy(constantDef.name, jConstant.nameFragment->c_str(), copyCount);
|
||||||
|
if (copyCount < std::extent_v<decltype(MaterialConstantDef::name)>)
|
||||||
|
memset(&constantDef.name[copyCount], 0, std::extent_v<decltype(MaterialConstantDef::name)> - copyCount);
|
||||||
|
constantDef.nameHash = jConstant.nameHash.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jConstant.literal.size() != 4)
|
||||||
|
{
|
||||||
|
PrintError(material, "constantDef literal must be array of size 4");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constantDef.literal.x = jConstant.literal[0];
|
||||||
|
constantDef.literal.y = jConstant.literal[1];
|
||||||
|
constantDef.literal.z = jConstant.literal[2];
|
||||||
|
constantDef.literal.w = jConstant.literal[3];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CreateStateBitsTableEntryFromJson(const JsonStateBitsTableEntry& jStateBitsTableEntry, GfxStateBits& stateBitsTableEntry, const Material& material)
|
||||||
|
{
|
||||||
|
auto& structured = stateBitsTableEntry.loadBits.structured;
|
||||||
|
|
||||||
|
structured.srcBlendRgb = jStateBitsTableEntry.srcBlendRgb;
|
||||||
|
structured.dstBlendRgb = jStateBitsTableEntry.dstBlendRgb;
|
||||||
|
structured.blendOpRgb = jStateBitsTableEntry.blendOpRgb;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::DISABLED)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 1;
|
||||||
|
structured.alphaTest = 0;
|
||||||
|
}
|
||||||
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GT0)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 0;
|
||||||
|
structured.alphaTest = GFXS_ALPHA_TEST_GT_0;
|
||||||
|
}
|
||||||
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128)
|
||||||
|
{
|
||||||
|
structured.alphaTestDisabled = 0;
|
||||||
|
structured.alphaTest = GFXS_ALPHA_TEST_GE_128;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for alphaTest");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.cullFace == JsonCullFace::NONE)
|
||||||
|
structured.cullFace = GFXS0_CULL_NONE;
|
||||||
|
else if (jStateBitsTableEntry.cullFace == JsonCullFace::BACK)
|
||||||
|
structured.cullFace = GFXS0_CULL_BACK;
|
||||||
|
else if (jStateBitsTableEntry.cullFace == JsonCullFace::FRONT)
|
||||||
|
structured.cullFace = GFXS0_CULL_FRONT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for cull face");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
structured.srcBlendAlpha = jStateBitsTableEntry.srcBlendAlpha;
|
||||||
|
structured.dstBlendAlpha = jStateBitsTableEntry.dstBlendAlpha;
|
||||||
|
structured.blendOpAlpha = jStateBitsTableEntry.blendOpAlpha;
|
||||||
|
structured.colorWriteRgb = jStateBitsTableEntry.colorWriteRgb;
|
||||||
|
structured.colorWriteAlpha = jStateBitsTableEntry.colorWriteAlpha;
|
||||||
|
structured.polymodeLine = jStateBitsTableEntry.polymodeLine;
|
||||||
|
structured.depthWrite = jStateBitsTableEntry.depthWrite;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.depthTest == JsonDepthTest::DISABLED)
|
||||||
|
structured.depthTestDisabled = 1;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::ALWAYS)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_ALWAYS;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::LESS)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_LESS;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::EQUAL)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_EQUAL;
|
||||||
|
else if (jStateBitsTableEntry.depthTest == JsonDepthTest::LESS_EQUAL)
|
||||||
|
structured.depthTest = GFXS_DEPTHTEST_LESSEQUAL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError(material, "Invalid value for depth test");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
structured.polygonOffset = jStateBitsTableEntry.polygonOffset;
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.stencilFront)
|
||||||
|
{
|
||||||
|
structured.stencilFrontEnabled = 1;
|
||||||
|
structured.stencilFrontPass = jStateBitsTableEntry.stencilFront->pass;
|
||||||
|
structured.stencilFrontFail = jStateBitsTableEntry.stencilFront->fail;
|
||||||
|
structured.stencilFrontZFail = jStateBitsTableEntry.stencilFront->zfail;
|
||||||
|
structured.stencilFrontFunc = jStateBitsTableEntry.stencilFront->func;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jStateBitsTableEntry.stencilBack)
|
||||||
|
{
|
||||||
|
structured.stencilBackEnabled = 1;
|
||||||
|
structured.stencilBackPass = jStateBitsTableEntry.stencilBack->pass;
|
||||||
|
structured.stencilBackFail = jStateBitsTableEntry.stencilBack->fail;
|
||||||
|
structured.stencilBackZFail = jStateBitsTableEntry.stencilBack->zfail;
|
||||||
|
structured.stencilBackFunc = jStateBitsTableEntry.stencilBack->func;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateMaterialFromJson(const JsonMaterial& jMaterial, Material& material) const
|
||||||
|
{
|
||||||
|
if (!CreateGameFlagsFromJson(jMaterial, material.info.gameFlags))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
material.info.sortKey = static_cast<unsigned char>(jMaterial.sortKey);
|
||||||
|
|
||||||
|
if (jMaterial.textureAtlas)
|
||||||
|
{
|
||||||
|
material.info.textureAtlasRowCount = jMaterial.textureAtlas->rows;
|
||||||
|
material.info.textureAtlasColumnCount = jMaterial.textureAtlas->columns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.info.textureAtlasRowCount = 0;
|
||||||
|
material.info.textureAtlasColumnCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
material.info.surfaceTypeBits = jMaterial.surfaceTypeBits;
|
||||||
|
material.info.layeredSurfaceTypes = jMaterial.layeredSurfaceTypes;
|
||||||
|
material.info.hashIndex = static_cast<uint16_t>(jMaterial.hashIndex);
|
||||||
|
material.info.surfaceFlags = jMaterial.surfaceFlags;
|
||||||
|
material.info.contents = jMaterial.contents;
|
||||||
|
|
||||||
|
if (jMaterial.stateBitsEntry.size() != std::extent_v<decltype(Material::stateBitsEntry)>)
|
||||||
|
{
|
||||||
|
PrintError(material, std::format("StateBitsEntry size is not {}", jMaterial.stateBitsEntry.size()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Material::stateBitsEntry)>; i++)
|
||||||
|
material.stateBitsEntry[i] = jMaterial.stateBitsEntry[i];
|
||||||
|
|
||||||
|
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
|
||||||
|
material.cameraRegion = jMaterial.cameraRegion;
|
||||||
|
material.probeMipBits = jMaterial.probeMipBits;
|
||||||
|
|
||||||
|
auto* techniqueSet = static_cast<XAssetInfo<MaterialTechniqueSet>*>(m_manager.LoadDependency(ASSET_TYPE_TECHNIQUE_SET, jMaterial.techniqueSet));
|
||||||
|
if (!techniqueSet)
|
||||||
|
{
|
||||||
|
PrintError(material, "Could not find technique set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(techniqueSet);
|
||||||
|
material.techniqueSet = techniqueSet->Asset();
|
||||||
|
|
||||||
|
if (!jMaterial.textures.empty())
|
||||||
|
{
|
||||||
|
material.textureCount = static_cast<unsigned char>(jMaterial.textures.size());
|
||||||
|
material.textureTable = static_cast<MaterialTextureDef*>(m_memory.Alloc(sizeof(MaterialTextureDef) * material.textureCount));
|
||||||
|
memset(material.textureTable, 0, sizeof(MaterialTextureDef) * material.textureCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.textureCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateTextureDefFromJson(jMaterial.textures[i], material.textureTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.textureCount = 0;
|
||||||
|
material.textureTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jMaterial.constants.empty())
|
||||||
|
{
|
||||||
|
material.constantCount = static_cast<unsigned char>(jMaterial.constants.size());
|
||||||
|
material.constantTable = static_cast<MaterialConstantDef*>(m_memory.Alloc(sizeof(MaterialConstantDef) * material.constantCount));
|
||||||
|
memset(material.constantTable, 0, sizeof(MaterialConstantDef) * material.constantCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.constantCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateConstantDefFromJson(jMaterial.constants[i], material.constantTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.constantCount = 0;
|
||||||
|
material.constantTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jMaterial.stateBits.empty())
|
||||||
|
{
|
||||||
|
material.stateBitsCount = static_cast<unsigned char>(jMaterial.stateBits.size());
|
||||||
|
material.stateBitsTable = static_cast<GfxStateBitsTable*>(m_memory.Alloc(sizeof(GfxStateBitsTable) * material.stateBitsCount));
|
||||||
|
memset(material.stateBitsTable, 0, sizeof(GfxStateBitsTable) * material.stateBitsCount);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < material.stateBitsCount; i++)
|
||||||
|
{
|
||||||
|
if (!CreateStateBitsTableEntryFromJson(jMaterial.stateBits[i], material.stateBitsTable[i], material))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.stateBitsCount = 0;
|
||||||
|
material.stateBitsTable = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jMaterial.thermalMaterial)
|
||||||
|
{
|
||||||
|
auto* thermalMaterial = static_cast<XAssetInfo<Material>*>(m_manager.LoadDependency(ASSET_TYPE_MATERIAL, jMaterial.thermalMaterial.value()));
|
||||||
|
if (!thermalMaterial)
|
||||||
|
{
|
||||||
|
PrintError(material, "Could not find thermal material");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dependencies.push_back(thermalMaterial);
|
||||||
|
material.thermalMaterial = thermalMaterial->Asset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.thermalMaterial = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& m_stream;
|
||||||
|
MemoryManager& m_memory;
|
||||||
|
IAssetLoadingManager& m_manager;
|
||||||
|
std::vector<XAssetInfoGeneric*>& m_dependencies;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool LoadMaterialAsJson(
|
||||||
|
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies)
|
||||||
|
{
|
||||||
|
const JsonLoader loader(stream, *memory, *manager, dependencies);
|
||||||
|
|
||||||
|
return loader.Load(material);
|
||||||
|
}
|
||||||
|
} // namespace T6
|
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AssetLoading/IAssetLoadingManager.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
bool LoadMaterialAsJson(
|
||||||
|
std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies);
|
||||||
|
} // namespace T6
|
@ -3,6 +3,7 @@
|
|||||||
#include "AssetLoaders/AssetLoaderFontIcon.h"
|
#include "AssetLoaders/AssetLoaderFontIcon.h"
|
||||||
#include "AssetLoaders/AssetLoaderGfxImage.h"
|
#include "AssetLoaders/AssetLoaderGfxImage.h"
|
||||||
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
||||||
|
#include "AssetLoaders/AssetLoaderMaterial.h"
|
||||||
#include "AssetLoaders/AssetLoaderPhysConstraints.h"
|
#include "AssetLoaders/AssetLoaderPhysConstraints.h"
|
||||||
#include "AssetLoaders/AssetLoaderPhysPreset.h"
|
#include "AssetLoaders/AssetLoaderPhysPreset.h"
|
||||||
#include "AssetLoaders/AssetLoaderQdb.h"
|
#include "AssetLoaders/AssetLoaderQdb.h"
|
||||||
@ -49,7 +50,8 @@ namespace T6
|
|||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XANIMPARTS, XAnimParts))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XMODEL, XModel))
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material))
|
// REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MATERIAL, Material))
|
||||||
|
REGISTER_ASSET_LOADER(AssetLoaderMaterial)
|
||||||
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet))
|
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet))
|
||||||
REGISTER_ASSET_LOADER(AssetLoaderGfxImage)
|
REGISTER_ASSET_LOADER(AssetLoaderGfxImage)
|
||||||
REGISTER_ASSET_LOADER(AssetLoaderSoundBank)
|
REGISTER_ASSET_LOADER(AssetLoaderSoundBank)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user