mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-06 06:09:52 +03:00
Added automated reflection based json serialization for reflected components
This commit is contained in:
@@ -90,9 +90,95 @@ namespace Nuake
|
|||||||
std::string value = fieldVal.cast<std::string>();
|
std::string value = fieldVal.cast<std::string>();
|
||||||
cursor[displayName] = value;
|
cursor[displayName] = value;
|
||||||
}
|
}
|
||||||
|
else if (auto prop = dataType.prop(HashedFieldPropName::IsEnum); prop)
|
||||||
|
{
|
||||||
|
auto enumMeta = dataType.type();
|
||||||
|
// Fallback to integer value if name not available
|
||||||
|
cursor[displayName] = static_cast<int>(fieldVal.cast<int>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonSnippet;
|
return jsonSnippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<IsComponentT T>
|
||||||
|
void Deserialize(const json& jsonSnippet, T& component)
|
||||||
|
{
|
||||||
|
const entt::meta_type meta = entt::resolve<T>();
|
||||||
|
if (!meta) return;
|
||||||
|
|
||||||
|
entt::meta_any metaAny = meta.from_void(static_cast<void*>(&component));
|
||||||
|
if (!metaAny) return;
|
||||||
|
|
||||||
|
const std::string componentName = Component::GetName(meta);
|
||||||
|
if (!jsonSnippet.contains(componentName)) return;
|
||||||
|
|
||||||
|
const json& cursor = jsonSnippet.at(componentName);
|
||||||
|
|
||||||
|
for (auto [fst, dataMember] : meta.data())
|
||||||
|
{
|
||||||
|
auto propName = dataMember.prop(HashedName::DisplayName);
|
||||||
|
if (!propName) continue;
|
||||||
|
|
||||||
|
const char* displayNameC = *propName.value().try_cast<const char*>();
|
||||||
|
std::string displayName = displayNameC;
|
||||||
|
|
||||||
|
if (!cursor.contains(displayName)) continue;
|
||||||
|
|
||||||
|
const entt::meta_type fieldType = dataMember.type();
|
||||||
|
|
||||||
|
if (fieldType == entt::resolve<float>())
|
||||||
|
{
|
||||||
|
dataMember.set(metaAny, cursor.at(displayName).get<float>());
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<int32_t>())
|
||||||
|
{
|
||||||
|
dataMember.set(metaAny, cursor.at(displayName).get<int32_t>());
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<bool>())
|
||||||
|
{
|
||||||
|
dataMember.set(metaAny, cursor.at(displayName).get<bool>());
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<Vector2>())
|
||||||
|
{
|
||||||
|
Vector2 vec;
|
||||||
|
vec.x = cursor.at(displayName).at("x").get<float>();
|
||||||
|
vec.y = cursor.at(displayName).at("y").get<float>();
|
||||||
|
dataMember.set(metaAny, vec);
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<Vector3>())
|
||||||
|
{
|
||||||
|
Vector3 vec;
|
||||||
|
vec.x = cursor.at(displayName).at("x").get<float>();
|
||||||
|
vec.y = cursor.at(displayName).at("y").get<float>();
|
||||||
|
vec.z = cursor.at(displayName).at("z").get<float>();
|
||||||
|
dataMember.set(metaAny, vec);
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<Vector4>())
|
||||||
|
{
|
||||||
|
Vector4 vec;
|
||||||
|
vec.x = cursor.at(displayName).at("x").get<float>();
|
||||||
|
vec.y = cursor.at(displayName).at("y").get<float>();
|
||||||
|
vec.z = cursor.at(displayName).at("z").get<float>();
|
||||||
|
vec.w = cursor.at(displayName).at("w").get<float>();
|
||||||
|
dataMember.set(metaAny, vec);
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<ResourceFile>())
|
||||||
|
{
|
||||||
|
std::string fileKey = "file" + displayName;
|
||||||
|
if (cursor.contains(fileKey))
|
||||||
|
{
|
||||||
|
//std::string relativePath = cursor.at(fileKey).get<std::string>();
|
||||||
|
//ResourceFile resource;
|
||||||
|
//resource.file = std::make_shared<File>(relativePath);
|
||||||
|
//dataMember.set(metaAny, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fieldType == entt::resolve<std::string>())
|
||||||
|
{
|
||||||
|
dataMember.set(metaAny, cursor.at(displayName).get<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,14 @@ namespace Serialization
|
|||||||
{
|
{
|
||||||
using namespace Nuake;
|
using namespace Nuake;
|
||||||
|
|
||||||
|
enum class TestEnum : int32_t
|
||||||
|
{
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four
|
||||||
|
};
|
||||||
|
|
||||||
class TestData : public Component
|
class TestData : public Component
|
||||||
{
|
{
|
||||||
NUAKECOMPONENT(TestData, "TestData");
|
NUAKECOMPONENT(TestData, "TestData");
|
||||||
@@ -19,6 +27,7 @@ namespace Serialization
|
|||||||
Vector2 myVec2;
|
Vector2 myVec2;
|
||||||
Vector3 myVec3;
|
Vector3 myVec3;
|
||||||
Vector4 myVec4;
|
Vector4 myVec4;
|
||||||
|
TestEnum myEnum;
|
||||||
|
|
||||||
static void InitializeComponentClass()
|
static void InitializeComponentClass()
|
||||||
{
|
{
|
||||||
@@ -28,6 +37,7 @@ namespace Serialization
|
|||||||
BindComponentField<&TestData::myVec2>("myVec2", "myVec2");
|
BindComponentField<&TestData::myVec2>("myVec2", "myVec2");
|
||||||
BindComponentField<&TestData::myVec3>("myVec3", "myVec3");
|
BindComponentField<&TestData::myVec3>("myVec3", "myVec3");
|
||||||
BindComponentField<&TestData::myVec4>("myVec4", "myVec4");
|
BindComponentField<&TestData::myVec4>("myVec4", "myVec4");
|
||||||
|
BindComponentField<&TestData::myEnum>("myEnum", "myEnum");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +52,8 @@ namespace Serialization
|
|||||||
.myString = "Hello World",
|
.myString = "Hello World",
|
||||||
.myVec2 = Vector2(1, 2),
|
.myVec2 = Vector2(1, 2),
|
||||||
.myVec3 = Vector3(3, 4, 5),
|
.myVec3 = Vector3(3, 4, 5),
|
||||||
.myVec4 = Vector4(6, 7, 8, 9)
|
.myVec4 = Vector4(6, 7, 8, 9),
|
||||||
|
.myEnum = TestEnum::Two
|
||||||
};
|
};
|
||||||
|
|
||||||
// Serialize into json
|
// Serialize into json
|
||||||
@@ -76,4 +87,35 @@ namespace Serialization
|
|||||||
REQUIRE(result["TestData"]["myVec4"]["z"] == testData.myVec4.z);
|
REQUIRE(result["TestData"]["myVec4"]["z"] == testData.myVec4.z);
|
||||||
REQUIRE(result["TestData"]["myVec4"]["w"] == testData.myVec4.w);
|
REQUIRE(result["TestData"]["myVec4"]["w"] == testData.myVec4.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Deserialize Struct", "[Serialization]")
|
||||||
|
{
|
||||||
|
// Initialize component
|
||||||
|
TestData::InternalInitializeClass();
|
||||||
|
TestData testData =
|
||||||
|
{
|
||||||
|
.myInt = 1337,
|
||||||
|
.myBool = true,
|
||||||
|
.myString = "Hello World",
|
||||||
|
.myVec2 = Vector2(1, 2),
|
||||||
|
.myVec3 = Vector3(3, 4, 5),
|
||||||
|
.myVec4 = Vector4(6, 7, 8, 9)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Serialize into json
|
||||||
|
ComponentSerializer serializer;
|
||||||
|
json result = serializer.Serialize(testData);
|
||||||
|
|
||||||
|
// Deserialize
|
||||||
|
TestData inTestData = TestData{ };
|
||||||
|
serializer.Deserialize(result, inTestData);
|
||||||
|
|
||||||
|
// Test JSON result
|
||||||
|
REQUIRE(inTestData.myInt == testData.myInt);
|
||||||
|
REQUIRE(inTestData.myBool == testData.myBool);
|
||||||
|
REQUIRE(inTestData.myString == testData.myString);
|
||||||
|
REQUIRE(inTestData.myVec2 == testData.myVec2);
|
||||||
|
REQUIRE(inTestData.myVec3 == testData.myVec3);
|
||||||
|
REQUIRE(inTestData.myVec4 == testData.myVec4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user