diff --git a/src/ObjCommon/Game/T6/Json/JsonMaterial.h b/src/ObjCommon/Game/T6/Json/JsonMaterial.h index 83762f74..e210676d 100644 --- a/src/ObjCommon/Game/T6/Json/JsonMaterial.h +++ b/src/ObjCommon/Game/T6/Json/JsonMaterial.h @@ -2,7 +2,7 @@ #include "Game/T6/T6.h" -#include "Json/JsonOptional.h" +#include "Json/JsonExtension.h" #include #include #include @@ -44,7 +44,7 @@ namespace T6 GfxStencilFunc func; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStencil, pass, fail, zfail, func); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonStencil, pass, fail, zfail, func); enum class JsonAlphaTest { @@ -154,24 +154,24 @@ namespace T6 std::optional stencilBack; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStateBitsTableEntry, - srcBlendRgb, - dstBlendRgb, - blendOpRgb, - alphaTest, - cullFace, - srcBlendAlpha, - dstBlendAlpha, - blendOpAlpha, - colorWriteRgb, - colorWriteAlpha, - polymodeLine, - depthWrite, - depthWrite, - depthTest, - polygonOffset, - stencilFront, - stencilBack); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonStateBitsTableEntry, + srcBlendRgb, + dstBlendRgb, + blendOpRgb, + alphaTest, + cullFace, + srcBlendAlpha, + dstBlendAlpha, + blendOpAlpha, + colorWriteRgb, + colorWriteAlpha, + polymodeLine, + depthWrite, + depthWrite, + depthTest, + polygonOffset, + stencilFront, + stencilBack); class JsonConstant { @@ -186,12 +186,12 @@ namespace T6 { if (in.name.has_value()) { - out["name"] = in.name; + optional_to_json(out, "name", in.name); } else { - out["nameFragment"] = in.nameFragment; - out["nameHash"] = in.nameHash; + optional_to_json(out, "nameFragment", in.nameFragment); + optional_to_json(out, "nameHash", in.nameHash); } out["literal"] = in.literal; @@ -199,9 +199,9 @@ namespace T6 inline void from_json(const nlohmann::json& in, JsonConstant& out) { - in.value("name", nlohmann::json()).get_to(out.name); - in.value("nameFragment", nlohmann::json()).get_to(out.nameFragment); - in.value("nameHash", nlohmann::json()).get_to(out.nameHash); + optional_from_json(in, "name", out.name); + optional_from_json(in, "nameFragment", out.nameFragment); + optional_from_json(in, "nameHash", out.nameHash); in.at("literal").get_to(out.literal); }; @@ -232,7 +232,7 @@ namespace T6 bool clampW; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonSamplerState, filter, mipMap, clampU, clampV, clampW); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonSamplerState, filter, mipMap, clampU, clampV, clampW); NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic, { @@ -284,13 +284,13 @@ namespace T6 { if (in.name.has_value()) { - out["name"] = in.name; + optional_to_json(out, "name", in.name); } else { - out["nameHash"] = in.nameHash; - out["nameStart"] = in.nameStart; - out["nameEnd"] = in.nameEnd; + optional_to_json(out, "nameHash", in.nameHash); + optional_to_json(out, "nameStart", in.nameStart); + optional_to_json(out, "nameEnd", in.nameEnd); } out["semantic"] = in.semantic; @@ -301,10 +301,10 @@ namespace T6 inline void from_json(const nlohmann::json& in, JsonTexture& out) { - in.value("name", nlohmann::json()).get_to(out.name); - in.value("nameHash", nlohmann::json()).get_to(out.nameHash); - in.value("nameStart", nlohmann::json()).get_to(out.nameStart); - in.value("nameEnd", nlohmann::json()).get_to(out.nameEnd); + optional_from_json(in, "name", out.name); + optional_from_json(in, "nameHash", out.nameHash); + optional_from_json(in, "nameStart", out.nameStart); + optional_from_json(in, "nameEnd", out.nameEnd); in.at("semantic").get_to(out.semantic); in.at("isMatureContent").get_to(out.isMatureContent); in.at("samplerState").get_to(out.samplerState); @@ -318,7 +318,7 @@ namespace T6 uint8_t columns; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonTextureAtlas, rows, columns); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonTextureAtlas, rows, columns); NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags, { @@ -376,22 +376,22 @@ namespace T6 std::optional thermalMaterial; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonMaterial, - gameFlags, - sortKey, - textureAtlas, - surfaceTypeBits, - layeredSurfaceTypes, - hashIndex, - surfaceFlags, - contents, - stateBitsEntry, - stateFlags, - cameraRegion, - probeMipBits, - techniqueSet, - textures, - constants, - stateBits, - thermalMaterial); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterial, + gameFlags, + sortKey, + textureAtlas, + surfaceTypeBits, + layeredSurfaceTypes, + hashIndex, + surfaceFlags, + contents, + stateBitsEntry, + stateFlags, + cameraRegion, + probeMipBits, + techniqueSet, + textures, + constants, + stateBits, + thermalMaterial); } // namespace T6 diff --git a/src/ObjCommon/Game/T6/Json/JsonWeaponCamo.h b/src/ObjCommon/Game/T6/Json/JsonWeaponCamo.h index eb9f72af..6b76cc2f 100644 --- a/src/ObjCommon/Game/T6/Json/JsonWeaponCamo.h +++ b/src/ObjCommon/Game/T6/Json/JsonWeaponCamo.h @@ -3,7 +3,7 @@ #include "Game/T6/T6.h" #include "Json/JsonCommon.h" -#include "Json/JsonOptional.h" +#include "Json/JsonExtension.h" #include #include #include @@ -21,7 +21,7 @@ namespace T6 float patternScale; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoSet, solidCamoImage, patternCamoImage, patternOffset, patternScale); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoSet, solidCamoImage, patternCamoImage, patternOffset, patternScale); class JsonWeaponCamoMaterialOverride { @@ -30,7 +30,7 @@ namespace T6 std::string camoMaterial; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterialOverride, baseMaterial, camoMaterial); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterialOverride, baseMaterial, camoMaterial); constexpr auto SHADER_CONST_COUNT = 8; @@ -46,7 +46,7 @@ namespace T6 static_assert(SHADER_CONST_COUNT == std::extent_v); - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterial, useColorMap, useNormalMap, useSpecularMap, materialOverrides, shaderConsts); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterial, useColorMap, useNormalMap, useSpecularMap, materialOverrides, shaderConsts); class JsonWeaponCamoMaterialSet { @@ -54,7 +54,7 @@ namespace T6 std::vector materials; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterialSet, materials); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterialSet, materials); class JsonWeaponCamo { @@ -65,5 +65,5 @@ namespace T6 std::vector camoMaterials; }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamo, solidBaseImage, patternBaseImage, camoSets, camoMaterials); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamo, solidBaseImage, patternBaseImage, camoSets, camoMaterials); } // namespace T6 diff --git a/src/ObjCommon/Json/JsonCommon.h b/src/ObjCommon/Json/JsonCommon.h index 57df18d1..f1a9291e 100644 --- a/src/ObjCommon/Json/JsonCommon.h +++ b/src/ObjCommon/Json/JsonCommon.h @@ -1,5 +1,6 @@ #pragma once +#include "Json/JsonExtension.h" #include class JsonVec2 @@ -9,7 +10,7 @@ public: float y; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec2, x, y); +NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec2, x, y); class JsonVec3 { @@ -19,7 +20,7 @@ public: float z; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec3, x, y, z); +NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec3, x, y, z); class JsonVec4 { @@ -30,4 +31,4 @@ public: float w; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec4, x, y, z, w); +NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec4, x, y, z, w); diff --git a/src/ObjCommon/Json/JsonExtension.h b/src/ObjCommon/Json/JsonExtension.h new file mode 100644 index 00000000..3b84b35a --- /dev/null +++ b/src/ObjCommon/Json/JsonExtension.h @@ -0,0 +1,58 @@ +#pragma once + +// Credits to +// https://www.kdab.com/jsonify-with-nlohmann-json/ + +#include +#include + +// partial specialization (full specialization works too) +namespace nlohmann +{ + template void optional_to_json(nlohmann::json& j, const char* name, const std::optional& value) + { + if (value) + j[name] = *value; + } + + template void optional_from_json(const nlohmann::json& j, const char* name, std::optional& value) + { + const auto it = j.find(name); + if (it != j.end()) + value = it->get(); + else + value = std::nullopt; + } + + template constexpr bool is_optional = false; + template constexpr bool is_optional> = true; + + template void extended_to_json(const char* key, nlohmann::json& j, const T& value) + { + if constexpr (is_optional) + nlohmann::optional_to_json(j, key, value); + else + j[key] = value; + } + + template void extended_from_json(const char* key, const nlohmann::json& j, T& value) + { + if constexpr (is_optional) + nlohmann::optional_from_json(j, key, value); + else + j.at(key).get_to(value); + } +} // namespace nlohmann + +#define EXTEND_JSON_TO(v1) extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1); +#define EXTEND_JSON_FROM(v1) extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1); + +#define NLOHMANN_DEFINE_TYPE_EXTENSION(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \ + { \ + NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, __VA_ARGS__)) \ + } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) \ + { \ + NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, __VA_ARGS__)) \ + } diff --git a/src/ObjCommon/Json/JsonOptional.h b/src/ObjCommon/Json/JsonOptional.h deleted file mode 100644 index df1cef8a..00000000 --- a/src/ObjCommon/Json/JsonOptional.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include - -// partial specialization (full specialization works too) -namespace nlohmann -{ - template struct adl_serializer> - { - static void to_json(json& j, const std::optional& opt) - { - if (!opt.has_value()) - { - j = nullptr; - } - else - { - j = *opt; // this will call adl_serializer::to_json which will - // find the free function to_json in T's namespace! - } - } - - static void from_json(const json& j, std::optional& opt) - { - if (j.is_null()) - { - opt = std::nullopt; - } - else - { - opt = j.template get(); // same as above, but with - // adl_serializer::from_json - } - } - }; -} // namespace nlohmann