refactor(datatypes): complete refactor of how datatypes work and removal of wrapper classes for bool, string etc.
This commit is contained in:
parent
c8880e0edc
commit
5f6ff971d2
39 changed files with 831 additions and 804 deletions
|
@ -9,10 +9,6 @@
|
|||
using namespace data;
|
||||
|
||||
static std::map<std::string, std::string> 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<std::string, std::string> LUA_TEST_FUNCS = {
|
|||
{ "std::string", "lua_isstring" },
|
||||
};
|
||||
|
||||
static std::map<std::string, std::string> 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<std::string, std::vector<MethodAnalysis>> 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::Variant, LuaCastError> Data::" << state.name << "::FromLuaValue(lua_State* L, int idx) {\n"
|
||||
out << "result<Variant, LuaCastError> " << 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 <pugixml.hpp>\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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -16,13 +16,17 @@ static std::map<std::string, std::string> CATEGORY_STR = {
|
|||
};
|
||||
|
||||
static std::map<std::string, std::string> MAPPED_TYPE = {
|
||||
{ "bool", "Data::Bool" },
|
||||
{ "int", "Data::Int" },
|
||||
{ "float", "Data::Float" },
|
||||
{ "std::string", "Data::String" },
|
||||
{ "glm::vec3", "Vector3" },
|
||||
};
|
||||
|
||||
static std::map<std::string, std::string> TYPEINFO_REFS = {
|
||||
{ "glm::vec3", "Vector3::TYPE" },
|
||||
{ "bool", "BOOL_TYPE" },
|
||||
{ "int", "INT_TYPE" },
|
||||
{ "float", "FLOAT_TYPE" },
|
||||
{ "std::string", "STRING_TYPE" },
|
||||
};
|
||||
|
||||
static std::map<std::string, std::monostate> 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<Data::Int>()";
|
||||
return "(SurfaceType)(int)" + valueStr + ".get<int>()";
|
||||
}
|
||||
|
||||
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<Instance>
|
||||
std::string subtype = parseWeakPtr(fieldType);
|
||||
if (!subtype.empty()) {
|
||||
return "Data::Variant(" + valueStr + ".expired() ? Data::InstanceRef() : Data::InstanceRef(std::dynamic_pointer_cast<Instance>(" + valueStr + ".lock())))";
|
||||
return "Variant(" + valueStr + ".expired() ? InstanceRef() : InstanceRef(std::dynamic_pointer_cast<Instance>(" + 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<MemberNotFound, AssignToReadOnlyMember> " << state.name << "::InternalSetPropertyValue(std::string name, Data::Variant value) {";
|
||||
out << "fallible<MemberNotFound, AssignToReadOnlyMember> " << 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<Vector3>()) + this->" << prop.fieldName << ".Position();";
|
||||
} else if (!subtype.empty()) {
|
||||
out << "\n std::weak_ptr<Instance> ref = value.get<Data::InstanceRef>();"
|
||||
out << "\n std::weak_ptr<Instance> ref = value.get<InstanceRef>();"
|
||||
<< "\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<Data::Variant, MemberNotFound> " << state.name << "::InternalGetPropertyValue(std::string name) {";
|
||||
out << "result<Variant, MemberNotFound> " << 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"
|
||||
|
|
|
@ -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 <memory>
|
||||
|
||||
|
@ -34,7 +34,7 @@ void addSelectionListener(SelectionUpdateHandler handler) {
|
|||
selectionUpdateListeners.push_back(handler);
|
||||
}
|
||||
|
||||
void sendPropertyUpdatedSignal(std::shared_ptr<Instance> instance, std::string property, Data::Variant newValue) {
|
||||
void sendPropertyUpdatedSignal(std::shared_ptr<Instance> instance, std::string property, Variant newValue) {
|
||||
for (PropertyUpdateHandler handler : propertyUpdatelisteners) {
|
||||
handler(instance, property, newValue);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ class Instance;
|
|||
typedef std::function<void(std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent)> HierarchyPreUpdateHandler;
|
||||
typedef std::function<void(std::shared_ptr<Instance> object, std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent)> HierarchyPostUpdateHandler;
|
||||
typedef std::function<void(std::vector<std::shared_ptr<Instance>> oldSelection, std::vector<std::shared_ptr<Instance>> newSelection, bool fromExplorer)> SelectionUpdateHandler;
|
||||
typedef std::function<void(std::shared_ptr<Instance> instance, std::string property, Data::Variant newValue)> PropertyUpdateHandler;
|
||||
typedef std::function<void(std::shared_ptr<Instance> instance, std::string property, Variant newValue)> PropertyUpdateHandler;
|
||||
|
||||
// TEMPORARY COMMON DATA FOR VARIOUS INTERNAL COMPONENTS
|
||||
|
||||
|
@ -28,5 +28,5 @@ void setSelection(std::vector<std::shared_ptr<Instance>> newSelection, bool from
|
|||
const std::vector<std::shared_ptr<Instance>> getSelection();
|
||||
void addSelectionListener(SelectionUpdateHandler handler);
|
||||
|
||||
void sendPropertyUpdatedSignal(std::shared_ptr<Instance> instance, std::string property, Data::Variant newValue);
|
||||
void sendPropertyUpdatedSignal(std::shared_ptr<Instance> instance, std::string property, Variant newValue);
|
||||
void addPropertyUpdateListener(PropertyUpdateHandler handler);
|
|
@ -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<Data::Variant, LuaCastError> FromLuaValue(lua_State*, int idx); \
|
||||
virtual void PushLuaValue(lua_State*) const; \
|
||||
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx); \
|
||||
private:
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
#include "base.h"
|
||||
#include "error/data.h"
|
||||
#include "meta.h"
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <pugixml.hpp>
|
||||
#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::Variant, LuaCastError> 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::Variant> 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::Variant> 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::Variant> 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::Variant> 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::Variant, LuaCastError> 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::Variant, LuaCastError> 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::Variant, LuaCastError> 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::Variant, LuaCastError> 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)));
|
||||
}
|
|
@ -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<Data::Variant> FromString(std::string); \
|
||||
static result<Data::Variant, LuaCastError> FromLuaValue(lua_State*, int idx); \
|
||||
};
|
||||
class Variant;
|
||||
typedef std::function<void(Variant, pugi::xml_node)> Serializer;
|
||||
typedef std::function<Variant(pugi::xml_node)> Deserializer;
|
||||
typedef std::function<std::string(Variant)> ToString;
|
||||
typedef std::function<std::optional<Variant>(std::string)> FromString;
|
||||
typedef std::function<result<Variant, LuaCastError>(lua_State*, int idx)> FromLuaValue;
|
||||
typedef std::function<void(Variant self, lua_State*)> PushLuaValue;
|
||||
|
||||
namespace Data {
|
||||
class Variant;
|
||||
typedef std::function<Data::Variant(pugi::xml_node)> Deserializer;
|
||||
typedef std::function<std::optional<Data::Variant>(std::string)> FromString;
|
||||
typedef std::function<result<Data::Variant, LuaCastError>(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<Data::Variant, LuaCastError> 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
|
||||
struct TypeInfo {
|
||||
std::string name;
|
||||
Serializer serializer;
|
||||
Deserializer deserializer;
|
||||
ToString toString;
|
||||
FromString fromString;
|
||||
PushLuaValue pushLuaValue;
|
||||
FromLuaValue fromLuaValue;
|
||||
};
|
|
@ -6,18 +6,18 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/matrix.hpp>
|
||||
#include <reactphysics3d/mathematics/Transform.h>
|
||||
#include "datatypes/meta.h"
|
||||
#include "datatypes/variant.h"
|
||||
#include <pugixml.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
// #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(),
|
||||
|
|
|
@ -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;
|
||||
// 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;
|
||||
};
|
|
@ -1,21 +1,21 @@
|
|||
#include "color3.h"
|
||||
#include "datatypes/meta.h"
|
||||
#include "datatypes/variant.h"
|
||||
#include <pugixml.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
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());
|
||||
}
|
|
@ -4,34 +4,30 @@
|
|||
#include "datatypes/annotation.h"
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
|
||||
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;
|
||||
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; }
|
||||
};
|
|
@ -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 <pugixml.hpp>
|
||||
#include <variant>
|
||||
|
||||
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<std::string, const Data::TypeInfo*> 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 },
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include <map>
|
||||
#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 <typename T> Variant(T obj) : wrapped(obj) {}
|
||||
template <typename T> T get() { return std::get<T>(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<std::string, const TypeInfo*> TYPE_MAP;
|
||||
}
|
211
core/src/datatypes/primitives.cpp
Normal file
211
core/src/datatypes/primitives.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
#include "primitives.h"
|
||||
#include "variant.h"
|
||||
#include <pugixml.hpp>
|
||||
#include "lua.h"
|
||||
#include <sstream>
|
||||
|
||||
// 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<Variant> Null_FromString(std::string str) {
|
||||
return std::monostate();
|
||||
}
|
||||
|
||||
void Null_PushLuaValue(Variant self, lua_State* L) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
result<Variant, LuaCastError> 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<bool>() ? "true" : "false");
|
||||
}
|
||||
|
||||
Variant Bool_Deserialize(pugi::xml_node node) {
|
||||
return node.text().as_bool();
|
||||
}
|
||||
|
||||
const std::string Bool_ToString(Variant self) {
|
||||
return self.get<bool>() ? "true" : "false";
|
||||
}
|
||||
|
||||
const std::optional<Variant> 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<bool>());
|
||||
}
|
||||
|
||||
result<Variant, LuaCastError> 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<int>());
|
||||
}
|
||||
|
||||
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<int>());
|
||||
}
|
||||
|
||||
const std::optional<Variant> 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<int>());
|
||||
}
|
||||
|
||||
result<Variant, LuaCastError> 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<float>());
|
||||
}
|
||||
|
||||
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<float>();
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
const std::optional<Variant> 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<float>());
|
||||
}
|
||||
|
||||
result<Variant, LuaCastError> 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<std::string>());
|
||||
}
|
||||
|
||||
Variant String_Deserialize(pugi::xml_node node) {
|
||||
return node.text().as_string();
|
||||
}
|
||||
|
||||
const std::string String_ToString(Variant self) {
|
||||
return self.get<std::string>();
|
||||
}
|
||||
|
||||
const std::optional<Variant> String_FromString(std::string string) {
|
||||
return string;
|
||||
}
|
||||
|
||||
void String_PushLuaValue(Variant self, lua_State* L) {
|
||||
lua_pushstring(L, self.get<std::string>().c_str());
|
||||
}
|
||||
|
||||
result<Variant, LuaCastError> 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
|
9
core/src/datatypes/primitives.h
Normal file
9
core/src/datatypes/primitives.h
Normal file
|
@ -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;
|
|
@ -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 <memory>
|
||||
#include <optional>
|
||||
#include "objects/base/instance.h"
|
||||
|
@ -10,34 +10,36 @@
|
|||
#include "objects/base/member.h"
|
||||
#include <pugixml.hpp>
|
||||
|
||||
Data::InstanceRef::InstanceRef() {};
|
||||
Data::InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {};
|
||||
Data::InstanceRef::~InstanceRef() = default;
|
||||
InstanceRef::InstanceRef() {};
|
||||
InstanceRef::InstanceRef(std::weak_ptr<Instance> 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<Instance>() {
|
||||
InstanceRef::operator std::weak_ptr<Instance>() {
|
||||
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::Variant, LuaCastError> Data::InstanceRef::FromLuaValue(lua_State* L, int idx) {
|
||||
result<Variant, LuaCastError> 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<Instance>**)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<PropertyMeta> 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<std::shared_ptr<Instance>> 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<Data::Variant, LuaCastError> value = meta->type->fromLuaValue(L, -1);
|
||||
result<Variant, LuaCastError> value = meta->type->fromLuaValue(L, -1);
|
||||
lua_pop(L, 3);
|
||||
|
||||
if (value.isError())
|
||||
|
|
|
@ -6,23 +6,20 @@
|
|||
|
||||
class Instance;
|
||||
|
||||
namespace Data {
|
||||
class InstanceRef : public Base {
|
||||
std::weak_ptr<Instance> ref;
|
||||
public:
|
||||
InstanceRef();
|
||||
InstanceRef(std::weak_ptr<Instance>);
|
||||
~InstanceRef();
|
||||
class InstanceRef {
|
||||
std::weak_ptr<Instance> ref;
|
||||
public:
|
||||
InstanceRef();
|
||||
InstanceRef(std::weak_ptr<Instance>);
|
||||
~InstanceRef();
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
operator std::weak_ptr<Instance>();
|
||||
operator std::weak_ptr<Instance>();
|
||||
|
||||
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<Data::Variant, LuaCastError> 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<Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
#include "signal.h"
|
||||
#include "datatypes/base.h"
|
||||
#include "meta.h"
|
||||
#include "variant.h"
|
||||
#include "lua.h"
|
||||
#include <cstdio>
|
||||
#include <luajit-2.1/lauxlib.h>
|
||||
|
@ -53,13 +53,13 @@ static void stackdump(lua_State* L) {
|
|||
fflush(stdout);
|
||||
}
|
||||
|
||||
void LuaSignalConnection::Call(std::vector<Data::Variant> args) {
|
||||
void LuaSignalConnection::Call(std::vector<Variant> 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<Data::Variant> args) {
|
|||
|
||||
//
|
||||
|
||||
CSignalConnection::CSignalConnection(std::function<void(std::vector<Data::Variant>)> func, std::weak_ptr<Signal> parent) : SignalConnection(parent) {
|
||||
CSignalConnection::CSignalConnection(std::function<void(std::vector<Variant>)> func, std::weak_ptr<Signal> parent) : SignalConnection(parent) {
|
||||
this->function = func;
|
||||
}
|
||||
|
||||
void CSignalConnection::Call(std::vector<Data::Variant> args) {
|
||||
void CSignalConnection::Call(std::vector<Variant> args) {
|
||||
function(args);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ void CSignalConnection::Call(std::vector<Data::Variant> args) {
|
|||
|
||||
SignalConnectionHolder::SignalConnectionHolder() : heldConnection() {}
|
||||
SignalConnectionHolder::SignalConnectionHolder(std::shared_ptr<SignalConnection> 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<void(std::vector<Data::Variant>)> callback) {
|
||||
SignalConnectionRef Signal::Connect(std::function<void(std::vector<Variant>)> callback) {
|
||||
auto conn = std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(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<void(std::vector<Data::Variant>)> callback) {
|
||||
SignalConnectionRef Signal::Once(std::function<void(std::vector<Variant>)> callback) {
|
||||
auto conn = std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(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<Data::Variant> args) {
|
||||
void Signal::Fire(std::vector<Variant> args) {
|
||||
for (std::shared_ptr<SignalConnection> connection : connections) {
|
||||
connection->Call(args);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ void Signal::Fire(std::vector<Data::Variant> args) {
|
|||
auto prevThreads = std::move(waitingThreads);
|
||||
waitingThreads = std::vector<std::pair<int, lua_State*>>();
|
||||
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<Data::Variant> args) {
|
|||
}
|
||||
|
||||
void Signal::Fire() {
|
||||
return Fire(std::vector<Data::Variant> {});
|
||||
return Fire(std::vector<Variant> {});
|
||||
}
|
||||
|
||||
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<Signal> ref) : signal(ref) {}
|
||||
Data::SignalRef::~SignalRef() = default;
|
||||
SignalRef::SignalRef(std::weak_ptr<Signal> 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<Signal>() {
|
||||
SignalRef::operator std::weak_ptr<Signal>() {
|
||||
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<Signal>**)lua_newuserdata(L, sizeof(std::weak_ptr<Signal>));
|
||||
|
@ -257,10 +255,10 @@ void Data::SignalRef::PushLuaValue(lua_State* L) const {
|
|||
lua_setmetatable(L, n+1);
|
||||
}
|
||||
|
||||
result<Data::Variant, LuaCastError> Data::SignalRef::FromLuaValue(lua_State* L, int idx) {
|
||||
result<Variant, LuaCastError> SignalRef::FromLuaValue(lua_State* L, int idx) {
|
||||
auto userdata = (std::weak_ptr<Signal>**)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<SignalConnection> ref) : signalConnection(ref) {}
|
||||
Data::SignalConnectionRef::~SignalConnectionRef() = default;
|
||||
SignalConnectionRef::SignalConnectionRef(std::weak_ptr<SignalConnection> 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<SignalConnection>() {
|
||||
SignalConnectionRef::operator std::weak_ptr<SignalConnection>() {
|
||||
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<SignalConnection>**)lua_newuserdata(L, sizeof(std::weak_ptr<SignalConnection>));
|
||||
|
@ -378,10 +374,10 @@ void Data::SignalConnectionRef::PushLuaValue(lua_State* L) const {
|
|||
lua_setmetatable(L, n+1);
|
||||
}
|
||||
|
||||
result<Data::Variant, LuaCastError> Data::SignalConnectionRef::FromLuaValue(lua_State* L, int idx) {
|
||||
result<Variant, LuaCastError> SignalConnectionRef::FromLuaValue(lua_State* L, int idx) {
|
||||
auto userdata = (std::weak_ptr<SignalConnection>**)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) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
class Instance;
|
||||
class Signal;
|
||||
|
||||
namespace Data { class SignalConnectionRef; }
|
||||
class SignalConnectionRef;
|
||||
|
||||
class SignalConnection : public std::enable_shared_from_this<SignalConnection> {
|
||||
protected:
|
||||
|
@ -23,7 +23,7 @@ protected:
|
|||
|
||||
SignalConnection(std::weak_ptr<Signal> parent);
|
||||
|
||||
virtual void Call(std::vector<Data::Variant>) = 0;
|
||||
virtual void Call(std::vector<Variant>) = 0;
|
||||
friend Signal;
|
||||
public:
|
||||
inline bool Connected() { return !parentSignal.expired(); };
|
||||
|
@ -33,13 +33,13 @@ public:
|
|||
};
|
||||
|
||||
class CSignalConnection : public SignalConnection {
|
||||
std::function<void(std::vector<Data::Variant>)> function;
|
||||
std::function<void(std::vector<Variant>)> function;
|
||||
|
||||
friend Signal;
|
||||
protected:
|
||||
void Call(std::vector<Data::Variant>) override;
|
||||
void Call(std::vector<Variant>) override;
|
||||
public:
|
||||
CSignalConnection(std::function<void(std::vector<Data::Variant>)>, std::weak_ptr<Signal> parent);
|
||||
CSignalConnection(std::function<void(std::vector<Variant>)>, std::weak_ptr<Signal> parent);
|
||||
};
|
||||
|
||||
class LuaSignalConnection : public SignalConnection {
|
||||
|
@ -48,7 +48,7 @@ class LuaSignalConnection : public SignalConnection {
|
|||
|
||||
friend Signal;
|
||||
protected:
|
||||
void Call(std::vector<Data::Variant>) override;
|
||||
void Call(std::vector<Variant>) override;
|
||||
public:
|
||||
LuaSignalConnection(lua_State*, std::weak_ptr<Signal> parent);
|
||||
LuaSignalConnection (const LuaSignalConnection&) = delete;
|
||||
|
@ -63,7 +63,7 @@ class SignalConnectionHolder {
|
|||
public:
|
||||
SignalConnectionHolder();
|
||||
SignalConnectionHolder(std::shared_ptr<SignalConnection>);
|
||||
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<Data::Variant> args);
|
||||
void Fire(std::vector<Variant> args);
|
||||
void Fire();
|
||||
Data::SignalConnectionRef Connect(std::function<void(std::vector<Data::Variant>)> callback);
|
||||
Data::SignalConnectionRef Connect(lua_State*);
|
||||
Data::SignalConnectionRef Once(std::function<void(std::vector<Data::Variant>)> callback);
|
||||
Data::SignalConnectionRef Once(lua_State*);
|
||||
SignalConnectionRef Connect(std::function<void(std::vector<Variant>)> callback);
|
||||
SignalConnectionRef Connect(lua_State*);
|
||||
SignalConnectionRef Once(std::function<void(std::vector<Variant>)> 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> signal;
|
||||
class SignalRef {
|
||||
std::weak_ptr<Signal> signal;
|
||||
|
||||
public:
|
||||
SignalRef(std::weak_ptr<Signal>);
|
||||
~SignalRef();
|
||||
public:
|
||||
SignalRef(std::weak_ptr<Signal>);
|
||||
~SignalRef();
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
operator std::weak_ptr<Signal>();
|
||||
operator std::weak_ptr<Signal>();
|
||||
|
||||
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<Data::Variant, LuaCastError> 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<Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
||||
};
|
||||
|
||||
class SignalConnectionRef : public Data::Base {
|
||||
std::weak_ptr<SignalConnection> signalConnection;
|
||||
class SignalConnectionRef {
|
||||
std::weak_ptr<SignalConnection> signalConnection;
|
||||
|
||||
public:
|
||||
SignalConnectionRef(std::weak_ptr<SignalConnection>);
|
||||
~SignalConnectionRef();
|
||||
public:
|
||||
SignalConnectionRef(std::weak_ptr<SignalConnection>);
|
||||
~SignalConnectionRef();
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
operator std::weak_ptr<SignalConnection>();
|
||||
operator std::weak_ptr<SignalConnection>();
|
||||
|
||||
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<Data::Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
||||
};
|
||||
}
|
||||
|
||||
using Data::SignalRef;
|
||||
using Data::SignalConnectionRef;
|
||||
virtual const std::string ToString() const;
|
||||
virtual void Serialize(pugi::xml_node node) const;
|
||||
virtual void PushLuaValue(lua_State*) const;
|
||||
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
||||
};
|
68
core/src/datatypes/variant.cpp
Normal file
68
core/src/datatypes/variant.cpp
Normal file
|
@ -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 <pugixml.hpp>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
[[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<std::string, const TypeInfo*> 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 },
|
||||
};
|
61
core/src/datatypes/variant.h
Normal file
61
core/src/datatypes/variant.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include <map>
|
||||
#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 <typename T> Variant(T obj) : wrapped(obj) {}
|
||||
template <typename T> T get() { return std::get<T>(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 <typename T, typename R, typename ...Args>
|
||||
std::function<R(Variant, Args...)> toVariantFunction(R(T::*f)(Args...)) {
|
||||
return [f](Variant var, Args... args) {
|
||||
return (var.get<T>().*f)(args...);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename ...Args>
|
||||
std::function<R(Variant, Args...)> toVariantFunction(R(T::*f)(Args...) const) {
|
||||
return [f](Variant var, Args... args) {
|
||||
return (var.get<T>().*f)(args...);
|
||||
};
|
||||
}
|
||||
|
||||
// Map of all data types to their type names
|
||||
extern std::map<std::string, const TypeInfo*> TYPE_MAP;
|
|
@ -7,91 +7,91 @@
|
|||
#include <string>
|
||||
#include <pugixml.hpp>
|
||||
#include "datatypes/base.h"
|
||||
#include "datatypes/meta.h"
|
||||
#include "datatypes/variant.h"
|
||||
#include <sstream>
|
||||
|
||||
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::Variant> Data::Vector3::FromString(std::string string) {
|
||||
std::optional<Variant> Vector3::FromString(std::string string) {
|
||||
float components[3];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
@ -109,5 +109,5 @@ std::optional<Data::Variant> 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]);
|
||||
}
|
|
@ -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<Variant> 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<Data::Variant> 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());
|
||||
}
|
|
@ -37,8 +37,8 @@
|
|||
#define AUTOGEN_PREAMBLE \
|
||||
protected: \
|
||||
virtual result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name) override; \
|
||||
virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value) override; \
|
||||
virtual result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name) override; \
|
||||
virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Variant value) override; \
|
||||
virtual result<Variant, MemberNotFound> InternalGetPropertyValue(std::string name) override; \
|
||||
virtual void InternalUpdateProperty(std::string name) override; \
|
||||
virtual std::vector<std::string> InternalGetProperties() override; \
|
||||
public: \
|
||||
|
|
|
@ -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<std::shared_ptr<Instance>> 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<Workspace> oldWorkspace) {
|
|||
|
||||
// Properties
|
||||
|
||||
result<Data::Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) {
|
||||
result<Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) {
|
||||
return InternalGetPropertyValue(name);
|
||||
}
|
||||
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::SetPropertyValue(std::string name, Data::Variant value, bool sendUpdateEvent) {
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> 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<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name)
|
|||
}
|
||||
|
||||
|
||||
result<Data::Variant, MemberNotFound> Instance::InternalGetPropertyValue(std::string name) {
|
||||
result<Variant, MemberNotFound> 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<PropertyMeta, MemberNotFound> 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<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyValue(std::string name, Data::Variant value) {
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyValue(std::string name, Variant value) {
|
||||
if (name == "Name") {
|
||||
this->name = (std::string)value.get<Data::String>();
|
||||
this->name = (std::string)value.get<std::string>();
|
||||
} else if (name == "Parent") {
|
||||
std::weak_ptr<Instance> ref = value.get<Data::InstanceRef>();
|
||||
std::weak_ptr<Instance> ref = value.get<InstanceRef>();
|
||||
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<Instance> properties using map above
|
||||
if (meta.type == &Data::InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(name).expect("Declared property is missing").get<Data::InstanceRef>();
|
||||
if (meta.type == &InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(name).expect("Declared property is missing").get<InstanceRef>();
|
||||
if (refWeak.expired()) continue;
|
||||
|
||||
auto ref = refWeak.lock();
|
||||
|
@ -333,7 +334,7 @@ result<std::shared_ptr<Instance>, NoSuchInstance> Instance::Deserialize(pugi::xm
|
|||
}
|
||||
|
||||
// Update std::shared_ptr<Instance> 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<std::shared_ptr<Instance>, 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<std::shared_ptr<Instance>, NoSuchInstance> Instance::Deserialize(pugi::xm
|
|||
|
||||
// Remap queued properties
|
||||
for (std::pair<std::shared_ptr<Instance>, 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<std::shared_ptr<Instance>> Instance::Clone(RefStateClone state) {
|
|||
if (meta.flags & (PROP_READONLY | PROP_NOSAVE)) continue;
|
||||
|
||||
// Update std::shared_ptr<Instance> properties using map above
|
||||
if (meta.type == &Data::InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(property).expect().get<Data::InstanceRef>();
|
||||
if (meta.type == &InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(property).expect().get<InstanceRef>();
|
||||
if (refWeak.expired()) continue;
|
||||
|
||||
auto ref = refWeak.lock();
|
||||
|
@ -444,17 +445,17 @@ std::optional<std::shared_ptr<Instance>> 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<std::shared_ptr<Instance>> Instance::Clone(RefStateClone state) {
|
|||
|
||||
// Remap queued properties
|
||||
for (std::pair<std::shared_ptr<Instance>, 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<std::pair<std::string, std::shared_ptr<Instance>>> 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<Instance> ref = GetPropertyValue(property).expect().get<Data::InstanceRef>();
|
||||
std::weak_ptr<Instance> ref = GetPropertyValue(property).expect().get<InstanceRef>();
|
||||
if (ref.expired()) continue;
|
||||
referenceProperties.push_back(std::make_pair(property, ref.lock()));
|
||||
}
|
||||
|
|
|
@ -69,8 +69,8 @@ protected:
|
|||
Instance(const InstanceType*);
|
||||
virtual ~Instance();
|
||||
|
||||
virtual result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name);
|
||||
virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value);
|
||||
virtual result<Variant, MemberNotFound> InternalGetPropertyValue(std::string name);
|
||||
virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Variant value);
|
||||
virtual result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name);
|
||||
virtual void InternalUpdateProperty(std::string name);
|
||||
virtual std::vector<std::string> InternalGetProperties();
|
||||
|
@ -114,8 +114,8 @@ public:
|
|||
std::string GetFullName();
|
||||
|
||||
// Properties
|
||||
result<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> SetPropertyValue(std::string name, Data::Variant value, bool sendUpdateEvent = true);
|
||||
result<Variant, MemberNotFound> GetPropertyValue(std::string name);
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> SetPropertyValue(std::string name, Variant value, bool sendUpdateEvent = true);
|
||||
result<PropertyMeta, MemberNotFound> GetPropertyMeta(std::string name);
|
||||
// Manually trigger the update of a property. Useful internally when setting properties directly
|
||||
void UpdateProperty(std::string name);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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> DataModel::CloneModel() {
|
|||
if (meta.flags & (PROP_READONLY | PROP_NOSAVE)) continue;
|
||||
|
||||
// Update std::shared_ptr<Instance> properties using map above
|
||||
if (meta.type == &Data::InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(property).expect().get<Data::InstanceRef>();
|
||||
if (meta.type == &InstanceRef::TYPE) {
|
||||
std::weak_ptr<Instance> refWeak = GetPropertyValue(property).expect().get<InstanceRef>();
|
||||
if (refWeak.expired()) continue;
|
||||
|
||||
auto ref = refWeak.lock();
|
||||
|
@ -140,17 +140,17 @@ std::shared_ptr<DataModel> 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> DataModel::CloneModel() {
|
|||
|
||||
// Remap queued properties
|
||||
for (std::pair<std::shared_ptr<Instance>, 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
|
||||
|
|
|
@ -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<Workspace>()).PushLuaValue(Lt);
|
||||
InstanceRef(dataModel().value()->GetService<Workspace>()).PushLuaValue(Lt);
|
||||
lua_setfield(Lt, -2, "workspace");
|
||||
|
||||
lua_pushlightuserdata(Lt, scriptContext.get());
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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<Part*>(pair.getBody2()->getUserData())->shared<Part>();
|
||||
|
||||
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) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
void addDebugRenderCFrame(CFrame);
|
||||
void addDebugRenderCFrame(CFrame, Color3);
|
|
@ -20,6 +20,6 @@ enum SurfaceType {
|
|||
SurfaceMotor = 7,
|
||||
};
|
||||
|
||||
namespace Data { class Vector3; } using Data::Vector3;
|
||||
class Vector3;
|
||||
NormalId faceFromNormal(Vector3);
|
||||
Vector3 normalFromFace(NormalId);
|
|
@ -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<MainWindow*>(window())
|
||||
|
|
|
@ -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 <QColorDialog>
|
||||
|
@ -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<Data::Float>());
|
||||
spinBox->setValue(currentValue.get<float>());
|
||||
|
||||
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<Data::Int>());
|
||||
spinBox->setValue(currentValue.get<int>());
|
||||
|
||||
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<Data::String>()));
|
||||
lineEdit->setText(QString::fromStdString(currentValue.get<std::string>()));
|
||||
|
||||
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<QDoubleSpinBox*>(editor);
|
||||
|
||||
spinBox->setValue(currentValue.get<Data::Float>());
|
||||
} else if (meta.type == &Data::Int::TYPE) {
|
||||
spinBox->setValue(currentValue.get<float>());
|
||||
} else if (meta.type == &INT_TYPE) {
|
||||
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor);
|
||||
|
||||
spinBox->setValue(currentValue.get<Data::Int>());
|
||||
} else if (meta.type == &Data::String::TYPE) {
|
||||
spinBox->setValue(currentValue.get<int>());
|
||||
} else if (meta.type == &STRING_TYPE) {
|
||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
||||
|
||||
lineEdit->setText(QString::fromStdString((std::string)currentValue.get<Data::String>()));
|
||||
lineEdit->setText(QString::fromStdString((std::string)currentValue.get<std::string>()));
|
||||
} else if (meta.type == &Color3::TYPE) {
|
||||
QColorDialog* colorDialog = dynamic_cast<QColorDialog*>(editor);
|
||||
|
||||
|
@ -186,20 +187,20 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if (meta.type == &Data::Float::TYPE) {
|
||||
if (meta.type == &FLOAT_TYPE) {
|
||||
QDoubleSpinBox* spinBox = dynamic_cast<QDoubleSpinBox*>(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<QSpinBox*>(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<QLineEdit*>(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<QColorDialog*>(editor);
|
||||
|
@ -212,7 +213,7 @@ public:
|
|||
} else if (meta.type->fromString) {
|
||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
||||
|
||||
std::optional<Data::Variant> parsedResult = meta.type->fromString(lineEdit->text().toStdString());
|
||||
std::optional<Variant> 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<std::shared_ptr<Instance>> 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<std::shared_ptr<Instance>> 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<Data::Bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
if (meta.type == &BOOL_TYPE) {
|
||||
item->setCheckState(1, (bool)currentValue.get<bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
} else if (meta.type == &Color3::TYPE) {
|
||||
Color3 color = currentValue.get<Color3>();
|
||||
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<Instance> inst, std::string property, Data::Variant newValue) {
|
||||
void PropertiesView::onPropertyUpdated(std::shared_ptr<Instance> inst, std::string property, Variant newValue) {
|
||||
// if (!currentInstance || currentInstance->expired() || instance != currentInstance->lock()) return;
|
||||
// if (std::chrono::duration_cast<std::chrono::milliseconds>(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<Instance> 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<Data::Bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
item->setCheckState(1, (bool)currentValue.get<bool>() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
ignorePropertyUpdates = false;
|
||||
} else if (meta.type == &Color3::TYPE) {
|
||||
Color3 color = currentValue.get<Color3>();
|
||||
|
|
|
@ -15,8 +15,8 @@ class PropertiesView : public QTreeWidget {
|
|||
std::weak_ptr<Instance> 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> instance, std::string property, Data::Variant newValue);
|
||||
void rebuildCompositeProperty(QTreeWidgetItem *item, const TypeInfo*, Variant);
|
||||
void onPropertyUpdated(std::shared_ptr<Instance> instance, std::string property, Variant newValue);
|
||||
|
||||
friend PropertiesItemDelegate;
|
||||
protected:
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <qtextformat.h>
|
||||
#include "mainwindow.h"
|
||||
#include "objects/script.h"
|
||||
#include "datatypes/meta.h"
|
||||
#include "datatypes/variant.h"
|
||||
#include <QPalette>
|
||||
#include <QStyleHints>
|
||||
|
||||
|
@ -115,9 +115,9 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
|
|||
setWindowTitle(QString::fromStdString(script->name));
|
||||
|
||||
// Add detector for script deletion to automatically close this document
|
||||
scriptDeletionHandler = script->AncestryChanged->Connect([this, script](std::vector<Data::Variant> args) {
|
||||
std::weak_ptr<Instance> child = args[0].get<Data::InstanceRef>();
|
||||
std::weak_ptr<Instance> newParent = args[1].get<Data::InstanceRef>();
|
||||
scriptDeletionHandler = script->AncestryChanged->Connect([this, script](std::vector<Variant> args) {
|
||||
std::weak_ptr<Instance> child = args[0].get<InstanceRef>();
|
||||
std::weak_ptr<Instance> newParent = args[1].get<InstanceRef>();
|
||||
if (child.expired() || child.lock() != script || !newParent.expired()) return;
|
||||
|
||||
dynamic_cast<MainWindow*>(window())->closeScriptDocument(script);
|
||||
|
|
Loading…
Add table
Reference in a new issue