From 5f6ff971d257fd348bf1d0738845b37a868b6c25 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Sat, 31 May 2025 23:08:05 +0200 Subject: [PATCH] refactor(datatypes): complete refactor of how datatypes work and removal of wrapper classes for bool, string etc. --- autogen/src/data/codegen.cpp | 80 ++++---- autogen/src/main.cpp | 4 +- autogen/src/object/codegen.cpp | 49 ++--- core/src/common.cpp | 4 +- core/src/common.h | 4 +- core/src/datatypes/annotation.h | 5 +- core/src/datatypes/base.cpp | 162 ----------------- core/src/datatypes/base.h | 79 ++------ core/src/datatypes/cframe.cpp | 58 +++--- core/src/datatypes/cframe.h | 100 +++++----- core/src/datatypes/color3.cpp | 20 +- core/src/datatypes/color3.h | 44 ++--- core/src/datatypes/meta.cpp | 48 ----- core/src/datatypes/meta.h | 49 ----- core/src/datatypes/primitives.cpp | 211 ++++++++++++++++++++++ core/src/datatypes/primitives.h | 9 + core/src/datatypes/ref.cpp | 42 +++-- core/src/datatypes/ref.h | 31 ++-- core/src/datatypes/signal.cpp | 70 ++++--- core/src/datatypes/signal.h | 79 ++++---- core/src/datatypes/variant.cpp | 68 +++++++ core/src/datatypes/variant.h | 61 +++++++ core/src/datatypes/vector.cpp | 66 +++---- core/src/datatypes/vector.h | 88 +++++---- core/src/objects/annotation.h | 4 +- core/src/objects/base/instance.cpp | 59 +++--- core/src/objects/base/instance.h | 8 +- core/src/objects/base/member.h | 2 +- core/src/objects/datamodel.cpp | 14 +- core/src/objects/script.cpp | 4 +- core/src/objects/script/scriptcontext.cpp | 6 +- core/src/objects/workspace.cpp | 10 +- core/src/partassembly.cpp | 12 +- core/src/rendering/renderer.h | 4 +- core/src/rendering/surface.h | 2 +- editor/mainglwidget.cpp | 2 +- editor/panes/propertiesview.cpp | 65 +++---- editor/panes/propertiesview.h | 4 +- editor/script/scriptdocument.cpp | 8 +- 39 files changed, 831 insertions(+), 804 deletions(-) delete mode 100644 core/src/datatypes/base.cpp delete mode 100644 core/src/datatypes/meta.cpp delete mode 100644 core/src/datatypes/meta.h create mode 100644 core/src/datatypes/primitives.cpp create mode 100644 core/src/datatypes/primitives.h create mode 100644 core/src/datatypes/variant.cpp create mode 100644 core/src/datatypes/variant.h diff --git a/autogen/src/data/codegen.cpp b/autogen/src/data/codegen.cpp index a5826ee..427bbaa 100644 --- a/autogen/src/data/codegen.cpp +++ b/autogen/src/data/codegen.cpp @@ -9,10 +9,6 @@ using namespace data; static std::map MAPPED_TYPE = { - { "bool", "Data::Bool" }, - { "int", "Data::Int" }, - { "float", "Data::Float" }, - { "std::string", "Data::String" }, { "glm::vec3", "Vector3" }, }; @@ -30,16 +26,36 @@ static std::map LUA_TEST_FUNCS = { { "std::string", "lua_isstring" }, }; +static std::map LUA_PUSH_FUNCS = { + { "bool", "lua_pushboolean" }, + { "int", "lua_pushinteger" }, + { "float", "lua_pushnumber" }, + // Handled specially + // { "std::string", "lua_pushstring" }, +}; + static std::string getLuaMethodFqn(std::string className, std::string methodName) { return "__lua_impl__" + className + "__" + methodName; } static std::string getMtName(std::string type) { - if (type.starts_with("Data::")) - return "__mt_" + type.substr(6); + // if (type.starts_with("Data::")) + // return "__mt_" + type.substr(6); return "__mt_" + type; } +static std::string pushLuaValue(std::string type, std::string expr) { + if (type == "std::string") + return "lua_pushstring(L, " + expr + ".c_str())"; + std::string mappedType = MAPPED_TYPE[type]; + if (mappedType != "") + return mappedType + "(" + expr + ").PushLuaValue(L)"; + std::string pushFunc = LUA_PUSH_FUNCS[type]; + if (pushFunc != "") + return pushFunc + "(L, " + expr + ")"; + return expr + ".PushLuaValue(L)"; +} + static void writeLuaGetArgument(std::ofstream& out, std::string type, int narg, bool member) { std::string varname = "arg" + std::to_string(narg); narg += 1; // Arguments start at 1 @@ -69,7 +85,7 @@ static void writeLuaTestArgument(std::ofstream& out, std::string type, int narg, } static void writeLuaMethodImpls(std::ofstream& out, ClassAnalysis& state) { - std::string fqn = "Data::" + state.name; + std::string fqn = "" + state.name; // Collect all method names to account for overloaded functions std::map> methods; @@ -132,11 +148,7 @@ static void writeLuaMethodImpls(std::ofstream& out, ClassAnalysis& state) { // Return result if (methodImpl.returnType != "void") { - std::string mappedType = MAPPED_TYPE[methodImpl.returnType]; - if (mappedType == "") - out << " result.PushLuaValue(L);\n"; - else - out << " " << mappedType << "(result).PushLuaValue(L);\n"; + out << " " << pushLuaValue(methodImpl.returnType, "result") << ";\n"; } if (methodImpl.returnType == "void") @@ -205,11 +217,7 @@ static void writeLuaMethodImpls(std::ofstream& out, ClassAnalysis& state) { // Return result if (methodImpl.returnType != "void") { - std::string mappedType = MAPPED_TYPE[methodImpl.returnType]; - if (mappedType == "") - out << " result.PushLuaValue(L);\n"; - else - out << " " << mappedType << "(result).PushLuaValue(L);\n"; + out << " " << pushLuaValue(methodImpl.returnType, "result") << ";\n"; } if (methodImpl.returnType == "void") @@ -228,7 +236,7 @@ static void writeLuaMethodImpls(std::ofstream& out, ClassAnalysis& state) { } static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) { - std::string fqn = "Data::" + state.name; + std::string fqn = state.name; out << "static int data_gc(lua_State*);\n" "static int data_index(lua_State*);\n" @@ -240,12 +248,9 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) { " {NULL, NULL} /* end of array */\n" "};\n\n"; - out << "void Data::" << state.name << "::PushLuaValue(lua_State* L) const {\n" + out << "void " << state.name << "::PushLuaValue(lua_State* L) const {\n" " int n = lua_gettop(L);\n" - // " // I'm torn... should this be Data::Variant, or Data::Base?\n" - // " // If I ever decouple typing from Data::Base, I'll switch it to variant,\n" - // " // otherwise, it doesn't make much sense to represent it as one\n" " " << fqn << "** userdata = (" << fqn << "**)lua_newuserdata(L, sizeof(" << fqn << "));\n" " *userdata = new " << fqn << "(*this);\n" @@ -257,11 +262,11 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) { "}\n\n"; - out << "result Data::" << state.name << "::FromLuaValue(lua_State* L, int idx) {\n" + out << "result " << state.name << "::FromLuaValue(lua_State* L, int idx) {\n" " " << fqn << "** userdata = (" << fqn << "**) luaL_testudata(L, idx, \"" << getMtName(state.name) << "\");\n" " if (userdata == nullptr)\n" " return LuaCastError(lua_typename(L, idx), \"" << state.name << "\");\n" - " return Data::Variant(**userdata);\n" + " return Variant(**userdata);\n" "}\n\n"; // Indexing methods and properties @@ -292,7 +297,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) { valueExpr = "this_->" + prop.backingSymbol + "()"; // This largely depends on the type - out << " " << type << "(" << valueExpr << ").PushLuaValue(L);\n"; + out << " " << pushLuaValue(type, valueExpr) << ";\n"; out << " return 1;\n"; out << " }"; @@ -334,7 +339,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) { } static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) { - std::string fqn = "Data::" + state.name; + std::string fqn = state.name; out << "static int lib_index(lua_State*);\n" "static const struct luaL_Reg lib_metatable [] = {\n" @@ -342,7 +347,7 @@ static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) { " {NULL, NULL} /* end of array */\n" "};\n\n"; - out << "void Data::" << state.name << "::PushLuaLibrary(lua_State* L) {\n" + out << "void " << state.name << "::PushLuaLibrary(lua_State* L) {\n" " lua_getglobal(L, \"_G\");\n" " lua_pushstring(L, \"" << state.name << "\");\n" "\n" @@ -382,7 +387,7 @@ static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) { else if (prop.backingType == PropertyBackingType::Method) valueExpr = fqn + "::" + prop.backingSymbol + "()"; - out << " " << type << "(" << valueExpr << ").PushLuaValue(L);\n"; + out << " " << pushLuaValue(type, valueExpr) << ";\n"; out << " return 1;\n"; out << " }"; @@ -408,22 +413,19 @@ static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) { } void data::writeCodeForClass(std::ofstream& out, std::string headerPath, ClassAnalysis& state) { - std::string fqn = "Data::" + state.name; - out << "#define __AUTOGEN_EXTRA_INCLUDES__\n"; out << "#include \"" << headerPath << "\"\n\n"; - out << "#include \"datatypes/meta.h\"\n"; + out << "#include \"datatypes/variant.h\"\n"; out << "#include \n"; out << "#include \"lua.h\"\n\n"; - out << "const Data::TypeInfo " << fqn << "::TYPE = {\n" + out << "const TypeInfo " << state.name << "::TYPE = {\n" << " .name = \"" << state.serializedName << "\",\n" - << " .deserializer = &" << fqn << "::Deserialize,\n"; - if (state.hasFromString) out << " .fromString = &" << fqn << "::FromString,\n"; - out << " .fromLuaValue = &" << fqn << "::FromLuaValue,\n" - << "};\n\n"; - - out << "const Data::TypeInfo& " << fqn << "::GetType() const {\n" - << " return TYPE;\n" + << " .serializer = toVariantFunction(&" << state.name << "::Serialize)," + << " .deserializer = &" << state.name << "::Deserialize,\n" + << " .toString = toVariantFunction(&" << state.name << "::ToString),"; + if (state.hasFromString) out << " .fromString = &" << state.name << "::FromString,\n"; + out << " .pushLuaValue = toVariantFunction(&" << state.name << "::PushLuaValue)," + << " .fromLuaValue = &" << state.name << "::FromLuaValue,\n" << "};\n\n"; writeLuaMethodImpls(out, state); diff --git a/autogen/src/main.cpp b/autogen/src/main.cpp index fe30b6b..b694687 100644 --- a/autogen/src/main.cpp +++ b/autogen/src/main.cpp @@ -54,7 +54,7 @@ int processHeader(fs::path srcRoot, fs::path srcPath, fs::path outPath) { fs::path relpath = fs::relative(srcPath, srcRoot); printf("[AUTOGEN] Processing file %s...\n", relpath.c_str()); object::analyzeClasses(cursor, srcRoot, &objectAnlyState); - data::analyzeClasses(cursor, srcRoot, &dataAnlyState); + analyzeClasses(cursor, srcRoot, &dataAnlyState); fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it @@ -72,7 +72,7 @@ int processHeader(fs::path srcRoot, fs::path srcPath, fs::path outPath) { } for (auto& [_, clazz] : dataAnlyState.classes) { - data::writeCodeForClass(outStream, relpath, clazz); + writeCodeForClass(outStream, relpath, clazz); } outStream.close(); diff --git a/autogen/src/object/codegen.cpp b/autogen/src/object/codegen.cpp index b15aa22..333b31d 100644 --- a/autogen/src/object/codegen.cpp +++ b/autogen/src/object/codegen.cpp @@ -16,13 +16,17 @@ static std::map CATEGORY_STR = { }; static std::map MAPPED_TYPE = { - { "bool", "Data::Bool" }, - { "int", "Data::Int" }, - { "float", "Data::Float" }, - { "std::string", "Data::String" }, { "glm::vec3", "Vector3" }, }; +static std::map TYPEINFO_REFS = { + { "glm::vec3", "Vector3::TYPE" }, + { "bool", "BOOL_TYPE" }, + { "int", "INT_TYPE" }, + { "float", "FLOAT_TYPE" }, + { "std::string", "STRING_TYPE" }, +}; + static std::map ENUM_TYPES = { { "SurfaceType", std::monostate() } }; @@ -40,7 +44,7 @@ static std::string parseWeakPtr(std::string weakPtrType) { static std::string castFromVariant(std::string valueStr, std::string fieldType) { // Manual exception for now, enums will get their own system eventually if (fieldType == "SurfaceType") { - return "(SurfaceType)(int)" + valueStr + ".get()"; + return "(SurfaceType)(int)" + valueStr + ".get()"; } std::string mappedType = MAPPED_TYPE[fieldType]; @@ -50,13 +54,13 @@ static std::string castFromVariant(std::string valueStr, std::string fieldType) static std::string castToVariant(std::string valueStr, std::string fieldType) { // Manual exception for now, enums will get their own system eventually if (fieldType == "SurfaceType") { - return "Data::Int((int)" + valueStr + ")"; + return "(int)" + valueStr; } // std::shared_ptr std::string subtype = parseWeakPtr(fieldType); if (!subtype.empty()) { - return "Data::Variant(" + valueStr + ".expired() ? Data::InstanceRef() : Data::InstanceRef(std::dynamic_pointer_cast(" + valueStr + ".lock())))"; + return "Variant(" + valueStr + ".expired() ? InstanceRef() : InstanceRef(std::dynamic_pointer_cast(" + valueStr + ".lock())))"; } std::string mappedType = MAPPED_TYPE[fieldType]; @@ -67,7 +71,7 @@ static std::string castToVariant(std::string valueStr, std::string fieldType) { } static void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) { - out << "fallible " << state.name << "::InternalSetPropertyValue(std::string name, Data::Variant value) {"; + out << "fallible " << state.name << "::InternalSetPropertyValue(std::string name, Variant value) {"; out << "\n "; bool first = true; @@ -83,7 +87,7 @@ static void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) { } else if (prop.cframeMember == CFrameMember_Rotation) { out << "\n this->" << prop.fieldName << " = CFrame::FromEulerAnglesXYZ(value.get()) + this->" << prop.fieldName << ".Position();"; } else if (!subtype.empty()) { - out << "\n std::weak_ptr ref = value.get();" + out << "\n std::weak_ptr ref = value.get();" << "\n this->" << prop.fieldName << " = ref.expired() ? std::weak_ptr<" << subtype << ">() : std::dynamic_pointer_cast<" << subtype << ">(ref.lock());"; } else { out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";"; @@ -128,7 +132,7 @@ static void writePropertyUpdateHandler(std::ofstream& out, ClassAnalysis state) } static void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) { - out << "result " << state.name << "::InternalGetPropertyValue(std::string name) {"; + out << "result " << state.name << "::InternalGetPropertyValue(std::string name) {"; out << "\n "; bool first = true; @@ -136,11 +140,11 @@ static void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) { out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {"; if (prop.cframeMember == CFrameMember_Position) { - out << "\n return Data::Variant(" << prop.fieldName << ".Position());"; + out << "\n return Variant(" << prop.fieldName << ".Position());"; } else if (prop.cframeMember == CFrameMember_Rotation) { - out << "\n return Data::Variant(" << prop.fieldName << ".ToEulerAnglesXYZ());"; + out << "\n return Variant(" << prop.fieldName << ".ToEulerAnglesXYZ());"; } else { - out << "\n return Data::Variant(" << castToVariant(prop.fieldName, prop.backingFieldType) << ");"; + out << "\n return Variant(" << castToVariant(prop.fieldName, prop.backingFieldType) << ");"; } out << "\n }"; @@ -153,7 +157,7 @@ static void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) { for (auto& signal : state.signals) { out << (first ? "" : " else ") << "if (name == \"" << signal.name << "\") {"; - out << "\n return Data::Variant(Data::SignalRef(" << signal.sourceFieldName << "));"; + out << "\n return Variant(SignalRef(" << signal.sourceFieldName << "));"; out << "\n }"; first = false; @@ -186,10 +190,10 @@ static void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) { for (auto& prop : state.properties) { out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {"; - std::string type = MAPPED_TYPE[prop.backingFieldType]; - if (type.empty()) type = prop.backingFieldType; - if (type == "SurfaceType") type = "Data::Int"; - if (!parseWeakPtr(prop.backingFieldType).empty()) type = "Data::InstanceRef"; + std::string typeInfo = TYPEINFO_REFS[prop.backingFieldType]; + if (typeInfo.empty()) typeInfo = prop.backingFieldType + "::TYPE"; + if (!parseWeakPtr(prop.backingFieldType).empty()) typeInfo = "InstanceRef::TYPE"; + if (prop.backingFieldType == "SurfaceType") typeInfo = "INT_TYPE"; std::string strFlags; if (prop.flags & PropertyFlag_Readonly) @@ -206,7 +210,7 @@ static void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) { std::string category = CATEGORY_STR[prop.category]; if (category.empty()) category = "PROP_CATEGORY_DATA"; - out << "\n return PropertyMeta { &" << type << "::TYPE, " << strFlags << ", " << category << " };"; + out << "\n return PropertyMeta { &" << typeInfo << ", " << strFlags << ", " << category << " };"; out << "\n }"; first = false; @@ -220,8 +224,8 @@ static void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) { std::string strFlags; strFlags += "PROP_READONLY"; - strFlags += "| PROP_HIDDEN"; - strFlags += "| PROP_NOSAVE"; + strFlags += " | PROP_HIDDEN"; + strFlags += " | PROP_NOSAVE"; out << "\n return PropertyMeta { &SignalRef::TYPE, " << strFlags << " };"; @@ -252,7 +256,8 @@ void object::writeCodeForClass(std::ofstream& out, std::string headerPath, Class out << "#define __AUTOGEN_EXTRA_INCLUDES__\n"; out << "#include \"" << state.headerPath << "\"\n\n"; - out << "#include \"datatypes/meta.h\"\n\n"; + out << "#include \"datatypes/variant.h\"\n\n"; + out << "#include \"datatypes/primitives.h\"\n\n"; out << "const InstanceType " << state.name << "::TYPE = {\n" << " .super = &" << state.baseClass << "::TYPE,\n" << " .className = \"" << state.name << "\",\n" diff --git a/core/src/common.cpp b/core/src/common.cpp index fc58748..1cc79f8 100644 --- a/core/src/common.cpp +++ b/core/src/common.cpp @@ -1,7 +1,7 @@ // TEMPORARY COMMON DATA FOR DIFFERENT INTERNAL COMPONENTS #include "objects/datamodel.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include "common.h" #include @@ -34,7 +34,7 @@ void addSelectionListener(SelectionUpdateHandler handler) { selectionUpdateListeners.push_back(handler); } -void sendPropertyUpdatedSignal(std::shared_ptr instance, std::string property, Data::Variant newValue) { +void sendPropertyUpdatedSignal(std::shared_ptr instance, std::string property, Variant newValue) { for (PropertyUpdateHandler handler : propertyUpdatelisteners) { handler(instance, property, newValue); } diff --git a/core/src/common.h b/core/src/common.h index 70f68b2..d50d4e1 100644 --- a/core/src/common.h +++ b/core/src/common.h @@ -12,7 +12,7 @@ class Instance; typedef std::function object, std::optional> oldParent, std::optional> newParent)> HierarchyPreUpdateHandler; typedef std::function object, std::optional> oldParent, std::optional> newParent)> HierarchyPostUpdateHandler; typedef std::function> oldSelection, std::vector> newSelection, bool fromExplorer)> SelectionUpdateHandler; -typedef std::function instance, std::string property, Data::Variant newValue)> PropertyUpdateHandler; +typedef std::function instance, std::string property, Variant newValue)> PropertyUpdateHandler; // TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS @@ -28,5 +28,5 @@ void setSelection(std::vector> newSelection, bool from const std::vector> getSelection(); void addSelectionListener(SelectionUpdateHandler handler); -void sendPropertyUpdatedSignal(std::shared_ptr instance, std::string property, Data::Variant newValue); +void sendPropertyUpdatedSignal(std::shared_ptr instance, std::string property, Variant newValue); void addPropertyUpdateListener(PropertyUpdateHandler handler); \ No newline at end of file diff --git a/core/src/datatypes/annotation.h b/core/src/datatypes/annotation.h index ff5b760..dd7d481 100644 --- a/core/src/datatypes/annotation.h +++ b/core/src/datatypes/annotation.h @@ -26,8 +26,7 @@ #define AUTOGEN_PREAMBLE_DATA \ public: \ -virtual const TypeInfo& GetType() const override; \ static const TypeInfo TYPE; \ -virtual void PushLuaValue(lua_State*) const override; \ -static result FromLuaValue(lua_State*, int idx); \ +virtual void PushLuaValue(lua_State*) const; \ +static result FromLuaValue(lua_State*, int idx); \ private: diff --git a/core/src/datatypes/base.cpp b/core/src/datatypes/base.cpp deleted file mode 100644 index 56beb07..0000000 --- a/core/src/datatypes/base.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "base.h" -#include "error/data.h" -#include "meta.h" -#include -#include -#include -#include "lua.h" - -#define IMPL_WRAPPER_CLASS(CLASS_NAME, WRAPPED_TYPE, TYPE_NAME) Data::CLASS_NAME::CLASS_NAME(WRAPPED_TYPE in) : value(in) {} \ -Data::CLASS_NAME::~CLASS_NAME() = default; \ -Data::CLASS_NAME::operator const WRAPPED_TYPE() const { return value; } \ -const Data::TypeInfo Data::CLASS_NAME::TYPE = { \ - .name = TYPE_NAME, \ - .deserializer = &Data::CLASS_NAME::Deserialize, \ - .fromString = &Data::CLASS_NAME::FromString, \ - .fromLuaValue = &Data::CLASS_NAME::FromLuaValue, \ -}; \ -const Data::TypeInfo& Data::CLASS_NAME::GetType() const { return Data::CLASS_NAME::TYPE; }; \ -void Data::CLASS_NAME::Serialize(pugi::xml_node node) const { node.text().set(std::string(this->ToString())); } - -Data::Base::~Base() {}; - -Data::Null::Null() {}; -Data::Null::~Null() = default; -const Data::TypeInfo Data::Null::TYPE = { - .name = "null", - .deserializer = &Data::Null::Deserialize, -}; -const Data::TypeInfo& Data::Null::GetType() const { return Data::Null::TYPE; }; - -const Data::String Data::Null::ToString() const { - return Data::String("null"); -} - -void Data::Null::Serialize(pugi::xml_node node) const { - node.text().set("null"); -} - -Data::Variant Data::Null::Deserialize(pugi::xml_node node) { - return Data::Null(); -} - -void Data::Null::PushLuaValue(lua_State* L) const { - lua_pushnil(L); -} - -result Data::Null::FromLuaValue(lua_State* L, int idx) { - return Data::Variant(Data::Null()); -} - -// - -IMPL_WRAPPER_CLASS(Bool, bool, "bool") -IMPL_WRAPPER_CLASS(Int, int, "int") -IMPL_WRAPPER_CLASS(Float, float, "float") -IMPL_WRAPPER_CLASS(String, std::string, "string") - -// ToString - -const Data::String Data::Bool::ToString() const { - return Data::String(value ? "true" : "false"); -} - -const Data::String Data::Int::ToString() const { - return Data::String(std::to_string(value)); -} - -const Data::String Data::Float::ToString() const { - std::stringstream stream; - stream << std::noshowpoint << value; - return Data::String(stream.str()); -} - -const Data::String Data::String::ToString() const { - return *this; -} - -// Deserialize - -Data::Variant Data::Bool::Deserialize(pugi::xml_node node) { - return Data::Bool(node.text().as_bool()); -} - -Data::Variant Data::Int::Deserialize(pugi::xml_node node) { - return Data::Int(node.text().as_int()); -} - -Data::Variant Data::Float::Deserialize(pugi::xml_node node) { - return Data::Float(node.text().as_float()); -} - -Data::Variant Data::String::Deserialize(pugi::xml_node node) { - return Data::String(node.text().as_string()); -} - -// FromString - -std::optional Data::Bool::FromString(std::string string) { - return Data::Bool(string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y'); -} - -std::optional Data::Int::FromString(std::string string) { - char* endPos; - int value = (int)std::strtol(string.c_str(), &endPos, 10); - if (endPos == string.c_str()) return std::nullopt; - return Data::Int(value); -} - -std::optional Data::Float::FromString(std::string string) { - char* endPos; - float value = std::strtof(string.c_str(), &endPos); - if (endPos == string.c_str()) return std::nullopt; - return Data::Float(value); -} - -std::optional Data::String::FromString(std::string string) { - return Data::String(string); -} - -// PushLuaValue - -void Data::Bool::PushLuaValue(lua_State* L) const { - lua_pushboolean(L, *this); -} - -void Data::Int::PushLuaValue(lua_State* L) const { - lua_pushinteger(L, *this); -} - -void Data::Float::PushLuaValue(lua_State* L) const { - lua_pushnumber(L, *this); -} - -void Data::String::PushLuaValue(lua_State* L) const { - lua_pushstring(L, value.c_str()); -} - -// FromLuaValue - -result Data::Bool::FromLuaValue(lua_State* L, int idx) { - if (!lua_isboolean(L, idx)) - return LuaCastError(lua_typename(L, idx), "boolean"); - return Data::Variant(Data::Bool(lua_toboolean(L, idx))); -} - -result Data::Int::FromLuaValue(lua_State* L, int idx) { - if (!lua_isnumber(L, idx)) - return LuaCastError(lua_typename(L, idx), "integer"); - return Data::Variant(Data::Int((int)lua_tonumber(L, idx))); -} - -result Data::Float::FromLuaValue(lua_State* L, int idx) { - if (!lua_isnumber(L, idx)) - return LuaCastError(lua_typename(L, idx), "float"); - return Data::Variant(Data::Float((float)lua_tonumber(L, idx))); -} - -result Data::String::FromLuaValue(lua_State* L, int idx) { - if (!lua_tostring(L, idx)) - return LuaCastError(lua_typename(L, idx), "string"); - return Data::Variant(Data::String(lua_tostring(L, idx))); -} \ No newline at end of file diff --git a/core/src/datatypes/base.h b/core/src/datatypes/base.h index 0048f19..8849735 100644 --- a/core/src/datatypes/base.h +++ b/core/src/datatypes/base.h @@ -10,67 +10,20 @@ extern "C" { typedef struct lua_State lua_State; } namespace pugi { class xml_node; }; -#define DEF_WRAPPER_CLASS(CLASS_NAME, WRAPPED_TYPE) class CLASS_NAME : public Data::Base { \ - WRAPPED_TYPE value; \ -public: \ - CLASS_NAME(WRAPPED_TYPE); \ - ~CLASS_NAME(); \ - operator const WRAPPED_TYPE() const; \ - virtual const TypeInfo& GetType() const override; \ - static const TypeInfo TYPE; \ - \ - virtual const Data::String ToString() const override; \ - virtual void Serialize(pugi::xml_node node) const override; \ - virtual void PushLuaValue(lua_State*) const override; \ - \ - static Data::Variant Deserialize(pugi::xml_node node); \ - static std::optional FromString(std::string); \ - static result FromLuaValue(lua_State*, int idx); \ -}; +class Variant; +typedef std::function Serializer; +typedef std::function Deserializer; +typedef std::function ToString; +typedef std::function(std::string)> FromString; +typedef std::function(lua_State*, int idx)> FromLuaValue; +typedef std::function PushLuaValue; -namespace Data { - class Variant; - typedef std::function Deserializer; - typedef std::function(std::string)> FromString; - typedef std::function(lua_State*, int idx)> FromLuaValue; - - struct TypeInfo { - std::string name; - Deserializer deserializer; - FromString fromString; - FromLuaValue fromLuaValue; - }; - - class String; - class Base { - public: - virtual ~Base(); - virtual const TypeInfo& GetType() const = 0; - virtual const Data::String ToString() const = 0; - virtual void Serialize(pugi::xml_node node) const = 0; - virtual void PushLuaValue(lua_State*) const = 0; - }; - - class Null : Base { - public: - Null(); - ~Null(); - virtual const TypeInfo& GetType() const override; - static const TypeInfo TYPE; - - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node node) const override; - virtual void PushLuaValue(lua_State*) const override; - - static Data::Variant Deserialize(pugi::xml_node node); - static result FromLuaValue(lua_State*, int idx); - }; - - DEF_WRAPPER_CLASS(Bool, bool) - DEF_WRAPPER_CLASS(Int, int) - DEF_WRAPPER_CLASS(Float, float) - DEF_WRAPPER_CLASS(String, std::string) -}; - - -#undef DEF_WRAPPER_CLASS \ No newline at end of file +struct TypeInfo { + std::string name; + Serializer serializer; + Deserializer deserializer; + ToString toString; + FromString fromString; + PushLuaValue pushLuaValue; + FromLuaValue fromLuaValue; +}; \ No newline at end of file diff --git a/core/src/datatypes/cframe.cpp b/core/src/datatypes/cframe.cpp index 805f4a2..b4d8be7 100644 --- a/core/src/datatypes/cframe.cpp +++ b/core/src/datatypes/cframe.cpp @@ -6,18 +6,18 @@ #include #include #include -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include #define GLM_ENABLE_EXPERIMENTAL #include -// #include "meta.h" // IWYU pragma: keep +// #include "variant.h" // IWYU pragma: keep -const Data::CFrame Data::CFrame::IDENTITY(glm::vec3(0, 0, 0), glm::mat3(1.f)); -const Data::CFrame Data::CFrame::YToZ(glm::vec3(0, 0, 0), glm::mat3(glm::vec3(1, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, 1, 0))); +const CFrame CFrame::IDENTITY(glm::vec3(0, 0, 0), glm::mat3(1.f)); +const CFrame CFrame::YToZ(glm::vec3(0, 0, 0), glm::mat3(glm::vec3(1, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, 1, 0))); -Data::CFrame::CFrame() : Data::CFrame::CFrame(glm::vec3(0, 0, 0), glm::mat3(1.f)) {} +CFrame::CFrame() : CFrame::CFrame(glm::vec3(0, 0, 0), glm::mat3(1.f)) {} -Data::CFrame::CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22) +CFrame::CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22) : translation(x, y, z) , rotation({ // { R00, R01, R02 }, @@ -29,17 +29,17 @@ Data::CFrame::CFrame(float x, float y, float z, float R00, float R01, float R02, }) { } -Data::CFrame::CFrame(glm::vec3 translation, glm::mat3 rotation) +CFrame::CFrame(glm::vec3 translation, glm::mat3 rotation) : translation(translation) , rotation(rotation) { } -Data::CFrame::CFrame(Vector3 position, glm::quat quat) +CFrame::CFrame(Vector3 position, glm::quat quat) : translation(position) , rotation(quat) { } -Data::CFrame::CFrame(const rp::Transform& transform) : Data::CFrame::CFrame(rpToGlm(transform.getPosition()), rpToGlm(transform.getOrientation())) { +CFrame::CFrame(const rp::Transform& transform) : CFrame::CFrame(rpToGlm(transform.getPosition()), rpToGlm(transform.getOrientation())) { } glm::mat3 lookAt(Vector3 position, Vector3 lookAt, Vector3 up) { @@ -52,35 +52,35 @@ glm::mat3 lookAt(Vector3 position, Vector3 lookAt, Vector3 up) { return { s, u, -f }; } -Data::CFrame::CFrame(Vector3 position, Vector3 lookAt, Vector3 up) +CFrame::CFrame(Vector3 position, Vector3 lookAt, Vector3 up) : translation(position) , rotation(::lookAt(position, lookAt, up)) { } -Data::CFrame::~CFrame() = default; +CFrame::~CFrame() = default; -const Data::String Data::CFrame::ToString() const { +const std::string CFrame::ToString() const { return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z()); } -Data::CFrame Data::CFrame::pointToward(Vector3 position, Vector3 toward) { - return Data::CFrame(position, position + toward, (abs(toward.Dot(Vector3(0, 1, 0))) > 0.999) ? Vector3(0, 0, 1) : Vector3(0, 1, 0)); +CFrame CFrame::pointToward(Vector3 position, Vector3 toward) { + return CFrame(position, position + toward, (abs(toward.Dot(Vector3(0, 1, 0))) > 0.999) ? Vector3(0, 0, 1) : Vector3(0, 1, 0)); } -Data::CFrame Data::CFrame::pointAligned(Vector3 position, Vector3 toward, Vector3 up, Vector3 right) { - return Data::CFrame(position, position + toward, (abs(toward.Dot(up)) > 0.999) ? right : up); +CFrame CFrame::pointAligned(Vector3 position, Vector3 toward, Vector3 up, Vector3 right) { + return CFrame(position, position + toward, (abs(toward.Dot(up)) > 0.999) ? right : up); } -Data::CFrame::operator glm::mat4() const { +CFrame::operator glm::mat4() const { // Always make sure to translate the position first, then rotate. Matrices work backwards return glm::translate(glm::mat4(1.0f), this->translation) * glm::mat4(this->rotation); } -Data::CFrame::operator rp::Transform() const { +CFrame::operator rp::Transform() const { return rp::Transform(glmToRp(translation), glmToRp(rotation)); } -Vector3 Data::CFrame::ToEulerAnglesXYZ() { +Vector3 CFrame::ToEulerAnglesXYZ() { float x; float y; float z; @@ -88,37 +88,37 @@ Vector3 Data::CFrame::ToEulerAnglesXYZ() { return Vector3(x, y, z); } -Data::CFrame Data::CFrame::FromEulerAnglesXYZ(Vector3 vector) { +CFrame CFrame::FromEulerAnglesXYZ(Vector3 vector) { glm::mat3 mat = glm::eulerAngleXYZ(vector.X(), vector.Y(), vector.Z()); - return Data::CFrame((glm::vec3)Vector3::ZERO, mat); + return CFrame((glm::vec3)Vector3::ZERO, mat); } -Data::CFrame Data::CFrame::Inverse() const { +CFrame CFrame::Inverse() const { return CFrame { -translation * glm::transpose(glm::inverse(rotation)), glm::inverse(rotation) }; } // Operators -Data::CFrame Data::CFrame::operator *(Data::CFrame otherFrame) const { +CFrame CFrame::operator *(CFrame otherFrame) const { return CFrame { this->translation + this->rotation * otherFrame.translation, this->rotation * otherFrame.rotation }; } -Vector3 Data::CFrame::operator *(Vector3 vector) const { +Vector3 CFrame::operator *(Vector3 vector) const { return this->translation + this->rotation * vector; } -Data::CFrame Data::CFrame::operator +(Vector3 vector) const { +CFrame CFrame::operator +(Vector3 vector) const { return CFrame { this->translation + glm::vec3(vector), this->rotation }; } -Data::CFrame Data::CFrame::operator -(Vector3 vector) const { +CFrame CFrame::operator -(Vector3 vector) const { return *this + -vector; } // Serialization -void Data::CFrame::Serialize(pugi::xml_node node) const { +void CFrame::Serialize(pugi::xml_node node) const { node.append_child("X").text().set(std::to_string(this->X())); node.append_child("Y").text().set(std::to_string(this->Y())); node.append_child("Z").text().set(std::to_string(this->Z())); @@ -134,8 +134,8 @@ void Data::CFrame::Serialize(pugi::xml_node node) const { } -Data::Variant Data::CFrame::Deserialize(pugi::xml_node node) { - return Data::CFrame( +Variant CFrame::Deserialize(pugi::xml_node node) { + return CFrame( node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float(), diff --git a/core/src/datatypes/cframe.h b/core/src/datatypes/cframe.h index 4871707..46311e7 100644 --- a/core/src/datatypes/cframe.h +++ b/core/src/datatypes/cframe.h @@ -9,66 +9,62 @@ namespace reactphysics3d { class Transform; }; -namespace Data { - class DEF_DATA_(name="CoordinateFrame") CFrame : public Base { - AUTOGEN_PREAMBLE_DATA +class DEF_DATA_(name="CoordinateFrame") CFrame { + AUTOGEN_PREAMBLE_DATA - glm::vec3 translation; - glm::mat3 rotation; - - CFrame(glm::vec3, glm::mat3); - public: - // CFrame(float x, float y, float z); - // CFrame(const glm::vec3&); - // CFrame(const rp::Vector3&); - DEF_DATA_CTOR CFrame(); - DEF_DATA_CTOR CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22); - DEF_DATA_CTOR CFrame(Vector3 , Vector3 lookAt, Vector3 up = Vector3(0, 1, 0)); - CFrame(const reactphysics3d::Transform&); - CFrame(Vector3 position, glm::quat quat); - ~CFrame(); + glm::vec3 translation; + glm::mat3 rotation; - // Same as CFrame(position, position + toward), but makes sure that up and toward are not linearly dependant - static CFrame pointToward(Vector3 position, Vector3 toward); - // Creates a cframe looking at position + toward, whilst aligning its up to up. - // If up and toward are approximately linearly dependent (their absolute dot product > 0.999), - // then the right is used instead - // Up and right must NOT be linearly dependent - static CFrame pointAligned(Vector3 position, Vector3 toward, Vector3 up, Vector3 right); + CFrame(glm::vec3, glm::mat3); +public: + // CFrame(float x, float y, float z); + // CFrame(const glm::vec3&); + // CFrame(const rp::Vector3&); + DEF_DATA_CTOR CFrame(); + DEF_DATA_CTOR CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22); + DEF_DATA_CTOR CFrame(Vector3 , Vector3 lookAt, Vector3 up = Vector3(0, 1, 0)); + CFrame(const reactphysics3d::Transform&); + CFrame(Vector3 position, glm::quat quat); + ~CFrame(); - DEF_DATA_PROP static const CFrame IDENTITY; - static const CFrame YToZ; + // Same as CFrame(position, position + toward), but makes sure that up and toward are not linearly dependant + static CFrame pointToward(Vector3 position, Vector3 toward); + // Creates a cframe looking at position + toward, whilst aligning its up to up. + // If up and toward are approximately linearly dependent (their absolute dot product > 0.999), + // then the right is used instead + // Up and right must NOT be linearly dependent + static CFrame pointAligned(Vector3 position, Vector3 toward, Vector3 up, Vector3 right); - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node parent) const override; - static Data::Variant Deserialize(pugi::xml_node node); + DEF_DATA_PROP static const CFrame IDENTITY; + static const CFrame YToZ; - static void PushLuaLibrary(lua_State*); + virtual const std::string ToString() const; + virtual void Serialize(pugi::xml_node parent) const; + static Variant Deserialize(pugi::xml_node node); - operator glm::mat4() const; - operator reactphysics3d::Transform() const; + static void PushLuaLibrary(lua_State*); - //inline static CFrame identity() { } - DEF_DATA_PROP inline Vector3 Position() const { return translation; } - DEF_DATA_PROP inline CFrame Rotation() const { return CFrame { glm::vec3(0, 0, 0), rotation }; } - DEF_DATA_METHOD CFrame Inverse() const; - DEF_DATA_PROP inline float X() const { return translation.x; } - DEF_DATA_PROP inline float Y() const { return translation.y; } - DEF_DATA_PROP inline float Z() const { return translation.z; } + operator glm::mat4() const; + operator reactphysics3d::Transform() const; - DEF_DATA_PROP inline Vector3 RightVector() { return glm::column(rotation, 0); } - DEF_DATA_PROP inline Vector3 UpVector() { return glm::column(rotation, 1); } - DEF_DATA_PROP inline Vector3 LookVector() { return -glm::column(rotation, 2); } + //inline static CFrame identity() { } + DEF_DATA_PROP inline Vector3 Position() const { return translation; } + DEF_DATA_PROP inline CFrame Rotation() const { return CFrame { glm::vec3(0, 0, 0), rotation }; } + DEF_DATA_METHOD CFrame Inverse() const; + DEF_DATA_PROP inline float X() const { return translation.x; } + DEF_DATA_PROP inline float Y() const { return translation.y; } + DEF_DATA_PROP inline float Z() const { return translation.z; } - DEF_DATA_METHOD Vector3 ToEulerAnglesXYZ(); - DEF_DATA_METHOD static CFrame FromEulerAnglesXYZ(Vector3); + DEF_DATA_PROP inline Vector3 RightVector() { return glm::column(rotation, 0); } + DEF_DATA_PROP inline Vector3 UpVector() { return glm::column(rotation, 1); } + DEF_DATA_PROP inline Vector3 LookVector() { return -glm::column(rotation, 2); } - // Operators - DEF_DATA_OP Data::CFrame operator *(Data::CFrame) const; - DEF_DATA_OP Vector3 operator *(Vector3) const; - DEF_DATA_OP Data::CFrame operator +(Vector3) const; - DEF_DATA_OP Data::CFrame operator -(Vector3) const; - }; -} + DEF_DATA_METHOD Vector3 ToEulerAnglesXYZ(); + DEF_DATA_METHOD static CFrame FromEulerAnglesXYZ(Vector3); -using Data::CFrame; \ No newline at end of file + // Operators + DEF_DATA_OP CFrame operator *(CFrame) const; + DEF_DATA_OP Vector3 operator *(Vector3) const; + DEF_DATA_OP CFrame operator +(Vector3) const; + DEF_DATA_OP CFrame operator -(Vector3) const; +}; \ No newline at end of file diff --git a/core/src/datatypes/color3.cpp b/core/src/datatypes/color3.cpp index 17ae46d..d612369 100644 --- a/core/src/datatypes/color3.cpp +++ b/core/src/datatypes/color3.cpp @@ -1,21 +1,21 @@ #include "color3.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include #include #include -Data::Color3::Color3(float r, float g, float b) : r(std::clamp(r, 0.f, 1.f)), g(std::clamp(g, 0.f, 1.f)), b(std::clamp(b, 0.f, 1.f)) {}; -Data::Color3::Color3(const glm::vec3& vec) : r(std::clamp(vec.x, 0.f, 1.f)), g(std::clamp(vec.y, 0.f, 1.f)), b(std::clamp(vec.z, 0.f, 1.f)) {}; +Color3::Color3(float r, float g, float b) : r(std::clamp(r, 0.f, 1.f)), g(std::clamp(g, 0.f, 1.f)), b(std::clamp(b, 0.f, 1.f)) {}; +Color3::Color3(const glm::vec3& vec) : r(std::clamp(vec.x, 0.f, 1.f)), g(std::clamp(vec.y, 0.f, 1.f)), b(std::clamp(vec.z, 0.f, 1.f)) {}; -Data::Color3::~Color3() = default; +Color3::~Color3() = default; -const Data::String Data::Color3::ToString() const { +const std::string Color3::ToString() const { return std::to_string(int(r*256)) + ", " + std::to_string(int(g*256)) + ", " + std::to_string(int(b*256)); } -Data::Color3::operator glm::vec3() const { return glm::vec3(r, g, b); }; +Color3::operator glm::vec3() const { return glm::vec3(r, g, b); }; -std::string Data::Color3::ToHex() const { +std::string Color3::ToHex() const { std::stringstream ss; ss << "FF" << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << int(r*255) @@ -25,7 +25,7 @@ std::string Data::Color3::ToHex() const { } -Data::Color3 Data::Color3::FromHex(std::string hex) { +Color3 Color3::FromHex(std::string hex) { float r = float(std::stoi(hex.substr(2, 2), nullptr, 16)) / 255; float g = float(std::stoi(hex.substr(4, 2), nullptr, 16)) / 255; float b = float(std::stoi(hex.substr(6, 2), nullptr, 16)) / 255; @@ -35,10 +35,10 @@ Data::Color3 Data::Color3::FromHex(std::string hex) { // Serialization -void Data::Color3::Serialize(pugi::xml_node node) const { +void Color3::Serialize(pugi::xml_node node) const { node.text().set(this->ToHex()); } -Data::Variant Data::Color3::Deserialize(pugi::xml_node node) { +Variant 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 f9fcb12..545b9b5 100644 --- a/core/src/datatypes/color3.h +++ b/core/src/datatypes/color3.h @@ -4,34 +4,30 @@ #include "datatypes/annotation.h" #include -namespace Data { - class DEF_DATA Color3 : public Base { - AUTOGEN_PREAMBLE_DATA +class DEF_DATA Color3 { + AUTOGEN_PREAMBLE_DATA - float r; - float g; - float b; - - public: - DEF_DATA_CTOR Color3(float r, float g, float b); - Color3(const glm::vec3&); - ~Color3(); + float r; + float g; + float b; - DEF_DATA_METHOD static Color3 FromHex(std::string hex); +public: + DEF_DATA_CTOR Color3(float r, float g, float b); + Color3(const glm::vec3&); + ~Color3(); - virtual const Data::String ToString() const override; - DEF_DATA_METHOD std::string ToHex() const; - virtual void Serialize(pugi::xml_node node) const override; - static Data::Variant Deserialize(pugi::xml_node node); + DEF_DATA_METHOD static Color3 FromHex(std::string hex); - static void PushLuaLibrary(lua_State*); + 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); - operator glm::vec3() const; + static void PushLuaLibrary(lua_State*); - DEF_DATA_PROP inline float R() const { return r; } - DEF_DATA_PROP inline float G() const { return g; } - DEF_DATA_PROP inline float B() const { return b; } - }; -} + operator glm::vec3() const; -using Data::Color3; \ No newline at end of file + DEF_DATA_PROP inline float R() const { return r; } + DEF_DATA_PROP inline float G() const { return g; } + DEF_DATA_PROP inline float B() const { return b; } +}; \ No newline at end of file diff --git a/core/src/datatypes/meta.cpp b/core/src/datatypes/meta.cpp deleted file mode 100644 index 35aba4d..0000000 --- a/core/src/datatypes/meta.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "meta.h" -#include "datatypes/base.h" -#include "datatypes/cframe.h" -#include "datatypes/ref.h" -#include "logger.h" -#include "panic.h" -#include -#include - -Data::String Data::Variant::ToString() const { - return std::visit([](auto&& it) { - return it.ToString(); - }, this->wrapped); -} - -void Data::Variant::Serialize(pugi::xml_node node) const { - std::visit([&](auto&& it) { - it.Serialize(node); - }, this->wrapped); -} - -void Data::Variant::PushLuaValue(lua_State* state) const { - return std::visit([&](auto&& it) { - return it.PushLuaValue(state); - }, this->wrapped); -} - -Data::Variant Data::Variant::Deserialize(pugi::xml_node node) { - if (Data::TYPE_MAP.count(node.name()) == 0) { - Logger::fatalErrorf("Unknown type for property: '%s'", node.name()); - panic(); - } - - const Data::TypeInfo* type = Data::TYPE_MAP[node.name()]; - return type->deserializer(node); -} - -std::map Data::TYPE_MAP = { - { "null", &Data::Null::TYPE }, - { "bool", &Data::Bool::TYPE }, - { "int", &Data::Int::TYPE }, - { "float", &Data::Float::TYPE }, - { "string", &Data::String::TYPE }, - { "Vector3", &Data::Vector3::TYPE }, - { "CoordinateFrame", &Data::CFrame::TYPE }, - { "Color3", &Data::Color3::TYPE }, - { "Ref", &Data::InstanceRef::TYPE }, -}; \ No newline at end of file diff --git a/core/src/datatypes/meta.h b/core/src/datatypes/meta.h deleted file mode 100644 index f897000..0000000 --- a/core/src/datatypes/meta.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include -#include "base.h" -#include "datatypes/color3.h" -#include "datatypes/ref.h" -#include "datatypes/signal.h" -#include "vector.h" -#include "cframe.h" - -// #define __VARIANT_TYPE std::variant< \ -// Null, \ -// Bool, \ -// Int, \ -// Float, \ -// String \ -// > - -namespace Data { - typedef std::variant< - Null, - Bool, - Int, - Float, - String, - Vector3, - CFrame, - Color3, - InstanceRef, - SignalRef, - SignalConnectionRef - > __VARIANT_TYPE; - - class Variant { - __VARIANT_TYPE wrapped; - public: - template Variant(T obj) : wrapped(obj) {} - template T get() { return std::get(wrapped); } - Data::String ToString() const; - - void Serialize(pugi::xml_node node) const; - void PushLuaValue(lua_State* state) const; - static Data::Variant Deserialize(pugi::xml_node node); - }; - - // 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/primitives.cpp b/core/src/datatypes/primitives.cpp new file mode 100644 index 0000000..067ebf5 --- /dev/null +++ b/core/src/datatypes/primitives.cpp @@ -0,0 +1,211 @@ +#include "primitives.h" +#include "variant.h" +#include +#include "lua.h" +#include + +// null + +void Null_Serialize(Variant self, pugi::xml_node node) { + node.text().set("null"); +} + +Variant Null_Deserialize(pugi::xml_node node) { + return std::monostate(); +} + +const std::string Null_ToString(Variant self) { + return "null"; +} + +const std::optional Null_FromString(std::string str) { + return std::monostate(); +} + +void Null_PushLuaValue(Variant self, lua_State* L) { + lua_pushnil(L); +} + +result Null_FromLuaValue(lua_State* L, int idx) { + return Variant(std::monostate()); +} + +const TypeInfo NULL_TYPE { + "null", + Null_Serialize, + Null_Deserialize, + Null_ToString, + Null_FromString, + Null_PushLuaValue, + Null_FromLuaValue, +}; + +// /null + +// bool + +void Bool_Serialize(Variant self, pugi::xml_node node) { + node.text().set(self.get() ? "true" : "false"); +} + +Variant Bool_Deserialize(pugi::xml_node node) { + return node.text().as_bool(); +} + +const std::string Bool_ToString(Variant self) { + return self.get() ? "true" : "false"; +} + +const std::optional Bool_FromString(std::string string) { + return string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y'; +} + +void Bool_PushLuaValue(Variant self, lua_State* L) { + lua_pushboolean(L, self.get()); +} + +result Bool_FromLuaValue(lua_State* L, int idx) { + if (!lua_isboolean(L, idx)) + return LuaCastError(lua_typename(L, idx), "boolean"); + return Variant(lua_toboolean(L, idx)); +} + +const TypeInfo BOOL_TYPE { + "bool", + Bool_Serialize, + Bool_Deserialize, + Bool_ToString, + Bool_FromString, + Bool_PushLuaValue, + Bool_FromLuaValue, +}; + +// /bool + +// int + +void Int_Serialize(Variant self, pugi::xml_node node) { + node.text().set(self.get()); +} + +Variant Int_Deserialize(pugi::xml_node node) { + return node.text().as_int(); +} + +const std::string Int_ToString(Variant self) { + return std::to_string(self.get()); +} + +const std::optional Int_FromString(std::string string) { + char* endPos; + int value = (int)std::strtol(string.c_str(), &endPos, 10); + if (endPos == string.c_str()) return std::nullopt; + return value; +} + +void Int_PushLuaValue(Variant self, lua_State* L) { + lua_pushinteger(L, self.get()); +} + +result Int_FromLuaValue(lua_State* L, int idx) { + if (!lua_isnumber(L, idx)) + return LuaCastError(lua_typename(L, idx), "integer"); + return Variant((int)lua_tonumber(L, idx)); +} + +const TypeInfo INT_TYPE { + "int", + Int_Serialize, + Int_Deserialize, + Int_ToString, + Int_FromString, + Int_PushLuaValue, + Int_FromLuaValue, +}; + +// /int + +// float + +void Float_Serialize(Variant self, pugi::xml_node node) { + node.text().set(self.get()); +} + +Variant Float_Deserialize(pugi::xml_node node) { + return node.text().as_float(); +} + +const std::string Float_ToString(Variant self) { + std::stringstream stream; + stream << std::noshowpoint << self.get(); + return stream.str(); +} + +const std::optional Float_FromString(std::string string) { + char* endPos; + float value = std::strtof(string.c_str(), &endPos); + if (endPos == string.c_str()) return std::nullopt; + return value; +} + +void Float_PushLuaValue(Variant self, lua_State* L) { + lua_pushnumber(L, self.get()); +} + +result Float_FromLuaValue(lua_State* L, int idx) { + if (!lua_isnumber(L, idx)) + return LuaCastError(lua_typename(L, idx), "float"); + return Variant((float)lua_tonumber(L, idx)); +} + +const TypeInfo FLOAT_TYPE { + "float", + Float_Serialize, + Float_Deserialize, + Float_ToString, + Float_FromString, + Float_PushLuaValue, + Float_FromLuaValue, +}; + +// /float + +// string + +void String_Serialize(Variant self, pugi::xml_node node) { + node.text().set(self.get()); +} + +Variant String_Deserialize(pugi::xml_node node) { + return node.text().as_string(); +} + +const std::string String_ToString(Variant self) { + return self.get(); +} + +const std::optional String_FromString(std::string string) { + return string; +} + +void String_PushLuaValue(Variant self, lua_State* L) { + lua_pushstring(L, self.get().c_str()); +} + +result String_FromLuaValue(lua_State* L, int idx) { + if (!lua_tostring(L, idx)) + return LuaCastError(lua_typename(L, idx), "string"); + return Variant(lua_tostring(L, idx)); +} + +const TypeInfo STRING_TYPE { + "string", + String_Serialize, + String_Deserialize, + String_ToString, + String_FromString, + String_PushLuaValue, + String_FromLuaValue, +}; + +// /string \ No newline at end of file diff --git a/core/src/datatypes/primitives.h b/core/src/datatypes/primitives.h new file mode 100644 index 0000000..8182e85 --- /dev/null +++ b/core/src/datatypes/primitives.h @@ -0,0 +1,9 @@ +#pragma once + +#include "base.h" + +extern const TypeInfo NULL_TYPE; +extern const TypeInfo BOOL_TYPE; +extern const TypeInfo INT_TYPE; +extern const TypeInfo FLOAT_TYPE; +extern const TypeInfo STRING_TYPE; \ No newline at end of file diff --git a/core/src/datatypes/ref.cpp b/core/src/datatypes/ref.cpp index 9fcb054..d50fd57 100644 --- a/core/src/datatypes/ref.cpp +++ b/core/src/datatypes/ref.cpp @@ -2,7 +2,7 @@ #include "datatypes/base.h" #include "error/data.h" #include "logger.h" -#include "meta.h" // IWYU pragma: keep +#include "variant.h" // IWYU pragma: keep #include #include #include "objects/base/instance.h" @@ -10,34 +10,36 @@ #include "objects/base/member.h" #include -Data::InstanceRef::InstanceRef() {}; -Data::InstanceRef::InstanceRef(std::weak_ptr instance) : ref(instance) {}; -Data::InstanceRef::~InstanceRef() = default; +InstanceRef::InstanceRef() {}; +InstanceRef::InstanceRef(std::weak_ptr instance) : ref(instance) {}; +InstanceRef::~InstanceRef() = default; -const Data::TypeInfo Data::InstanceRef::TYPE = { +const TypeInfo InstanceRef::TYPE = { .name = "Ref", - .deserializer = &Data::InstanceRef::Deserialize, - .fromLuaValue = &Data::InstanceRef::FromLuaValue, + .serializer = toVariantFunction(&InstanceRef::Serialize), + .deserializer = &InstanceRef::Deserialize, + .toString = toVariantFunction(&InstanceRef::ToString), + .fromString = nullptr, + .pushLuaValue = toVariantFunction(&InstanceRef::PushLuaValue), + .fromLuaValue = &InstanceRef::FromLuaValue, }; -const Data::TypeInfo& Data::InstanceRef::GetType() const { return Data::InstanceRef::TYPE; }; - -const Data::String Data::InstanceRef::ToString() const { +const std::string InstanceRef::ToString() const { return ref.expired() ? "" : ref.lock()->name; } -Data::InstanceRef::operator std::weak_ptr() { +InstanceRef::operator std::weak_ptr() { return ref; } // Serialization -void Data::InstanceRef::Serialize(pugi::xml_node node) const { +void InstanceRef::Serialize(pugi::xml_node node) const { // Handled by Instance panic(); } -Data::Variant Data::InstanceRef::Deserialize(pugi::xml_node node) { +Variant InstanceRef::Deserialize(pugi::xml_node node) { // Handled by Instance panic(); } @@ -52,7 +54,7 @@ static const struct luaL_Reg metatable [] = { {NULL, NULL} /* end of array */ }; -void Data::InstanceRef::PushLuaValue(lua_State* L) const { +void InstanceRef::PushLuaValue(lua_State* L) const { if (ref.expired()) return lua_pushnil(L); int n = lua_gettop(L); @@ -70,14 +72,14 @@ void Data::InstanceRef::PushLuaValue(lua_State* L) const { lua_setmetatable(L, n+1); } -result Data::InstanceRef::FromLuaValue(lua_State* L, int idx) { +result InstanceRef::FromLuaValue(lua_State* L, int idx) { if (lua_isnil(L, idx)) - return Data::Variant(Data::InstanceRef()); + return Variant(InstanceRef()); if (!lua_isuserdata(L, idx)) return LuaCastError(lua_typename(L, idx), "Instance"); // TODO: overhaul this to support other types auto userdata = (std::shared_ptr**)lua_touserdata(L, idx); - return Data::Variant(Data::InstanceRef(**userdata)); + return Variant(InstanceRef(**userdata)); } static int inst_gc(lua_State* L) { @@ -99,7 +101,7 @@ static int inst_index(lua_State* L) { // Read property std::optional meta = inst->GetPropertyMeta(key); if (meta) { - Data::Variant value = inst->GetPropertyValue(key).expect(); + Variant value = inst->GetPropertyValue(key).expect(); value.PushLuaValue(L); return 1; } @@ -107,7 +109,7 @@ static int inst_index(lua_State* L) { // Look for child std::optional> child = inst->FindFirstChild(key); if (child) { - Data::InstanceRef(child.value()).PushLuaValue(L); + InstanceRef(child.value()).PushLuaValue(L); return 1; } @@ -129,7 +131,7 @@ static int inst_newindex(lua_State* L) { if (key == "Parent" && inst->IsParentLocked()) return luaL_error(L, "Cannot set property Parent (%s) of %s, parent is locked", inst->GetParent() ? inst->GetParent().value()->name.c_str() : "NULL", inst->GetClass()->className.c_str()); - result value = meta->type->fromLuaValue(L, -1); + result value = meta->type->fromLuaValue(L, -1); lua_pop(L, 3); if (value.isError()) diff --git a/core/src/datatypes/ref.h b/core/src/datatypes/ref.h index fbcbe15..05e82bb 100644 --- a/core/src/datatypes/ref.h +++ b/core/src/datatypes/ref.h @@ -6,23 +6,20 @@ class Instance; -namespace Data { - class InstanceRef : public Base { - std::weak_ptr ref; - public: - InstanceRef(); - InstanceRef(std::weak_ptr); - ~InstanceRef(); +class InstanceRef { + std::weak_ptr ref; +public: + InstanceRef(); + InstanceRef(std::weak_ptr); + ~InstanceRef(); - virtual const TypeInfo& GetType() const override; - static const TypeInfo TYPE; + static const TypeInfo TYPE; - operator std::weak_ptr(); + operator std::weak_ptr(); - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node node) const override; - virtual void PushLuaValue(lua_State*) const override; - static Data::Variant Deserialize(pugi::xml_node node); - static result FromLuaValue(lua_State*, int idx); - }; -} + 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 result FromLuaValue(lua_State*, int idx); +}; \ No newline at end of file diff --git a/core/src/datatypes/signal.cpp b/core/src/datatypes/signal.cpp index e0ae5ca..74b7924 100644 --- a/core/src/datatypes/signal.cpp +++ b/core/src/datatypes/signal.cpp @@ -1,6 +1,6 @@ #include "signal.h" #include "datatypes/base.h" -#include "meta.h" +#include "variant.h" #include "lua.h" #include #include @@ -53,13 +53,13 @@ static void stackdump(lua_State* L) { fflush(stdout); } -void LuaSignalConnection::Call(std::vector args) { +void LuaSignalConnection::Call(std::vector args) { lua_State* thread = lua_newthread(state); // Push function lua_rawgeti(thread, LUA_REGISTRYINDEX, function); - for (Data::Variant arg : args) { + for (Variant arg : args) { arg.PushLuaValue(thread); } @@ -74,11 +74,11 @@ void LuaSignalConnection::Call(std::vector args) { // -CSignalConnection::CSignalConnection(std::function)> func, std::weak_ptr parent) : SignalConnection(parent) { +CSignalConnection::CSignalConnection(std::function)> func, std::weak_ptr parent) : SignalConnection(parent) { this->function = func; } -void CSignalConnection::Call(std::vector args) { +void CSignalConnection::Call(std::vector args) { function(args); } @@ -86,7 +86,7 @@ void CSignalConnection::Call(std::vector args) { SignalConnectionHolder::SignalConnectionHolder() : heldConnection() {} SignalConnectionHolder::SignalConnectionHolder(std::shared_ptr connection) : heldConnection(connection) {} -SignalConnectionHolder::SignalConnectionHolder(Data::SignalConnectionRef other) : heldConnection(other) {} +SignalConnectionHolder::SignalConnectionHolder(SignalConnectionRef other) : heldConnection(other) {} SignalConnectionHolder::~SignalConnectionHolder() { // printf("Prediscon!\n"); @@ -97,7 +97,7 @@ SignalConnectionHolder::~SignalConnectionHolder() { // -SignalConnectionRef Signal::Connect(std::function)> callback) { +SignalConnectionRef Signal::Connect(std::function)> callback) { auto conn = std::dynamic_pointer_cast(std::make_shared(callback, weak_from_this())); connections.push_back(conn); return SignalConnectionRef(conn); @@ -109,7 +109,7 @@ SignalConnectionRef Signal::Connect(lua_State* state) { return SignalConnectionRef(conn); } -SignalConnectionRef Signal::Once(std::function)> callback) { +SignalConnectionRef Signal::Once(std::function)> callback) { auto conn = std::dynamic_pointer_cast(std::make_shared(callback, weak_from_this())); onceConnections.push_back(conn); return SignalConnectionRef(conn); @@ -132,7 +132,7 @@ int Signal::Wait(lua_State* thread) { return lua_yield(thread, 0); } -void Signal::Fire(std::vector args) { +void Signal::Fire(std::vector args) { for (std::shared_ptr connection : connections) { connection->Call(args); } @@ -148,7 +148,7 @@ void Signal::Fire(std::vector args) { auto prevThreads = std::move(waitingThreads); waitingThreads = std::vector>(); for (auto& [threadId, thread] : prevThreads) { - for (Data::Variant arg : args) { + for (Variant arg : args) { arg.PushLuaValue(thread); } @@ -165,7 +165,7 @@ void Signal::Fire(std::vector args) { } void Signal::Fire() { - return Fire(std::vector {}); + return Fire(std::vector {}); } void Signal::DisconnectAll() { @@ -222,29 +222,27 @@ static const struct luaL_Reg signal_metatable [] = { {NULL, NULL} /* end of array */ }; -Data::SignalRef::SignalRef(std::weak_ptr ref) : signal(ref) {} -Data::SignalRef::~SignalRef() = default; +SignalRef::SignalRef(std::weak_ptr ref) : signal(ref) {} +SignalRef::~SignalRef() = default; -const Data::TypeInfo Data::SignalRef::TYPE = { +const TypeInfo SignalRef::TYPE = { .name = "Signal", - .fromLuaValue = &Data::SignalRef::FromLuaValue, + .fromLuaValue = &SignalRef::FromLuaValue, }; -const Data::TypeInfo& Data::SignalRef::GetType() const { return Data::SignalRef::TYPE; }; - -const Data::String Data::SignalRef::ToString() const { - return Data::String("Signal"); +const std::string SignalRef::ToString() const { + return "Signal"; } -Data::SignalRef::operator std::weak_ptr() { +SignalRef::operator std::weak_ptr() { return signal; } -void Data::SignalRef::Serialize(pugi::xml_node node) const { +void SignalRef::Serialize(pugi::xml_node node) const { // Not serializable } -void Data::SignalRef::PushLuaValue(lua_State* L) const { +void SignalRef::PushLuaValue(lua_State* L) const { int n = lua_gettop(L); auto userdata = (std::weak_ptr**)lua_newuserdata(L, sizeof(std::weak_ptr)); @@ -257,10 +255,10 @@ void Data::SignalRef::PushLuaValue(lua_State* L) const { lua_setmetatable(L, n+1); } -result Data::SignalRef::FromLuaValue(lua_State* L, int idx) { +result SignalRef::FromLuaValue(lua_State* L, int idx) { auto userdata = (std::weak_ptr**)luaL_checkudata(L, 1, "__mt_signal"); lua_pop(L, 1); - return Data::Variant(Data::SignalRef(**userdata)); + return Variant(SignalRef(**userdata)); } static int signal_gc(lua_State* L) { @@ -343,29 +341,27 @@ static const struct luaL_Reg signalconnection_metatable [] = { {NULL, NULL} /* end of array */ }; -Data::SignalConnectionRef::SignalConnectionRef(std::weak_ptr ref) : signalConnection(ref) {} -Data::SignalConnectionRef::~SignalConnectionRef() = default; +SignalConnectionRef::SignalConnectionRef(std::weak_ptr ref) : signalConnection(ref) {} +SignalConnectionRef::~SignalConnectionRef() = default; -const Data::TypeInfo Data::SignalConnectionRef::TYPE = { +const TypeInfo SignalConnectionRef::TYPE = { .name = "Signal", - .fromLuaValue = &Data::SignalConnectionRef::FromLuaValue, + .fromLuaValue = &SignalConnectionRef::FromLuaValue, }; -const Data::TypeInfo& Data::SignalConnectionRef::GetType() const { return Data::SignalConnectionRef::TYPE; }; - -const Data::String Data::SignalConnectionRef::ToString() const { - return Data::String("Connection"); +const std::string SignalConnectionRef::ToString() const { + return "Connection"; } -Data::SignalConnectionRef::operator std::weak_ptr() { +SignalConnectionRef::operator std::weak_ptr() { return signalConnection; } -void Data::SignalConnectionRef::Serialize(pugi::xml_node node) const { +void SignalConnectionRef::Serialize(pugi::xml_node node) const { // Not serializable } -void Data::SignalConnectionRef::PushLuaValue(lua_State* L) const { +void SignalConnectionRef::PushLuaValue(lua_State* L) const { int n = lua_gettop(L); auto userdata = (std::weak_ptr**)lua_newuserdata(L, sizeof(std::weak_ptr)); @@ -378,10 +374,10 @@ void Data::SignalConnectionRef::PushLuaValue(lua_State* L) const { lua_setmetatable(L, n+1); } -result Data::SignalConnectionRef::FromLuaValue(lua_State* L, int idx) { +result SignalConnectionRef::FromLuaValue(lua_State* L, int idx) { auto userdata = (std::weak_ptr**)luaL_checkudata(L, 1, "__mt_signalconnection"); lua_pop(L, 1); - return Data::Variant(Data::SignalConnectionRef(**userdata)); + return Variant(SignalConnectionRef(**userdata)); } static int signalconnection_tostring(lua_State* L) { diff --git a/core/src/datatypes/signal.h b/core/src/datatypes/signal.h index 5b23652..14a6723 100644 --- a/core/src/datatypes/signal.h +++ b/core/src/datatypes/signal.h @@ -15,7 +15,7 @@ class Instance; class Signal; -namespace Data { class SignalConnectionRef; } +class SignalConnectionRef; class SignalConnection : public std::enable_shared_from_this { protected: @@ -23,7 +23,7 @@ protected: SignalConnection(std::weak_ptr parent); - virtual void Call(std::vector) = 0; + virtual void Call(std::vector) = 0; friend Signal; public: inline bool Connected() { return !parentSignal.expired(); }; @@ -33,13 +33,13 @@ public: }; class CSignalConnection : public SignalConnection { - std::function)> function; + std::function)> function; friend Signal; protected: - void Call(std::vector) override; + void Call(std::vector) override; public: - CSignalConnection(std::function)>, std::weak_ptr parent); + CSignalConnection(std::function)>, std::weak_ptr parent); }; class LuaSignalConnection : public SignalConnection { @@ -48,7 +48,7 @@ class LuaSignalConnection : public SignalConnection { friend Signal; protected: - void Call(std::vector) override; + void Call(std::vector) override; public: LuaSignalConnection(lua_State*, std::weak_ptr parent); LuaSignalConnection (const LuaSignalConnection&) = delete; @@ -63,7 +63,7 @@ class SignalConnectionHolder { public: SignalConnectionHolder(); SignalConnectionHolder(std::shared_ptr); - SignalConnectionHolder(Data::SignalConnectionRef other); + SignalConnectionHolder(SignalConnectionRef other); ~SignalConnectionHolder(); // Prevent SignalConnectionHolder being accidentally copied, making it useless @@ -90,12 +90,12 @@ public: Signal& operator= (const Signal&) = delete; void DisconnectAll(); - void Fire(std::vector args); + void Fire(std::vector args); void Fire(); - Data::SignalConnectionRef Connect(std::function)> callback); - Data::SignalConnectionRef Connect(lua_State*); - Data::SignalConnectionRef Once(std::function)> callback); - Data::SignalConnectionRef Once(lua_State*); + SignalConnectionRef Connect(std::function)> callback); + SignalConnectionRef Connect(lua_State*); + SignalConnectionRef Once(std::function)> callback); + SignalConnectionRef Once(lua_State*); int Wait(lua_State*); }; @@ -105,43 +105,36 @@ public: virtual ~SignalSource(); }; -namespace Data { - class SignalRef : public Data::Base { - std::weak_ptr signal; +class SignalRef { + std::weak_ptr signal; - public: - SignalRef(std::weak_ptr); - ~SignalRef(); +public: + SignalRef(std::weak_ptr); + ~SignalRef(); - virtual const TypeInfo& GetType() const override; - static const TypeInfo TYPE; + static const TypeInfo TYPE; - operator std::weak_ptr(); + operator std::weak_ptr(); - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node node) const override; - virtual void PushLuaValue(lua_State*) const override; - static result FromLuaValue(lua_State*, int idx); - }; + virtual const std::string ToString() const; + virtual void Serialize(pugi::xml_node node) const; + virtual void PushLuaValue(lua_State*) const; + static result FromLuaValue(lua_State*, int idx); +}; - class SignalConnectionRef : public Data::Base { - std::weak_ptr signalConnection; +class SignalConnectionRef { + std::weak_ptr signalConnection; - public: - SignalConnectionRef(std::weak_ptr); - ~SignalConnectionRef(); +public: + SignalConnectionRef(std::weak_ptr); + ~SignalConnectionRef(); - virtual const TypeInfo& GetType() const override; - static const TypeInfo TYPE; + static const TypeInfo TYPE; - operator std::weak_ptr(); + operator std::weak_ptr(); - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node node) const override; - virtual void PushLuaValue(lua_State*) const override; - static result FromLuaValue(lua_State*, int idx); - }; -} - -using Data::SignalRef; -using Data::SignalConnectionRef; \ No newline at end of file + virtual const std::string ToString() const; + virtual void Serialize(pugi::xml_node node) const; + virtual void PushLuaValue(lua_State*) const; + 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 new file mode 100644 index 0000000..5b230b1 --- /dev/null +++ b/core/src/datatypes/variant.cpp @@ -0,0 +1,68 @@ +#include "variant.h" +#include "datatypes/base.h" +#include "datatypes/cframe.h" +#include "datatypes/primitives.h" +#include "datatypes/ref.h" +#include "datatypes/signal.h" +#include "datatypes/vector.h" +#include "logger.h" +#include "panic.h" +#include +#include +#include + +[[noreturn]] inline void unreachable() { +#if defined(_MSC_VER) && !defined(__clang__) // MSVC + __assume(false); +#else // GCC, Clang + __builtin_unreachable(); +#endif +} + +const TypeInfo* VARIANT_TYPES[] { + &NULL_TYPE, + &BOOL_TYPE, + &INT_TYPE, + &FLOAT_TYPE, + &STRING_TYPE, + &Vector3::TYPE, + &CFrame::TYPE, + &Color3::TYPE, + &InstanceRef::TYPE, + &SignalRef::TYPE, + &SignalConnectionRef::TYPE, +}; + +std::string Variant::ToString() const { + return VARIANT_TYPES[wrapped.index()]->toString(*this); +} + +void Variant::Serialize(pugi::xml_node node) const { + VARIANT_TYPES[wrapped.index()]->serializer(*this, node); +} + +void Variant::PushLuaValue(lua_State* state) const { + VARIANT_TYPES[wrapped.index()]->pushLuaValue(*this, state); +} + +Variant Variant::Deserialize(pugi::xml_node node) { + if (TYPE_MAP.count(node.name()) == 0) { + Logger::fatalErrorf("Unknown type for property: '%s'", node.name()); + panic(); + } + + const TypeInfo* type = TYPE_MAP[node.name()]; + return type->deserializer(node); +} + +std::map TYPE_MAP = { + { "null", &NULL_TYPE }, + { "bool", &BOOL_TYPE }, + { "int", &INT_TYPE }, + { "float", &FLOAT_TYPE }, + { "string", &STRING_TYPE }, + { "Vector3", &Vector3::TYPE }, + { "CoordinateFrame", &CFrame::TYPE }, + { "Color3", &Color3::TYPE }, + { "Ref", &InstanceRef::TYPE }, +}; \ No newline at end of file diff --git a/core/src/datatypes/variant.h b/core/src/datatypes/variant.h new file mode 100644 index 0000000..013fc67 --- /dev/null +++ b/core/src/datatypes/variant.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include "base.h" +#include "datatypes/color3.h" +#include "datatypes/ref.h" +#include "datatypes/signal.h" +#include "vector.h" +#include "cframe.h" + +// #define __VARIANT_TYPE std::variant< \ +// Null, \ +// Bool, \ +// Int, \ +// Float, \ +// String \ +// > + +typedef std::variant< + std::monostate, + bool, + int, + float, + std::string, + Vector3, + CFrame, + Color3, + InstanceRef, + SignalRef, + SignalConnectionRef +> __VARIANT_TYPE; + +class Variant { + __VARIANT_TYPE wrapped; +public: + template Variant(T obj) : wrapped(obj) {} + template T get() { return std::get(wrapped); } + std::string ToString() const; + + void Serialize(pugi::xml_node node) const; + void PushLuaValue(lua_State* state) const; + static Variant Deserialize(pugi::xml_node node); +}; + +template +std::function toVariantFunction(R(T::*f)(Args...)) { + return [f](Variant var, Args... args) { + return (var.get().*f)(args...); + }; +} + +template +std::function toVariantFunction(R(T::*f)(Args...) const) { + return [f](Variant var, Args... args) { + return (var.get().*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 ebf3092..23f3086 100644 --- a/core/src/datatypes/vector.cpp +++ b/core/src/datatypes/vector.cpp @@ -7,91 +7,91 @@ #include #include #include "datatypes/base.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include namespace rp = reactphysics3d; -Data::Vector3::Vector3() : vector(glm::vec3(0, 0, 0)) {}; -Data::Vector3::Vector3(const glm::vec3& src) : vector(src) {}; -Data::Vector3::Vector3(const rp::Vector3& src) : vector(glm::vec3(src.x, src.y, src.z)) {}; -Data::Vector3::Vector3(float x, const float y, float z) : vector(glm::vec3(x, y, z)) {}; +Vector3::Vector3() : vector(glm::vec3(0, 0, 0)) {}; +Vector3::Vector3(const glm::vec3& src) : vector(src) {}; +Vector3::Vector3(const rp::Vector3& src) : vector(glm::vec3(src.x, src.y, src.z)) {}; +Vector3::Vector3(float x, const float y, float z) : vector(glm::vec3(x, y, z)) {}; -Data::Vector3::~Vector3() = default; +Vector3::~Vector3() = default; -Data::Vector3 Data::Vector3::ZERO(0, 0, 0); -Data::Vector3 Data::Vector3::ONE(1, 1, 1); +Vector3 Vector3::ZERO(0, 0, 0); +Vector3 Vector3::ONE(1, 1, 1); -const Data::String Data::Vector3::ToString() const { +const std::string Vector3::ToString() const { // https://stackoverflow.com/a/46424921/16255372 std::stringstream stream; stream << std::setprecision(8) << std::noshowpoint << X() << ", " << Y() << ", " << Z(); return stream.str(); } -Data::Vector3::operator glm::vec3() const { return vector; }; -Data::Vector3::operator rp::Vector3() const { return rp::Vector3(X(), Y(), Z()); }; +Vector3::operator glm::vec3() const { return vector; }; +Vector3::operator rp::Vector3() const { return rp::Vector3(X(), Y(), Z()); }; // Operators -Data::Vector3 Data::Vector3::operator *(float scale) const { - return Data::Vector3(this->X() * scale, this->Y() * scale, this->Z() * scale); +Vector3 Vector3::operator *(float scale) const { + return Vector3(this->X() * scale, this->Y() * scale, this->Z() * scale); } -Data::Vector3 Data::Vector3::operator /(float scale) const { - return Data::Vector3(this->X() / scale, this->Y() / scale, this->Z() / scale); +Vector3 Vector3::operator /(float scale) const { + return Vector3(this->X() / scale, this->Y() / scale, this->Z() / scale); } // Component-wise -Data::Vector3 Data::Vector3::operator *(Data::Vector3 other) const { - return Data::Vector3(this->X() * other.X(), this->Y() * other.Y(), this->Z() * other.Z()); +Vector3 Vector3::operator *(Vector3 other) const { + return Vector3(this->X() * other.X(), this->Y() * other.Y(), this->Z() * other.Z()); } -Data::Vector3 Data::Vector3::operator +(Data::Vector3 other) const { - return Data::Vector3(this->X() + other.X(), this->Y() + other.Y(), this->Z() + other.Z()); +Vector3 Vector3::operator +(Vector3 other) const { + return Vector3(this->X() + other.X(), this->Y() + other.Y(), this->Z() + other.Z()); } -Data::Vector3 Data::Vector3::operator -(Data::Vector3 other) const { - return Data::Vector3(this->X() - other.X(), this->Y() - other.Y(), this->Z() - other.Z()); +Vector3 Vector3::operator -(Vector3 other) const { + return Vector3(this->X() - other.X(), this->Y() - other.Y(), this->Z() - other.Z()); } -Data::Vector3 Data::Vector3::operator -() const { - return Data::Vector3(-this->X(), -this->Y(), -this->Z()); +Vector3 Vector3::operator -() const { + return Vector3(-this->X(), -this->Y(), -this->Z()); } -bool Data::Vector3::operator ==(Data::Vector3 other) const { +bool Vector3::operator ==(Vector3 other) const { return this->X() == other.X() && this->Y() == other.Y() && this->Z() == other.Z(); } -bool Data::Vector3::operator <(Data::Vector3 other) const { +bool Vector3::operator <(Vector3 other) const { return X() < other.X() && Y() < other.Y() && Z() < other.Z(); } -bool Data::Vector3::operator >(Data::Vector3 other) const { +bool Vector3::operator >(Vector3 other) const { return X() > other.X() && Y() > other.Y() && Z() > other.Z(); } -Data::Vector3 Data::Vector3::Cross(Data::Vector3 other) const { +Vector3 Vector3::Cross(Vector3 other) const { return glm::cross(this->vector, other.vector); } -float Data::Vector3::Dot(Data::Vector3 other) const { +float Vector3::Dot(Vector3 other) const { return glm::dot(this->vector, other.vector); } // Serialization -void Data::Vector3::Serialize(pugi::xml_node node) const { +void Vector3::Serialize(pugi::xml_node node) const { node.append_child("X").text().set(std::to_string(this->X())); node.append_child("Y").text().set(std::to_string(this->Y())); node.append_child("Z").text().set(std::to_string(this->Z())); } -Data::Variant Data::Vector3::Deserialize(pugi::xml_node node) { - return Data::Vector3(node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float()); +Variant 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()); } -std::optional Data::Vector3::FromString(std::string string) { +std::optional Vector3::FromString(std::string string) { float components[3]; for (int i = 0; i < 3; i++) { @@ -109,5 +109,5 @@ std::optional Data::Vector3::FromString(std::string string) { components[i] = value; } - return Data::Vector3(components[0], components[1], components[2]); + return Vector3(components[0], components[1], components[2]); } \ No newline at end of file diff --git a/core/src/datatypes/vector.h b/core/src/datatypes/vector.h index 78441ae..0388fe9 100644 --- a/core/src/datatypes/vector.h +++ b/core/src/datatypes/vector.h @@ -7,59 +7,55 @@ namespace reactphysics3d { class Vector3; }; -namespace Data { - class DEF_DATA Vector3 : public Base { - AUTOGEN_PREAMBLE_DATA - glm::vec3 vector; +class DEF_DATA Vector3 { + AUTOGEN_PREAMBLE_DATA + glm::vec3 vector; + +public: + DEF_DATA_CTOR Vector3(); + DEF_DATA_CTOR Vector3(float x, float y, float z); + Vector3(const glm::vec3&); + Vector3(const reactphysics3d::Vector3&); + ~Vector3(); + + DEF_DATA_PROP static Vector3 ZERO; + DEF_DATA_PROP static Vector3 ONE; + + virtual const std::string ToString() const; + virtual void Serialize(pugi::xml_node node) const; + + static Variant Deserialize(pugi::xml_node node); + static std::optional FromString(std::string); - public: - DEF_DATA_CTOR Vector3(); - DEF_DATA_CTOR Vector3(float x, float y, float z); - Vector3(const glm::vec3&); - Vector3(const reactphysics3d::Vector3&); - ~Vector3(); + static void PushLuaLibrary(lua_State*); - DEF_DATA_PROP static Data::Vector3 ZERO; - DEF_DATA_PROP static Data::Vector3 ONE; + operator glm::vec3() const; + operator reactphysics3d::Vector3() const; - virtual const Data::String ToString() const override; - virtual void Serialize(pugi::xml_node node) const override; + DEF_DATA_PROP inline float X() const { return vector.x; } + DEF_DATA_PROP inline float Y() const { return vector.y; } + DEF_DATA_PROP inline float Z() const { return vector.z; } + DEF_DATA_METHOD inline float Magnitude() const { return glm::length(vector); } + DEF_DATA_METHOD inline Vector3 Unit() const { return glm::normalize(vector); } + DEF_DATA_METHOD inline Vector3 Abs() const { return glm::abs(vector); } - static Data::Variant Deserialize(pugi::xml_node node); - static std::optional FromString(std::string); - - static void PushLuaLibrary(lua_State*); + DEF_DATA_METHOD Vector3 Cross(Vector3) const; + DEF_DATA_METHOD float Dot(Vector3) const; - operator glm::vec3() const; - operator reactphysics3d::Vector3() const; + // Operators + DEF_DATA_OP Vector3 operator *(float) const; + DEF_DATA_OP Vector3 operator /(float) const; + DEF_DATA_OP Vector3 operator *(Vector3) const; // Component-wise + DEF_DATA_OP Vector3 operator +(Vector3) const; + DEF_DATA_OP Vector3 operator -(Vector3) const; + DEF_DATA_OP Vector3 operator -() const; - DEF_DATA_PROP inline float X() const { return vector.x; } - DEF_DATA_PROP inline float Y() const { return vector.y; } - DEF_DATA_PROP inline float Z() const { return vector.z; } - DEF_DATA_METHOD inline float Magnitude() const { return glm::length(vector); } - DEF_DATA_METHOD inline Data::Vector3 Unit() const { return glm::normalize(vector); } - DEF_DATA_METHOD inline Data::Vector3 Abs() const { return glm::abs(vector); } + DEF_DATA_OP bool operator <(Vector3) const; + DEF_DATA_OP bool operator >(Vector3) const; - DEF_DATA_METHOD Data::Vector3 Cross(Data::Vector3) const; - DEF_DATA_METHOD float Dot(Data::Vector3) const; - - // Operators - DEF_DATA_OP Data::Vector3 operator *(float) const; - DEF_DATA_OP Data::Vector3 operator /(float) const; - DEF_DATA_OP Data::Vector3 operator *(Data::Vector3) const; // Component-wise - DEF_DATA_OP Data::Vector3 operator +(Data::Vector3) const; - DEF_DATA_OP Data::Vector3 operator -(Data::Vector3) const; - DEF_DATA_OP Data::Vector3 operator -() const; + DEF_DATA_OP bool operator ==(Vector3) const; +}; - DEF_DATA_OP bool operator <(Data::Vector3) const; - DEF_DATA_OP bool operator >(Data::Vector3) const; - - DEF_DATA_OP bool operator ==(Data::Vector3) const; - }; -} - -using Data::Vector3; - -inline void printVec(Data::Vector3 vec) { +inline void printVec(Vector3 vec) { printf("(%f, %f, %f)\n", vec.X(), vec.Y(), vec.Z()); } \ No newline at end of file diff --git a/core/src/objects/annotation.h b/core/src/objects/annotation.h index 5d16d4a..9c6d299 100644 --- a/core/src/objects/annotation.h +++ b/core/src/objects/annotation.h @@ -37,8 +37,8 @@ #define AUTOGEN_PREAMBLE \ protected: \ virtual result InternalGetPropertyMeta(std::string name) override; \ -virtual fallible InternalSetPropertyValue(std::string name, Data::Variant value) override; \ -virtual result InternalGetPropertyValue(std::string name) override; \ +virtual fallible InternalSetPropertyValue(std::string name, Variant value) override; \ +virtual result InternalGetPropertyValue(std::string name) override; \ virtual void InternalUpdateProperty(std::string name) override; \ virtual std::vector InternalGetProperties() override; \ public: \ diff --git a/core/src/objects/base/instance.cpp b/core/src/objects/base/instance.cpp index 07ce9a2..9f3d51b 100644 --- a/core/src/objects/base/instance.cpp +++ b/core/src/objects/base/instance.cpp @@ -1,6 +1,7 @@ #include "instance.h" #include "common.h" -#include "datatypes/meta.h" +#include "datatypes/primitives.h" +#include "datatypes/variant.h" #include "datatypes/base.h" #include "datatypes/ref.h" #include "error/instance.h" @@ -96,7 +97,7 @@ void Instance::updateAncestry(std::optional> updatedCh } OnAncestryChanged(updatedChild, newParent); - AncestryChanged->Fire({updatedChild.has_value() ? Data::InstanceRef(updatedChild.value()) : Data::InstanceRef(), newParent.has_value() ? Data::InstanceRef(newParent.value()) : Data::InstanceRef()}); + AncestryChanged->Fire({updatedChild.has_value() ? InstanceRef(updatedChild.value()) : InstanceRef(), newParent.has_value() ? InstanceRef(newParent.value()) : InstanceRef()}); // Old workspace used to exist, and workspaces differ if (!oldWorkspace.expired() && oldWorkspace != _workspace) { @@ -179,11 +180,11 @@ void Instance::OnWorkspaceRemoved(std::shared_ptr oldWorkspace) { // Properties -result Instance::GetPropertyValue(std::string name) { +result Instance::GetPropertyValue(std::string name) { return InternalGetPropertyValue(name); } -fallible Instance::SetPropertyValue(std::string name, Data::Variant value, bool sendUpdateEvent) { +fallible Instance::SetPropertyValue(std::string name, Variant value, bool sendUpdateEvent) { auto result = InternalSetPropertyValue(name, value); if (result.isSuccess() && sendUpdateEvent) { InternalUpdateProperty(name); @@ -197,33 +198,33 @@ result Instance::GetPropertyMeta(std::string name) } -result Instance::InternalGetPropertyValue(std::string name) { +result Instance::InternalGetPropertyValue(std::string name) { if (name == "Name") { - return Data::Variant(Data::String(this->name)); + return Variant(this->name); } else if (name == "Parent") { - return Data::Variant(Data::InstanceRef(this->parent)); + return Variant(InstanceRef(this->parent)); } else if (name == "ClassName") { - return Data::Variant(Data::String(GetClass()->className)); + return Variant(GetClass()->className); } return MemberNotFound(GetClass()->className, name); } result Instance::InternalGetPropertyMeta(std::string name) { if (name == "Name") { - return PropertyMeta { &Data::String::TYPE }; + return PropertyMeta { &STRING_TYPE }; } else if (name == "Parent") { - return PropertyMeta { &Data::InstanceRef::TYPE, PROP_NOSAVE }; + return PropertyMeta { &InstanceRef::TYPE, PROP_NOSAVE }; } else if (name == "ClassName") { - return PropertyMeta { &Data::String::TYPE, PROP_NOSAVE | PROP_READONLY }; + return PropertyMeta { &STRING_TYPE, PROP_NOSAVE | PROP_READONLY }; } return MemberNotFound(GetClass()->className, name); } -fallible Instance::InternalSetPropertyValue(std::string name, Data::Variant value) { +fallible Instance::InternalSetPropertyValue(std::string name, Variant value) { if (name == "Name") { - this->name = (std::string)value.get(); + this->name = (std::string)value.get(); } else if (name == "Parent") { - std::weak_ptr ref = value.get(); + std::weak_ptr ref = value.get(); SetParent(ref.expired() ? std::nullopt : std::make_optional(ref.lock())); } else if (name == "ClassName") { return AssignToReadOnlyMember(GetClass()->className, name); @@ -273,8 +274,8 @@ void Instance::Serialize(pugi::xml_node parent, RefStateSerialize state) { propertyNode.append_attribute("name").set_value(name); // Update std::shared_ptr properties using map above - if (meta.type == &Data::InstanceRef::TYPE) { - std::weak_ptr refWeak = GetPropertyValue(name).expect("Declared property is missing").get(); + if (meta.type == &InstanceRef::TYPE) { + std::weak_ptr refWeak = GetPropertyValue(name).expect("Declared property is missing").get(); if (refWeak.expired()) continue; auto ref = refWeak.lock(); @@ -333,7 +334,7 @@ result, NoSuchInstance> Instance::Deserialize(pugi::xm } // Update std::shared_ptr properties using map above - if (meta_.expect().type == &Data::InstanceRef::TYPE) { + if (meta_.expect().type == &InstanceRef::TYPE) { if (propertyNode.text().empty()) continue; @@ -342,17 +343,17 @@ result, NoSuchInstance> Instance::Deserialize(pugi::xm if (remappedRef) { // If the instance has already been remapped, set the new value - object->SetPropertyValue(propertyName, Data::InstanceRef(remappedRef)).expect(); + object->SetPropertyValue(propertyName, InstanceRef(remappedRef)).expect(); } else { // Otheriise, queue this property to be updated later, and keep its current value auto& refs = state->refsAwaitingRemap[refId]; refs.push_back(std::make_pair(object, propertyName)); state->refsAwaitingRemap[refId] = refs; - object->SetPropertyValue(propertyName, Data::InstanceRef()).expect(); + object->SetPropertyValue(propertyName, InstanceRef()).expect(); } } else { - Data::Variant value = Data::Variant::Deserialize(propertyNode); + Variant value = Variant::Deserialize(propertyNode); object->SetPropertyValue(propertyName, value).expect("Declared property was missing"); } } @@ -363,7 +364,7 @@ result, NoSuchInstance> Instance::Deserialize(pugi::xm // Remap queued properties for (std::pair, std::string> ref : state->refsAwaitingRemap[remappedId]) { - ref.first->SetPropertyValue(ref.second, Data::InstanceRef(object)).expect(); + ref.first->SetPropertyValue(ref.second, InstanceRef(object)).expect(); } state->refsAwaitingRemap[remappedId].clear(); @@ -435,8 +436,8 @@ 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 == &Data::InstanceRef::TYPE) { - std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); + if (meta.type == &InstanceRef::TYPE) { + std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); if (refWeak.expired()) continue; auto ref = refWeak.lock(); @@ -444,17 +445,17 @@ std::optional> Instance::Clone(RefStateClone state) { if (remappedRef) { // If the instance has already been remapped, set the new value - newInstance->SetPropertyValue(property, Data::InstanceRef(remappedRef)).expect(); + newInstance->SetPropertyValue(property, InstanceRef(remappedRef)).expect(); } else { // Otheriise, queue this property to be updated later, and keep its current value auto& refs = state->refsAwaitingRemap[ref]; refs.push_back(std::make_pair(newInstance, property)); state->refsAwaitingRemap[ref] = refs; - newInstance->SetPropertyValue(property, Data::InstanceRef(ref)).expect(); + newInstance->SetPropertyValue(property, InstanceRef(ref)).expect(); } } else { - Data::Variant value = GetPropertyValue(property).expect(); + Variant value = GetPropertyValue(property).expect(); newInstance->SetPropertyValue(property, value).expect(); } } @@ -464,7 +465,7 @@ std::optional> Instance::Clone(RefStateClone state) { // Remap queued properties for (std::pair, std::string> ref : state->refsAwaitingRemap[shared_from_this()]) { - ref.first->SetPropertyValue(ref.second, Data::InstanceRef(newInstance)).expect(); + ref.first->SetPropertyValue(ref.second, InstanceRef(newInstance)).expect(); } state->refsAwaitingRemap[shared_from_this()].clear(); @@ -485,9 +486,9 @@ std::vector>> Instance::GetRefe for (std::string property : propertyNames) { PropertyMeta meta = GetPropertyMeta(property).expect(); - if (meta.type != &Data::InstanceRef::TYPE) continue; + if (meta.type != &InstanceRef::TYPE) continue; - std::weak_ptr ref = GetPropertyValue(property).expect().get(); + std::weak_ptr ref = GetPropertyValue(property).expect().get(); if (ref.expired()) continue; referenceProperties.push_back(std::make_pair(property, ref.lock())); } diff --git a/core/src/objects/base/instance.h b/core/src/objects/base/instance.h index cb74c96..5d1ee14 100644 --- a/core/src/objects/base/instance.h +++ b/core/src/objects/base/instance.h @@ -69,8 +69,8 @@ protected: Instance(const InstanceType*); virtual ~Instance(); - virtual result InternalGetPropertyValue(std::string name); - virtual fallible InternalSetPropertyValue(std::string name, Data::Variant value); + virtual result InternalGetPropertyValue(std::string name); + virtual fallible InternalSetPropertyValue(std::string name, Variant value); virtual result InternalGetPropertyMeta(std::string name); virtual void InternalUpdateProperty(std::string name); virtual std::vector InternalGetProperties(); @@ -114,8 +114,8 @@ public: std::string GetFullName(); // Properties - result GetPropertyValue(std::string name); - fallible SetPropertyValue(std::string name, Data::Variant value, bool sendUpdateEvent = true); + result GetPropertyValue(std::string name); + fallible SetPropertyValue(std::string name, Variant value, bool sendUpdateEvent = true); result GetPropertyMeta(std::string name); // Manually trigger the update of a property. Useful internally when setting properties directly void UpdateProperty(std::string name); diff --git a/core/src/objects/base/member.h b/core/src/objects/base/member.h index d971b8f..3fc5b9b 100644 --- a/core/src/objects/base/member.h +++ b/core/src/objects/base/member.h @@ -24,7 +24,7 @@ enum PropertyCategory { const int PROPERTY_CATEGORY_MAX = PROP_CATEGORY_SURFACE_INPUT; struct PropertyMeta { - const Data::TypeInfo* type; + const TypeInfo* type; PropertyFlags flags; PropertyCategory category = PROP_CATEGORY_DATA; }; diff --git a/core/src/objects/datamodel.cpp b/core/src/objects/datamodel.cpp index 539b913..1b6e1f2 100644 --- a/core/src/objects/datamodel.cpp +++ b/core/src/objects/datamodel.cpp @@ -5,7 +5,7 @@ #include "objects/base/service.h" #include "objects/meta.h" #include "objects/script/serverscriptservice.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include "workspace.h" #include "logger.h" #include "panic.h" @@ -131,8 +131,8 @@ std::shared_ptr DataModel::CloneModel() { if (meta.flags & (PROP_READONLY | PROP_NOSAVE)) continue; // Update std::shared_ptr properties using map above - if (meta.type == &Data::InstanceRef::TYPE) { - std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); + if (meta.type == &InstanceRef::TYPE) { + std::weak_ptr refWeak = GetPropertyValue(property).expect().get(); if (refWeak.expired()) continue; auto ref = refWeak.lock(); @@ -140,17 +140,17 @@ std::shared_ptr DataModel::CloneModel() { if (remappedRef) { // If the instance has already been remapped, set the new value - newModel->SetPropertyValue(property, Data::InstanceRef(remappedRef)).expect(); + newModel->SetPropertyValue(property, InstanceRef(remappedRef)).expect(); } else { // Otheriise, queue this property to be updated later, and keep its current value auto& refs = state->refsAwaitingRemap[ref]; refs.push_back(std::make_pair(newModel, property)); state->refsAwaitingRemap[ref] = refs; - newModel->SetPropertyValue(property, Data::InstanceRef(ref)).expect(); + newModel->SetPropertyValue(property, InstanceRef(ref)).expect(); } } else { - Data::Variant value = GetPropertyValue(property).expect(); + Variant value = GetPropertyValue(property).expect(); newModel->SetPropertyValue(property, value).expect(); } } @@ -160,7 +160,7 @@ std::shared_ptr DataModel::CloneModel() { // Remap queued properties for (std::pair, std::string> ref : state->refsAwaitingRemap[shared_from_this()]) { - ref.first->SetPropertyValue(ref.second, Data::InstanceRef(newModel)).expect(); + ref.first->SetPropertyValue(ref.second, InstanceRef(newModel)).expect(); } // Clone services diff --git a/core/src/objects/script.cpp b/core/src/objects/script.cpp index c19df66..ec24bb3 100644 --- a/core/src/objects/script.cpp +++ b/core/src/objects/script.cpp @@ -41,10 +41,10 @@ void Script::Run() { // Initialize script globals lua_getglobal(Lt, "_G"); - Data::InstanceRef(dataModel().value()).PushLuaValue(Lt); + InstanceRef(dataModel().value()).PushLuaValue(Lt); lua_setfield(Lt, -2, "game"); - Data::InstanceRef(dataModel().value()->GetService()).PushLuaValue(Lt); + InstanceRef(dataModel().value()->GetService()).PushLuaValue(Lt); lua_setfield(Lt, -2, "workspace"); lua_pushlightuserdata(Lt, scriptContext.get()); diff --git a/core/src/objects/script/scriptcontext.cpp b/core/src/objects/script/scriptcontext.cpp index 3b176ea..3985e5c 100644 --- a/core/src/objects/script/scriptcontext.cpp +++ b/core/src/objects/script/scriptcontext.cpp @@ -43,9 +43,9 @@ void ScriptContext::InitService() { // luaopen_debug(state); luaopen_bit(state); - Data::Vector3::PushLuaLibrary(state); - Data::CFrame::PushLuaLibrary(state); - Data::Color3::PushLuaLibrary(state); + Vector3::PushLuaLibrary(state); + CFrame::PushLuaLibrary(state); + Color3::PushLuaLibrary(state); // TODO: custom os library diff --git a/core/src/objects/workspace.cpp b/core/src/objects/workspace.cpp index 8b2085e..74cfcfa 100644 --- a/core/src/objects/workspace.cpp +++ b/core/src/objects/workspace.cpp @@ -1,5 +1,5 @@ #include "workspace.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include "datatypes/ref.h" #include "datatypes/vector.h" #include "objects/base/instance.h" @@ -33,11 +33,11 @@ void PhysicsEventListener::onContact(const rp::CollisionCallback::CallbackData& auto part1 = reinterpret_cast(pair.getBody2()->getUserData())->shared(); if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart) { - part0->Touched->Fire({ (Data::Variant)Data::InstanceRef(part1) }); - part1->Touched->Fire({ (Data::Variant)Data::InstanceRef(part0) }); + part0->Touched->Fire({ (Variant)InstanceRef(part1) }); + part1->Touched->Fire({ (Variant)InstanceRef(part0) }); } else if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactExit) { - part0->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part1) }); - part1->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part0) }); + part0->TouchEnded->Fire({ (Variant)InstanceRef(part1) }); + part1->TouchEnded->Fire({ (Variant)InstanceRef(part0) }); } } } diff --git a/core/src/partassembly.cpp b/core/src/partassembly.cpp index fc4f03d..c5f120c 100644 --- a/core/src/partassembly.cpp +++ b/core/src/partassembly.cpp @@ -1,7 +1,7 @@ #include "partassembly.h" #include "common.h" #include "datatypes/cframe.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include "datatypes/vector.h" #include "math_helper.h" #include "objects/base/instance.h" @@ -49,7 +49,7 @@ void PartAssembly::SetOrigin(CFrame newOrigin) { for (auto part : parts) { part->cframe = newOrigin * (_assemblyOrigin.Inverse() * part->cframe); part->UpdateProperty("CFrame"); - // sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe)); + // sendPropertyUpdatedSignal(part, "CFrame", Variant(part->cframe)); } _assemblyOrigin = newOrigin; @@ -59,7 +59,7 @@ void PartAssembly::TransformBy(CFrame transform) { for (auto part : parts) { part->cframe = transform * part->cframe; part->UpdateProperty("CFrame"); - sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe)); + sendPropertyUpdatedSignal(part, "CFrame", Variant(part->cframe)); } _assemblyOrigin = transform * _assemblyOrigin; @@ -69,7 +69,7 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) { if (parts.size() == 1) { parts[0]->size = newSize; parts[0]->UpdateProperty("Size"); - sendPropertyUpdatedSignal(parts[0], "Size", Data::Variant((Data::Vector3)parts[0]->size)); + sendPropertyUpdatedSignal(parts[0], "Size", Variant((Vector3)parts[0]->size)); _bounds = newSize; return; } @@ -82,10 +82,10 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) { localOff = localOff * factor; part->cframe = part->cframe.Rotation() + _assemblyOrigin * localOff; part->UpdateProperty("CFrame"); - sendPropertyUpdatedSignal(part, "CFrame", Data::Variant(part->cframe)); + sendPropertyUpdatedSignal(part, "CFrame", Variant(part->cframe)); part->size *= factor; part->UpdateProperty("Size"); - sendPropertyUpdatedSignal(part, "Size", Data::Variant((Data::Vector3)part->size)); + sendPropertyUpdatedSignal(part, "Size", Variant((Vector3)part->size)); } _bounds = _bounds * factor; diff --git a/core/src/rendering/renderer.h b/core/src/rendering/renderer.h index 0cae941..5aa33bb 100644 --- a/core/src/rendering/renderer.h +++ b/core/src/rendering/renderer.h @@ -8,5 +8,5 @@ namespace Data { class CFrame; class Color3; }; void renderInit(GLFWwindow* window, int width, int height); void render(GLFWwindow* window); void setViewport(int width, int height); -void addDebugRenderCFrame(Data::CFrame); -void addDebugRenderCFrame(Data::CFrame, Data::Color3); \ No newline at end of file +void addDebugRenderCFrame(CFrame); +void addDebugRenderCFrame(CFrame, Color3); \ No newline at end of file diff --git a/core/src/rendering/surface.h b/core/src/rendering/surface.h index e2e45fa..0c83e3b 100644 --- a/core/src/rendering/surface.h +++ b/core/src/rendering/surface.h @@ -20,6 +20,6 @@ enum SurfaceType { SurfaceMotor = 7, }; -namespace Data { class Vector3; } using Data::Vector3; +class Vector3; NormalId faceFromNormal(Vector3); Vector3 normalFromFace(NormalId); \ No newline at end of file diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index d8854db..796fb69 100755 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -17,7 +17,7 @@ #include "physics/util.h" #include "rendering/renderer.h" #include "rendering/shader.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #define PI 3.14159 #define M_mainWindow dynamic_cast(window()) diff --git a/editor/panes/propertiesview.cpp b/editor/panes/propertiesview.cpp index 12ddaf9..705cef9 100644 --- a/editor/panes/propertiesview.cpp +++ b/editor/panes/propertiesview.cpp @@ -1,7 +1,8 @@ #include "panes/propertiesview.h" #include "common.h" #include "datatypes/base.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" +#include "datatypes/primitives.h" #include "objects/base/member.h" #include @@ -49,7 +50,7 @@ public: std::string propertyName = !isComposite ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString() : view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString(); PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect(); - Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect(); + Variant currentValue = inst->GetPropertyValue(propertyName).expect(); if (isComposite) { if (meta.type == &Vector3::TYPE) { @@ -65,9 +66,9 @@ public: return nullptr; } - if (meta.type == &Data::Float::TYPE) { + if (meta.type == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); - spinBox->setValue(currentValue.get()); + spinBox->setValue(currentValue.get()); if (meta.flags & PROP_UNIT_FLOAT) { spinBox->setMinimum(0); @@ -76,14 +77,14 @@ public: } return spinBox; - } else if (meta.type == &Data::Int::TYPE) { + } else if (meta.type == &INT_TYPE) { QSpinBox* spinBox = new QSpinBox(parent); - spinBox->setValue(currentValue.get()); + spinBox->setValue(currentValue.get()); return spinBox; - } else if (meta.type == &Data::String::TYPE) { + } else if (meta.type == &STRING_TYPE) { QLineEdit* lineEdit = new QLineEdit(parent); - lineEdit->setText(QString::fromStdString(currentValue.get())); + lineEdit->setText(QString::fromStdString(currentValue.get())); return lineEdit; } else if (meta.type == &Color3::TYPE) { @@ -115,7 +116,7 @@ public: std::string propertyName = !index.parent().parent().isValid() ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString() : view->itemFromIndex(index.parent())->data(0, Qt::DisplayRole).toString().toStdString(); PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect(); - Data::Variant currentValue = inst->GetPropertyValue(propertyName).expect(); + Variant currentValue = inst->GetPropertyValue(propertyName).expect(); if (isComposite) { if (meta.type == &Vector3::TYPE) { @@ -131,18 +132,18 @@ public: return; } - if (meta.type == &Data::Float::TYPE) { + if (meta.type == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = dynamic_cast(editor); - spinBox->setValue(currentValue.get()); - } else if (meta.type == &Data::Int::TYPE) { + spinBox->setValue(currentValue.get()); + } else if (meta.type == &INT_TYPE) { QSpinBox* spinBox = dynamic_cast(editor); - spinBox->setValue(currentValue.get()); - } else if (meta.type == &Data::String::TYPE) { + spinBox->setValue(currentValue.get()); + } else if (meta.type == &STRING_TYPE) { QLineEdit* lineEdit = dynamic_cast(editor); - lineEdit->setText(QString::fromStdString((std::string)currentValue.get())); + lineEdit->setText(QString::fromStdString((std::string)currentValue.get())); } else if (meta.type == &Color3::TYPE) { QColorDialog* colorDialog = dynamic_cast(editor); @@ -186,20 +187,20 @@ public: return; } - if (meta.type == &Data::Float::TYPE) { + if (meta.type == &FLOAT_TYPE) { QDoubleSpinBox* spinBox = dynamic_cast(editor); - inst->SetPropertyValue(propertyName, Data::Float((float)spinBox->value())).expect(); + inst->SetPropertyValue(propertyName, (float)spinBox->value()).expect(); model->setData(index, spinBox->value()); - } else if (meta.type == &Data::Int::TYPE) { + } else if (meta.type == &INT_TYPE) { QSpinBox* spinBox = dynamic_cast(editor); - inst->SetPropertyValue(propertyName, Data::Int((float)spinBox->value())).expect(); + inst->SetPropertyValue(propertyName, (int)spinBox->value()).expect(); model->setData(index, spinBox->value()); - } else if (meta.type == &Data::String::TYPE) { + } else if (meta.type == &STRING_TYPE) { QLineEdit* lineEdit = dynamic_cast(editor); - inst->SetPropertyValue(propertyName, Data::String(lineEdit->text().toStdString())).expect(); + inst->SetPropertyValue(propertyName, lineEdit->text().toStdString()).expect(); model->setData(index, lineEdit->text()); } else if (meta.type == &Color3::TYPE) { QColorDialog* colorDialog = dynamic_cast(editor); @@ -212,7 +213,7 @@ public: } else if (meta.type->fromString) { QLineEdit* lineEdit = dynamic_cast(editor); - std::optional parsedResult = meta.type->fromString(lineEdit->text().toStdString()); + std::optional parsedResult = meta.type->fromString(lineEdit->text().toStdString()); if (!parsedResult) return; inst->SetPropertyValue(propertyName, parsedResult.value()).expect(); model->setData(index, QString::fromStdString(parsedResult.value().ToString())); @@ -296,7 +297,7 @@ void PropertiesView::setSelected(std::optional> instan for (std::string property : properties) { PropertyMeta meta = inst->GetPropertyMeta(property).expect(); - Data::Variant currentValue = inst->GetPropertyValue(property).expect(); + Variant currentValue = inst->GetPropertyValue(property).expect(); if (meta.type == &CFrame::TYPE || meta.flags & PROP_HIDDEN) continue; @@ -304,8 +305,8 @@ void PropertiesView::setSelected(std::optional> instan item->setFlags(item->flags() | Qt::ItemIsEditable | Qt::ItemIsSelectable); item->setData(0, Qt::DisplayRole, QString::fromStdString(property)); - if (meta.type == &Data::Bool::TYPE) { - item->setCheckState(1, (bool)currentValue.get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + if (meta.type == &BOOL_TYPE) { + item->setCheckState(1, (bool)currentValue.get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); } else if (meta.type == &Color3::TYPE) { Color3 color = currentValue.get(); item->setData(1, Qt::DecorationRole, QColor::fromRgbF(color.R(), color.G(), color.B())); @@ -352,12 +353,12 @@ void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) { std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString(); PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect(); - if (meta.type == &Data::Bool::TYPE) { - inst->SetPropertyValue(propertyName, Data::Bool(item->checkState(1) == Qt::Checked)).expect(); + if (meta.type == &BOOL_TYPE) { + inst->SetPropertyValue(propertyName, item->checkState(1) == Qt::Checked).expect(); } } -void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const Data::TypeInfo* type, Data::Variant value) { +void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const TypeInfo* type, Variant value) { if (type == &Vector3::TYPE) { // https://forum.qt.io/post/266837 foreach(auto i, item->takeChildren()) delete i; @@ -384,13 +385,13 @@ void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const Data: } // static auto lastUpdateTime = std::chrono::steady_clock::now(); -void PropertiesView::onPropertyUpdated(std::shared_ptr inst, std::string property, Data::Variant newValue) { +void PropertiesView::onPropertyUpdated(std::shared_ptr inst, std::string property, Variant newValue) { // if (!currentInstance || currentInstance->expired() || instance != currentInstance->lock()) return; // if (std::chrono::duration_cast(std::chrono::steady_clock::now() - lastUpdateTime).count() < 1000) return; // lastUpdateTime = std::chrono::steady_clock::now(); PropertyMeta meta = inst->GetPropertyMeta(property).expect(); - Data::Variant currentValue = inst->GetPropertyValue(property).expect(); + Variant currentValue = inst->GetPropertyValue(property).expect(); if (meta.type == &CFrame::TYPE) return; @@ -401,10 +402,10 @@ void PropertiesView::onPropertyUpdated(std::shared_ptr inst, std::stri if (item->data(0, Qt::DisplayRole).toString().toStdString() != property) continue; - if (meta.type == &Data::Bool::TYPE) { + if (meta.type == &BOOL_TYPE) { // This is done because otherwise propertyChanged will catch this change erroneously ignorePropertyUpdates = true; - item->setCheckState(1, (bool)currentValue.get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + item->setCheckState(1, (bool)currentValue.get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); ignorePropertyUpdates = false; } else if (meta.type == &Color3::TYPE) { Color3 color = currentValue.get(); diff --git a/editor/panes/propertiesview.h b/editor/panes/propertiesview.h index b9c2882..098f06f 100644 --- a/editor/panes/propertiesview.h +++ b/editor/panes/propertiesview.h @@ -15,8 +15,8 @@ class PropertiesView : public QTreeWidget { std::weak_ptr currentInstance; void propertyChanged(QTreeWidgetItem *item, int column); void activateProperty(QTreeWidgetItem *item, int column); - void rebuildCompositeProperty(QTreeWidgetItem *item, const Data::TypeInfo*, Data::Variant); - void onPropertyUpdated(std::shared_ptr instance, std::string property, Data::Variant newValue); + void rebuildCompositeProperty(QTreeWidgetItem *item, const TypeInfo*, Variant); + void onPropertyUpdated(std::shared_ptr instance, std::string property, Variant newValue); friend PropertiesItemDelegate; protected: diff --git a/editor/script/scriptdocument.cpp b/editor/script/scriptdocument.cpp index 6e27d61..322a2c4 100644 --- a/editor/script/scriptdocument.cpp +++ b/editor/script/scriptdocument.cpp @@ -16,7 +16,7 @@ #include #include "mainwindow.h" #include "objects/script.h" -#include "datatypes/meta.h" +#include "datatypes/variant.h" #include #include @@ -115,9 +115,9 @@ ScriptDocument::ScriptDocument(std::shared_ptr