From 5149e34723878d746b5f64bfddc39a4d480deddd Mon Sep 17 00:00:00 2001 From: maelstrom Date: Mon, 2 Jun 2025 18:39:39 +0200 Subject: [PATCH] refactor(datatypes): more refactoring to allow for enums --- autogen/src/data/codegen.cpp | 4 ++-- core/src/datatypes/base.h | 23 +++++-------------- core/src/datatypes/cframe.cpp | 2 +- core/src/datatypes/cframe.h | 2 +- core/src/datatypes/color3.cpp | 2 +- core/src/datatypes/color3.h | 2 +- core/src/datatypes/enum.cpp | 36 ++++++++++++++++++++++++++---- core/src/datatypes/enum.h | 25 ++++++++++++++++----- core/src/datatypes/ref.cpp | 2 +- core/src/datatypes/ref.h | 2 +- core/src/datatypes/variant.cpp | 29 +++++++++++++++++++----- core/src/datatypes/variant.h | 15 ++++++++++++- core/src/datatypes/vector.cpp | 2 +- core/src/datatypes/vector.h | 2 +- core/src/objects/base/instance.cpp | 10 ++++----- core/src/objects/datamodel.cpp | 2 +- editor/panes/propertiesview.cpp | 16 +++++-------- 17 files changed, 116 insertions(+), 60 deletions(-) diff --git a/autogen/src/data/codegen.cpp b/autogen/src/data/codegen.cpp index 427bbaa..ec5f9c4 100644 --- a/autogen/src/data/codegen.cpp +++ b/autogen/src/data/codegen.cpp @@ -418,10 +418,10 @@ void data::writeCodeForClass(std::ofstream& out, std::string headerPath, ClassAn out << "#include \"datatypes/variant.h\"\n"; out << "#include \n"; out << "#include \"lua.h\"\n\n"; - out << "const TypeInfo " << state.name << "::TYPE = {\n" + out << "const TypeDescriptor " << state.name << "::TYPE = {\n" << " .name = \"" << state.serializedName << "\",\n" << " .serializer = toVariantFunction(&" << state.name << "::Serialize)," - << " .deserializer = &" << state.name << "::Deserialize,\n" + << " .deserializer = toVariantGenerator(&" << state.name << "::Deserialize),\n" << " .toString = toVariantFunction(&" << state.name << "::ToString),"; if (state.hasFromString) out << " .fromString = &" << state.name << "::FromString,\n"; out << " .pushLuaValue = toVariantFunction(&" << state.name << "::PushLuaValue)," diff --git a/core/src/datatypes/base.h b/core/src/datatypes/base.h index 66fa13d..e40a474 100644 --- a/core/src/datatypes/base.h +++ b/core/src/datatypes/base.h @@ -3,7 +3,6 @@ #include #include #include -#include "datatypes/enum.h" #include "error/result.h" #include "error/data.h" @@ -29,22 +28,12 @@ struct TypeDescriptor { FromLuaValue fromLuaValue; }; -enum DataType { - // This distinction is not currently useful, so to - // minimize complexity, there will only be two categories - // (for now) - //DATA_PRIMITIVE, - //DATA_COMPOUND, - DATA_VALUE, - DATA_ENUM, -}; +class Enum; struct TypeInfo { - DataType type; - union { - const TypeDescriptor* descriptor; - _EnumData* enumData; - }; - - inline TypeInfo(const TypeDescriptor* descriptor) : type(DATA_VALUE), descriptor(descriptor) {} + const TypeDescriptor* descriptor; + Enum* enum_; + + inline TypeInfo(const TypeDescriptor* descriptor) : descriptor(descriptor) {} + TypeInfo(Enum*); }; \ No newline at end of file diff --git a/core/src/datatypes/cframe.cpp b/core/src/datatypes/cframe.cpp index b4d8be7..917b1c8 100644 --- a/core/src/datatypes/cframe.cpp +++ b/core/src/datatypes/cframe.cpp @@ -134,7 +134,7 @@ void CFrame::Serialize(pugi::xml_node node) const { } -Variant CFrame::Deserialize(pugi::xml_node node) { +CFrame CFrame::Deserialize(pugi::xml_node node) { return CFrame( node.child("X").text().as_float(), node.child("Y").text().as_float(), diff --git a/core/src/datatypes/cframe.h b/core/src/datatypes/cframe.h index 46311e7..7a1b996 100644 --- a/core/src/datatypes/cframe.h +++ b/core/src/datatypes/cframe.h @@ -40,7 +40,7 @@ public: virtual const std::string ToString() const; virtual void Serialize(pugi::xml_node parent) const; - static Variant Deserialize(pugi::xml_node node); + static CFrame Deserialize(pugi::xml_node node); static void PushLuaLibrary(lua_State*); diff --git a/core/src/datatypes/color3.cpp b/core/src/datatypes/color3.cpp index d612369..24dc01d 100644 --- a/core/src/datatypes/color3.cpp +++ b/core/src/datatypes/color3.cpp @@ -39,6 +39,6 @@ void Color3::Serialize(pugi::xml_node node) const { node.text().set(this->ToHex()); } -Variant Color3::Deserialize(pugi::xml_node node) { +Color3 Color3::Deserialize(pugi::xml_node node) { return Color3::FromHex(node.text().get()); } \ No newline at end of file diff --git a/core/src/datatypes/color3.h b/core/src/datatypes/color3.h index 545b9b5..ba5e837 100644 --- a/core/src/datatypes/color3.h +++ b/core/src/datatypes/color3.h @@ -21,7 +21,7 @@ public: virtual const std::string ToString() const; DEF_DATA_METHOD std::string ToHex() const; virtual void Serialize(pugi::xml_node node) const; - static Variant Deserialize(pugi::xml_node node); + static Color3 Deserialize(pugi::xml_node node); static void PushLuaLibrary(lua_State*); diff --git a/core/src/datatypes/enum.cpp b/core/src/datatypes/enum.cpp index 96668f7..2ad5ce7 100644 --- a/core/src/datatypes/enum.cpp +++ b/core/src/datatypes/enum.cpp @@ -1,8 +1,12 @@ #include "enum.h" +#include "datatypes/base.h" +#include "datatypes/variant.h" + +TypeInfo::TypeInfo(Enum* enum_) : enum_(enum_), descriptor(&EnumItem::TYPE) {} Enum::Enum(_EnumData* data) : data(data) {} -std::vector Enum::GetEnumItems() { +std::vector Enum::GetEnumItems() const { std::vector enumItems; for (int i = 0; i < data->count; i++) { @@ -12,7 +16,7 @@ std::vector Enum::GetEnumItems() { return enumItems; } -std::optional Enum::FromName(std::string name) { +std::optional Enum::FromName(std::string name) const { for (int i = 0; i < data->count; i++) { if (data->values[i].second == name) return EnumItem(data, name, data->values[i].first); @@ -20,7 +24,7 @@ std::optional Enum::FromName(std::string name) { return {}; } -std::optional Enum::FromValue(int value) { +std::optional Enum::FromValue(int value) const { for (int i = 0; i < data->count; i++) { if (data->values[i].first == value) return EnumItem(data, data->values[i].second, value); @@ -28,4 +32,28 @@ std::optional Enum::FromValue(int value) { return {}; } -EnumItem::EnumItem(_EnumData* parentData, std::string name, int value) : parentData(parentData), name(name), value(value) {} \ No newline at end of file +EnumItem::EnumItem(_EnumData* parentData, std::string name, int value) : parentData(parentData), name(name), value(value) {} + +// + +std::string Enum::ToString() { + return "Enum." + this->data->name; +} + +void Enum::PushLuaValue(lua_State*) { + +} + +Variant Enum::FromLuaValue(lua_State*, int) { + +} + +const TypeDescriptor Enum::TYPE { + .name = "Enum", + .toString = toVariantFunction(&Enum::ToString), + // .fromString = Enum_FromString, + // .pushLuaValue = &Enum_PushLuaValue, + .fromLuaValue = toVariantGenerator(Enum::FromLuaValue), + // .serializer = Enum_Serialize, + // .deserializer = Enum_Deserialize, +}; \ No newline at end of file diff --git a/core/src/datatypes/enum.h b/core/src/datatypes/enum.h index 7bb66c1..b8c6fa0 100644 --- a/core/src/datatypes/enum.h +++ b/core/src/datatypes/enum.h @@ -1,11 +1,14 @@ #pragma once +#include "base.h" #include #include #include +#include "lua.h" struct _EnumData { std::pair* values; + std::string name; int count; }; @@ -16,9 +19,16 @@ class Enum { public: Enum(_EnumData*); - std::vector GetEnumItems(); - std::optional FromName(std::string); - std::optional FromValue(int); + static const TypeDescriptor TYPE; + + inline _EnumData* InternalType() const { return this->data; }; + std::vector GetEnumItems() const; + std::optional FromName(std::string) const; + std::optional FromValue(int) const; + + std::string ToString(); + void PushLuaValue(lua_State*); + static Variant FromLuaValue(lua_State*, int); }; class EnumItem { @@ -27,7 +37,10 @@ class EnumItem { int value; public: EnumItem(_EnumData*, std::string, int); - inline std::string Name() { return this->name; } - inline int Value() { return this->value; } - inline Enum EnumType() { return Enum(this->parentData); } + + static const TypeDescriptor TYPE; + + inline std::string Name() const { return this->name; } + inline int Value() const { return this->value; } + inline Enum EnumType() const { return Enum(this->parentData); } }; \ No newline at end of file diff --git a/core/src/datatypes/ref.cpp b/core/src/datatypes/ref.cpp index a20686b..ddfe121 100644 --- a/core/src/datatypes/ref.cpp +++ b/core/src/datatypes/ref.cpp @@ -39,7 +39,7 @@ void InstanceRef::Serialize(pugi::xml_node node) const { panic(); } -Variant InstanceRef::Deserialize(pugi::xml_node node) { +InstanceRef InstanceRef::Deserialize(pugi::xml_node node) { // Handled by Instance panic(); } diff --git a/core/src/datatypes/ref.h b/core/src/datatypes/ref.h index 21be169..15f5c19 100644 --- a/core/src/datatypes/ref.h +++ b/core/src/datatypes/ref.h @@ -20,6 +20,6 @@ public: virtual const std::string ToString() const; virtual void Serialize(pugi::xml_node node) const; virtual void PushLuaValue(lua_State*) const; - static Variant Deserialize(pugi::xml_node node); + static InstanceRef Deserialize(pugi::xml_node node); static result FromLuaValue(lua_State*, int idx); }; \ No newline at end of file diff --git a/core/src/datatypes/variant.cpp b/core/src/datatypes/variant.cpp index 7b6d813..c9915bc 100644 --- a/core/src/datatypes/variant.cpp +++ b/core/src/datatypes/variant.cpp @@ -1,6 +1,7 @@ #include "variant.h" #include "datatypes/base.h" #include "datatypes/cframe.h" +#include "datatypes/enum.h" #include "datatypes/primitives.h" #include "datatypes/ref.h" #include "datatypes/signal.h" @@ -31,26 +32,44 @@ const TypeDescriptor* VARIANT_TYPES[] { &InstanceRef::TYPE, &SignalRef::TYPE, &SignalConnectionRef::TYPE, + // &Enum::TYPE, + // &EnumItem::TYPE, }; +const TypeInfo Variant::GetTypeInfo() const { + return VARIANT_TYPES[wrapped.index()]; +} + +const TypeDescriptor* Variant::GetType() const { + return VARIANT_TYPES[wrapped.index()]; +} + std::string Variant::ToString() const { + if (!VARIANT_TYPES[wrapped.index()]->pushLuaValue) { + Logger::fatalErrorf("Data type %s does not implement toString", VARIANT_TYPES[wrapped.index()]->name.c_str()); + } return VARIANT_TYPES[wrapped.index()]->toString(*this); } void Variant::Serialize(pugi::xml_node node) const { + if (!VARIANT_TYPES[wrapped.index()]->pushLuaValue) { + Logger::fatalErrorf("Data type %s does not implement serializer", VARIANT_TYPES[wrapped.index()]->name.c_str()); + } VARIANT_TYPES[wrapped.index()]->serializer(*this, node); } void Variant::PushLuaValue(lua_State* state) const { - printf("What %zu\n", wrapped.index()); + if (!VARIANT_TYPES[wrapped.index()]->pushLuaValue) { + Logger::fatalErrorf("Data type %s does not implement pushLuaValue", VARIANT_TYPES[wrapped.index()]->name.c_str()); + } VARIANT_TYPES[wrapped.index()]->pushLuaValue(*this, state); } Variant Variant::Deserialize(pugi::xml_node node, const TypeInfo type) { - if (type.type == DATA_VALUE) - return type.descriptor->deserializer(node); - else - panic(); //TODO: NYI + if (!type.descriptor->deserializer) { + Logger::fatalErrorf("Data type %s does not implement deserialize", type.descriptor->name.c_str()); + } + return type.descriptor->deserializer(node); } std::map TYPE_MAP = { diff --git a/core/src/datatypes/variant.h b/core/src/datatypes/variant.h index ddbe9b6..d5fbba0 100644 --- a/core/src/datatypes/variant.h +++ b/core/src/datatypes/variant.h @@ -4,6 +4,7 @@ #include #include "base.h" #include "datatypes/color3.h" +#include "datatypes/enum.h" #include "datatypes/ref.h" #include "datatypes/signal.h" #include "vector.h" @@ -28,7 +29,9 @@ typedef std::variant< Color3, InstanceRef, SignalRef, - SignalConnectionRef + SignalConnectionRef, + Enum, + EnumItem > __VARIANT_TYPE; class Variant { @@ -38,6 +41,9 @@ public: template T get() { return std::get(wrapped); } std::string ToString() const; + const TypeInfo GetTypeInfo() const; + const TypeDescriptor* GetType() const; + void Serialize(pugi::xml_node node) const; void PushLuaValue(lua_State* state) const; static Variant Deserialize(pugi::xml_node node, const TypeInfo); @@ -57,5 +63,12 @@ std::function toVariantFunction(R(T::*f)(Args...) const) { }; } +template +std::function toVariantGenerator(T(f)(Args...)) { + return [f](Args... args) { + return (Variant)f(args...); + }; +} + // Map of all data types to their type names extern std::map TYPE_MAP; \ No newline at end of file diff --git a/core/src/datatypes/vector.cpp b/core/src/datatypes/vector.cpp index 23f3086..39c58fe 100644 --- a/core/src/datatypes/vector.cpp +++ b/core/src/datatypes/vector.cpp @@ -87,7 +87,7 @@ void Vector3::Serialize(pugi::xml_node node) const { node.append_child("Z").text().set(std::to_string(this->Z())); } -Variant Vector3::Deserialize(pugi::xml_node node) { +Vector3 Vector3::Deserialize(pugi::xml_node node) { return Vector3(node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float()); } diff --git a/core/src/datatypes/vector.h b/core/src/datatypes/vector.h index 0388fe9..3f2a3d3 100644 --- a/core/src/datatypes/vector.h +++ b/core/src/datatypes/vector.h @@ -24,7 +24,7 @@ public: virtual const std::string ToString() const; virtual void Serialize(pugi::xml_node node) const; - static Variant Deserialize(pugi::xml_node node); + static Vector3 Deserialize(pugi::xml_node node); static std::optional FromString(std::string); static void PushLuaLibrary(lua_State*); diff --git a/core/src/objects/base/instance.cpp b/core/src/objects/base/instance.cpp index 0cc6cc1..b5aabfd 100644 --- a/core/src/objects/base/instance.cpp +++ b/core/src/objects/base/instance.cpp @@ -270,11 +270,11 @@ void Instance::Serialize(pugi::xml_node parent, RefStateSerialize state) { PropertyMeta meta = GetPropertyMeta(name).expect("Meta of declared property is missing"); if (meta.flags & (PROP_NOSAVE | PROP_READONLY)) continue; // This property should not be serialized. Skip... - pugi::xml_node propertyNode = propertiesNode.append_child(meta.type.type == DATA_ENUM ? "token" : meta.type.descriptor->name); + pugi::xml_node propertyNode = propertiesNode.append_child(meta.type.descriptor->name); propertyNode.append_attribute("name").set_value(name); // Update std::shared_ptr properties using map above - if (meta.type.type == DATA_VALUE && meta.type.descriptor == &InstanceRef::TYPE) { + if (meta.type.descriptor == &InstanceRef::TYPE) { std::weak_ptr refWeak = GetPropertyValue(name).expect("Declared property is missing").get(); if (refWeak.expired()) continue; @@ -335,7 +335,7 @@ result, NoSuchInstance> Instance::Deserialize(pugi::xm auto meta = meta_.expect(); // Update std::shared_ptr properties using map above - if (meta.type.type == DATA_VALUE && meta.type.descriptor == &InstanceRef::TYPE) { + if (meta.type.descriptor == &InstanceRef::TYPE) { if (propertyNode.text().empty()) continue; @@ -437,7 +437,7 @@ std::optional> Instance::Clone(RefStateClone state) { if (meta.flags & (PROP_READONLY | PROP_NOSAVE)) continue; // Update std::shared_ptr properties using map above - if (meta.type.type == DATA_VALUE && meta.type.descriptor == &InstanceRef::TYPE) { + if (meta.type.descriptor == &InstanceRef::TYPE) { std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); if (refWeak.expired()) continue; @@ -487,7 +487,7 @@ std::vector>> Instance::GetRefe for (std::string property : propertyNames) { PropertyMeta meta = GetPropertyMeta(property).expect(); - if (meta.type.type != DATA_VALUE || meta.type.descriptor != &InstanceRef::TYPE) continue; + if (meta.type.descriptor != &InstanceRef::TYPE) continue; std::weak_ptr ref = GetPropertyValue(property).expect().get(); if (ref.expired()) continue; diff --git a/core/src/objects/datamodel.cpp b/core/src/objects/datamodel.cpp index 3d413c3..3ff30ed 100644 --- a/core/src/objects/datamodel.cpp +++ b/core/src/objects/datamodel.cpp @@ -131,7 +131,7 @@ std::shared_ptr DataModel::CloneModel() { if (meta.flags & (PROP_READONLY | PROP_NOSAVE)) continue; // Update std::shared_ptr properties using map above - if (meta.type.type == DATA_VALUE && meta.type.descriptor == &InstanceRef::TYPE) { + if (meta.type.descriptor == &InstanceRef::TYPE) { std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); if (refWeak.expired()) continue; diff --git a/editor/panes/propertiesview.cpp b/editor/panes/propertiesview.cpp index 20127c4..2ac45cb 100644 --- a/editor/panes/propertiesview.cpp +++ b/editor/panes/propertiesview.cpp @@ -66,9 +66,7 @@ public: return nullptr; } - if (meta.type.type == DATA_ENUM) { - - } else if (meta.type.descriptor == &FLOAT_TYPE) { + if (meta.type.descriptor == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); spinBox->setValue(currentValue.get()); @@ -134,9 +132,7 @@ public: return; } - if (meta.type.type == DATA_ENUM) { - - } else if (meta.type.descriptor == &FLOAT_TYPE) { + if (meta.type.descriptor == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = dynamic_cast(editor); spinBox->setValue(currentValue.get()); @@ -191,9 +187,7 @@ public: return; } - if (meta.type.type == DATA_ENUM) { - - } else if (meta.type.descriptor == &FLOAT_TYPE) { + if (meta.type.descriptor == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = dynamic_cast(editor); inst->SetPropertyValue(propertyName, (float)spinBox->value()).expect(); @@ -327,7 +321,7 @@ void PropertiesView::setSelected(std::optional> instan item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString())); } - if (meta.type.type == DATA_VALUE && meta.type.descriptor != &Color3::TYPE && (!meta.type.descriptor->fromString || meta.flags & PROP_READONLY)) { + if (meta.type.descriptor != &Color3::TYPE && (!meta.type.descriptor->fromString || meta.flags & PROP_READONLY)) { item->setDisabled(true); } @@ -424,7 +418,7 @@ void PropertiesView::onPropertyUpdated(std::shared_ptr inst, std::stri item->setData(1, Qt::DisplayRole, QString::fromStdString(currentValue.ToString())); } - if (meta.type.type == DATA_VALUE && meta.type.descriptor != &Color3::TYPE && (!meta.type.descriptor->fromString || meta.flags & PROP_READONLY)) { + if (meta.type.descriptor != &Color3::TYPE && (!meta.type.descriptor->fromString || meta.flags & PROP_READONLY)) { item->setDisabled(true); }