mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-07-01 00:57:56 -05:00
refactor: use templating for JsonMaterialLoader
This commit is contained in:
@ -52,6 +52,7 @@ function ObjLoading:project()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjCommon:use()
|
||||||
useSourceTemplating("ObjLoading")
|
useSourceTemplating("ObjLoading")
|
||||||
|
|
||||||
self:include(includes)
|
self:include(includes)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "LoaderMaterialIW5.h"
|
#include "LoaderMaterialIW5.h"
|
||||||
|
|
||||||
#include "Game/IW5/IW5.h"
|
#include "Game/IW5/IW5.h"
|
||||||
#include "JsonMaterialLoader.h"
|
#include "Game/IW5/Material/JsonMaterialLoaderIW5.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -1,382 +0,0 @@
|
|||||||
#include "JsonMaterialLoader.h"
|
|
||||||
|
|
||||||
#include "Game/T6/CommonT6.h"
|
|
||||||
#include "Game/T6/Json/JsonMaterial.h"
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using namespace nlohmann;
|
|
||||||
using namespace T6;
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class JsonLoader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
|
|
||||||
: m_stream(stream),
|
|
||||||
m_memory(memory),
|
|
||||||
m_context(context),
|
|
||||||
m_registration(registration)
|
|
||||||
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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 << std::format("Tried to load material \"{}\" but did not find expected type material of version 1\n", material.info.name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const auto jMaterial = jRoot.get<JsonMaterial>();
|
|
||||||
return CreateMaterialFromJson(jMaterial, material);
|
|
||||||
}
|
|
||||||
catch (const json::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << std::format("Failed to parse json of material: {}\n", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void PrintError(const Material& material, const std::string& message)
|
|
||||||
{
|
|
||||||
std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = m_context.LoadDependency<AssetImage>(jTexture.image);
|
|
||||||
if (!image)
|
|
||||||
{
|
|
||||||
PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_registration.AddDependency(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 = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
|
|
||||||
if (!techniqueSet)
|
|
||||||
{
|
|
||||||
PrintError(material, "Could not find technique set");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_registration.AddDependency(techniqueSet);
|
|
||||||
material.techniqueSet = techniqueSet->Asset();
|
|
||||||
|
|
||||||
if (!jMaterial.textures.empty())
|
|
||||||
{
|
|
||||||
material.textureCount = static_cast<unsigned char>(jMaterial.textures.size());
|
|
||||||
material.textureTable = m_memory.Alloc<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 = m_memory.Alloc<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 = m_memory.Alloc<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 = m_context.LoadDependency<AssetMaterial>(jMaterial.thermalMaterial.value());
|
|
||||||
if (!thermalMaterial)
|
|
||||||
{
|
|
||||||
PrintError(material, "Could not find thermal material");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_registration.AddDependency(thermalMaterial);
|
|
||||||
material.thermalMaterial = thermalMaterial->Asset();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
material.thermalMaterial = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream& m_stream;
|
|
||||||
MemoryManager& m_memory;
|
|
||||||
AssetCreationContext& m_context;
|
|
||||||
AssetRegistration<AssetMaterial>& m_registration;
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
bool LoadMaterialAsJson(
|
|
||||||
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
|
|
||||||
{
|
|
||||||
const JsonLoader loader(stream, memory, context, registration);
|
|
||||||
|
|
||||||
return loader.Load(material);
|
|
||||||
}
|
|
||||||
} // namespace T6
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Asset/AssetCreationContext.h"
|
|
||||||
#include "Asset/AssetRegistration.h"
|
|
||||||
#include "Game/T6/T6.h"
|
|
||||||
#include "Utils/MemoryManager.h"
|
|
||||||
|
|
||||||
#include <istream>
|
|
||||||
|
|
||||||
namespace T6
|
|
||||||
{
|
|
||||||
bool LoadMaterialAsJson(
|
|
||||||
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration);
|
|
||||||
} // namespace T6
|
|
@ -1,6 +1,6 @@
|
|||||||
#include "LoaderMaterialT6.h"
|
#include "LoaderMaterialT6.h"
|
||||||
|
|
||||||
#include "Game/T6/Material/JsonMaterialLoader.h"
|
#include "Game/T6/Material/JsonMaterialLoaderT6.h"
|
||||||
#include "Game/T6/T6.h"
|
#include "Game/T6/T6.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -1,15 +1,37 @@
|
|||||||
#include "JsonMaterialLoader.h"
|
#options GAME (IW5, T6)
|
||||||
|
|
||||||
|
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".cpp"
|
||||||
|
|
||||||
|
#if GAME == "IW5"
|
||||||
|
#define FEATURE_IW5
|
||||||
|
#define HAS_WATER
|
||||||
|
#define GAME_LOWER "iw5"
|
||||||
|
#elif GAME == "T6"
|
||||||
|
#define FEATURE_T6
|
||||||
|
#define GAME_LOWER "t6"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This file was templated.
|
||||||
|
// See JsonMaterialLoader.cpp.template.
|
||||||
|
// Do not modify, changes will be lost.
|
||||||
|
|
||||||
|
#set LOADER_HEADER "\"JsonMaterialLoader" + GAME + ".h\""
|
||||||
|
#include LOADER_HEADER
|
||||||
|
|
||||||
|
#ifdef HAS_WATER
|
||||||
#include "Base64.h"
|
#include "Base64.h"
|
||||||
#include "Game/IW5/CommonIW5.h"
|
#endif
|
||||||
#include "Game/IW5/Material/JsonMaterial.h"
|
#set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\""
|
||||||
|
#include COMMON_HEADER
|
||||||
|
#set JSON_HEADER "\"Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h\""
|
||||||
|
#include JSON_HEADER
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
using namespace IW5;
|
using namespace GAME;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -27,20 +49,28 @@ namespace
|
|||||||
bool Load(Material& material) const
|
bool Load(Material& material) const
|
||||||
{
|
{
|
||||||
const auto jRoot = json::parse(m_stream);
|
const auto jRoot = json::parse(m_stream);
|
||||||
std::string game;
|
|
||||||
std::string type;
|
std::string type;
|
||||||
unsigned version;
|
unsigned version;
|
||||||
|
|
||||||
jRoot.at("_type").get_to(type);
|
jRoot.at("_type").get_to(type);
|
||||||
jRoot.at("_game").get_to(game);
|
|
||||||
jRoot.at("_version").get_to(version);
|
jRoot.at("_version").get_to(version);
|
||||||
|
|
||||||
if (type != "material" || version != 1u || game != "iw5")
|
if (type != "material" || version != 1u)
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Tried to load material \"{}\" but did not find expected type material of version 1\n", material.info.name);
|
std::cerr << std::format("Tried to load material \"{}\" but did not find expected type material of version 1\n", material.info.name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef FEATURE_T6 // T6 did not have this check in version 1, so to stay backwards compatible, let it stay that way
|
||||||
|
std::string game;
|
||||||
|
jRoot.at("_game").get_to(game);
|
||||||
|
if (game != GAME_LOWER)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Tried to load material \"{}\" but \"_game\" did not find expected type value {}\n", material.info.name, GAME_LOWER);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto jMaterial = jRoot.get<JsonMaterial>();
|
const auto jMaterial = jRoot.get<JsonMaterial>();
|
||||||
@ -60,7 +90,11 @@ namespace
|
|||||||
std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message);
|
std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEATURE_IW5
|
||||||
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned char& gameFlags)
|
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned char& gameFlags)
|
||||||
|
#elif defined(FEATURE_T6)
|
||||||
|
static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
for (const auto gameFlag : jMaterial.gameFlags)
|
for (const auto gameFlag : jMaterial.gameFlags)
|
||||||
gameFlags |= gameFlag;
|
gameFlags |= gameFlag;
|
||||||
@ -77,6 +111,7 @@ namespace
|
|||||||
samplerState.clampW = jSamplerState.clampW;
|
samplerState.clampW = jSamplerState.clampW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_WATER
|
||||||
bool CreateWaterFromJson(const JsonWater& jWater, water_t& water, const Material& material) const
|
bool CreateWaterFromJson(const JsonWater& jWater, water_t& water, const Material& material) const
|
||||||
{
|
{
|
||||||
water.writable.floatTime = jWater.floatTime;
|
water.writable.floatTime = jWater.floatTime;
|
||||||
@ -120,6 +155,7 @@ namespace
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool CreateTextureDefFromJson(const JsonTexture& jTexture, MaterialTextureDef& textureDef, const Material& material) const
|
bool CreateTextureDefFromJson(const JsonTexture& jTexture, MaterialTextureDef& textureDef, const Material& material) const
|
||||||
{
|
{
|
||||||
@ -157,6 +193,9 @@ namespace
|
|||||||
CreateSamplerStateFromJson(jTexture.samplerState, textureDef.samplerState);
|
CreateSamplerStateFromJson(jTexture.samplerState, textureDef.samplerState);
|
||||||
|
|
||||||
textureDef.semantic = jTexture.semantic;
|
textureDef.semantic = jTexture.semantic;
|
||||||
|
#ifdef FEATURE_T6
|
||||||
|
textureDef.isMatureContent = jTexture.isMatureContent;
|
||||||
|
#endif
|
||||||
|
|
||||||
auto* imageAsset = m_context.LoadDependency<AssetImage>(jTexture.image);
|
auto* imageAsset = m_context.LoadDependency<AssetImage>(jTexture.image);
|
||||||
if (!imageAsset)
|
if (!imageAsset)
|
||||||
@ -166,6 +205,7 @@ namespace
|
|||||||
}
|
}
|
||||||
m_registration.AddDependency(imageAsset);
|
m_registration.AddDependency(imageAsset);
|
||||||
|
|
||||||
|
#ifdef HAS_WATER
|
||||||
if (jTexture.water)
|
if (jTexture.water)
|
||||||
{
|
{
|
||||||
if (jTexture.semantic != TS_WATER_MAP)
|
if (jTexture.semantic != TS_WATER_MAP)
|
||||||
@ -195,6 +235,9 @@ namespace
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
textureDef.u.image = imageAsset->Asset();
|
textureDef.u.image = imageAsset->Asset();
|
||||||
|
#else
|
||||||
|
textureDef.image = imageAsset->Asset();
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -257,11 +300,13 @@ namespace
|
|||||||
structured.alphaTestDisabled = 0;
|
structured.alphaTestDisabled = 0;
|
||||||
structured.alphaTest = GFXS_ALPHA_TEST_GT_0;
|
structured.alphaTest = GFXS_ALPHA_TEST_GT_0;
|
||||||
}
|
}
|
||||||
|
#ifdef FEATURE_IW5
|
||||||
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::LT128)
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::LT128)
|
||||||
{
|
{
|
||||||
structured.alphaTestDisabled = 0;
|
structured.alphaTestDisabled = 0;
|
||||||
structured.alphaTest = GFXS_ALPHA_TEST_LT_128;
|
structured.alphaTest = GFXS_ALPHA_TEST_LT_128;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128)
|
else if (jStateBitsTableEntry.alphaTest == JsonAlphaTest::GE128)
|
||||||
{
|
{
|
||||||
structured.alphaTestDisabled = 0;
|
structured.alphaTestDisabled = 0;
|
||||||
@ -290,7 +335,9 @@ namespace
|
|||||||
structured.blendOpAlpha = jStateBitsTableEntry.blendOpAlpha;
|
structured.blendOpAlpha = jStateBitsTableEntry.blendOpAlpha;
|
||||||
structured.colorWriteRgb = jStateBitsTableEntry.colorWriteRgb;
|
structured.colorWriteRgb = jStateBitsTableEntry.colorWriteRgb;
|
||||||
structured.colorWriteAlpha = jStateBitsTableEntry.colorWriteAlpha;
|
structured.colorWriteAlpha = jStateBitsTableEntry.colorWriteAlpha;
|
||||||
|
#ifdef FEATURE_IW5
|
||||||
structured.gammaWrite = jStateBitsTableEntry.gammaWrite;
|
structured.gammaWrite = jStateBitsTableEntry.gammaWrite;
|
||||||
|
#endif
|
||||||
structured.polymodeLine = jStateBitsTableEntry.polymodeLine;
|
structured.polymodeLine = jStateBitsTableEntry.polymodeLine;
|
||||||
structured.depthWrite = jStateBitsTableEntry.depthWrite;
|
structured.depthWrite = jStateBitsTableEntry.depthWrite;
|
||||||
|
|
||||||
@ -352,6 +399,12 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
material.info.surfaceTypeBits = jMaterial.surfaceTypeBits;
|
material.info.surfaceTypeBits = jMaterial.surfaceTypeBits;
|
||||||
|
#ifdef FEATURE_T6
|
||||||
|
material.info.layeredSurfaceTypes = jMaterial.layeredSurfaceTypes;
|
||||||
|
material.info.hashIndex = static_cast<uint16_t>(jMaterial.hashIndex);
|
||||||
|
material.info.surfaceFlags = jMaterial.surfaceFlags;
|
||||||
|
material.info.contents = jMaterial.contents;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (jMaterial.stateBitsEntry.size() != std::extent_v<decltype(Material::stateBitsEntry)>)
|
if (jMaterial.stateBitsEntry.size() != std::extent_v<decltype(Material::stateBitsEntry)>)
|
||||||
{
|
{
|
||||||
@ -363,6 +416,9 @@ namespace
|
|||||||
|
|
||||||
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
|
material.stateFlags = static_cast<unsigned char>(jMaterial.stateFlags);
|
||||||
material.cameraRegion = jMaterial.cameraRegion;
|
material.cameraRegion = jMaterial.cameraRegion;
|
||||||
|
#ifdef FEATURE_T6
|
||||||
|
material.probeMipBits = jMaterial.probeMipBits;
|
||||||
|
#endif
|
||||||
|
|
||||||
auto* techniqueSet = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
|
auto* techniqueSet = m_context.LoadDependency<AssetTechniqueSet>(jMaterial.techniqueSet);
|
||||||
if (!techniqueSet)
|
if (!techniqueSet)
|
||||||
@ -424,6 +480,24 @@ namespace
|
|||||||
material.stateBitsTable = nullptr;
|
material.stateBitsTable = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEATURE_T6
|
||||||
|
if (jMaterial.thermalMaterial)
|
||||||
|
{
|
||||||
|
auto* thermalMaterial = m_context.LoadDependency<AssetMaterial>(jMaterial.thermalMaterial.value());
|
||||||
|
if (!thermalMaterial)
|
||||||
|
{
|
||||||
|
PrintError(material, "Could not find thermal material");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_registration.AddDependency(thermalMaterial);
|
||||||
|
material.thermalMaterial = thermalMaterial->Asset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material.thermalMaterial = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +508,7 @@ namespace
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace IW5
|
namespace GAME
|
||||||
{
|
{
|
||||||
bool LoadMaterialAsJson(
|
bool LoadMaterialAsJson(
|
||||||
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
|
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration)
|
||||||
@ -443,4 +517,4 @@ namespace IW5
|
|||||||
|
|
||||||
return loader.Load(material);
|
return loader.Load(material);
|
||||||
}
|
}
|
||||||
} // namespace IW5
|
} // namespace GAME
|
@ -1,14 +1,23 @@
|
|||||||
|
#options GAME (IW5, T6)
|
||||||
|
|
||||||
|
#filename "Game/" + GAME + "/Material/JsonMaterialLoader" + GAME + ".h"
|
||||||
|
|
||||||
|
// This file was templated.
|
||||||
|
// See JsonMaterialLoader.h.template.
|
||||||
|
// Do not modify, changes will be lost.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Asset/AssetCreationContext.h"
|
#include "Asset/AssetCreationContext.h"
|
||||||
#include "Asset/AssetRegistration.h"
|
#include "Asset/AssetRegistration.h"
|
||||||
#include "Game/IW5/IW5.h"
|
#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\""
|
||||||
|
#include GAME_HEADER
|
||||||
#include "Utils/MemoryManager.h"
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
|
|
||||||
namespace IW5
|
namespace GAME
|
||||||
{
|
{
|
||||||
bool LoadMaterialAsJson(
|
bool LoadMaterialAsJson(
|
||||||
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration);
|
std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration<AssetMaterial>& registration);
|
||||||
} // namespace IW5
|
} // namespace GAME
|
@ -12,7 +12,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This file was templated.
|
// This file was templated.
|
||||||
// See JsonMaterialWriter.h.template.
|
// See JsonMaterialWriter.cpp.template.
|
||||||
// Do not modify, changes will be lost.
|
// Do not modify, changes will be lost.
|
||||||
|
|
||||||
#set WRITER_HEADER "\"JsonMaterialWriter" + GAME + ".h\""
|
#set WRITER_HEADER "\"JsonMaterialWriter" + GAME + ".h\""
|
||||||
|
Reference in New Issue
Block a user