feat(autogen): enum integration with objects

This commit is contained in:
maelstrom 2025-06-05 00:24:25 +02:00
parent 46856a06e2
commit 1f296e5fe4
9 changed files with 36 additions and 14 deletions

View file

@ -1,9 +1,7 @@
#include "codegen.h" #include "codegen.h"
#include "analysis.h" #include "analysis.h"
#include <fstream> #include <fstream>
#include <map>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
using namespace enum_; using namespace enum_;
@ -17,7 +15,7 @@ void enum_::writeCodeForClass(std::ofstream& out, std::string headerPath, EnumAn
out << " { " << entry.value << ", \"" << entry.name << "\" },\n"; out << " { " << entry.value << ", \"" << entry.name << "\" },\n";
} }
out << "};"; out << "};\n\n";
out << "static _EnumData __data_" << state.name << " = {\n" out << "static _EnumData __data_" << state.name << " = {\n"
<< " \"" << state.name << "\",\n" << " \"" << state.name << "\",\n"
@ -26,6 +24,8 @@ void enum_::writeCodeForClass(std::ofstream& out, std::string headerPath, EnumAn
<< "};\n\n"; << "};\n\n";
out << "namespace EnumType {\n" out << "namespace EnumType {\n"
<< " const Enum " << state.name << "(&__data_" << state.name << ");\n" // extern is necessary here too to prevent "const" from marking Enum as implicitly static
// https://stackoverflow.com/questions/2190919/mixing-extern-and-const#comment2509591_2190981
<< " extern const Enum " << state.name << "(&__data_" << state.name << ");\n"
<< "}\n\n"; << "}\n\n";
} }

View file

@ -80,7 +80,13 @@ static void processField(CXCursor cur, ClassAnalysis* state) {
anly.flags = anly.flags | PropertyFlags::PropertyFlag_Readonly; anly.flags = anly.flags | PropertyFlags::PropertyFlag_Readonly;
CXType type = clang_getCursorType(cur); CXType type = clang_getCursorType(cur);
anly.backingFieldType = x_clang_toString(clang_getTypeSpelling(type)).c_str(); anly.backingFieldType = x_clang_toString(clang_getTypeSpelling(type));
CXCursor typeCur = clang_getTypeDeclaration(type);
bool isEnum = findAnnotation(typeCur, "OB::def_enum").has_value();
if (isEnum) {
anly.backingFieldType = "EnumItem";
anly.backingFieldEnum = x_clang_toString(clang_getTypeSpelling(type));
}
state->properties.push_back(anly); state->properties.push_back(anly);

View file

@ -31,6 +31,7 @@ struct PropertyAnalysis {
std::string fieldName; std::string fieldName;
CFrameMember cframeMember = CFrameMember_None; // for cframe_position_prop etc. CFrameMember cframeMember = CFrameMember_None; // for cframe_position_prop etc.
std::string backingFieldType; std::string backingFieldType;
std::string backingFieldEnum;
std::string onUpdateCallback; std::string onUpdateCallback;
std::string category; std::string category;
PropertyFlags flags = (PropertyFlags)0; PropertyFlags flags = (PropertyFlags)0;

View file

@ -89,6 +89,8 @@ static void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
} else if (!subtype.empty()) { } else if (!subtype.empty()) {
out << "\n std::weak_ptr<Instance> ref = value.get<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());"; << "\n this->" << prop.fieldName << " = ref.expired() ? std::weak_ptr<" << subtype << ">() : std::dynamic_pointer_cast<" << subtype << ">(ref.lock());";
} else if (prop.backingFieldType == "EnumItem") {
out << "\n this->" << prop.fieldName << " = (" << prop.backingFieldEnum << ")value.get<EnumItem>().Value();";
} else { } else {
out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";"; out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";";
} }
@ -143,6 +145,8 @@ static void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
out << "\n return Variant(" << prop.fieldName << ".Position());"; out << "\n return Variant(" << prop.fieldName << ".Position());";
} else if (prop.cframeMember == CFrameMember_Rotation) { } else if (prop.cframeMember == CFrameMember_Rotation) {
out << "\n return Variant(" << prop.fieldName << ".ToEulerAnglesXYZ());"; out << "\n return Variant(" << prop.fieldName << ".ToEulerAnglesXYZ());";
} else if (prop.backingFieldType == "EnumItem") {
out << "\n return Variant(EnumType::" << prop.backingFieldEnum << ".FromValueInternal(" << prop.fieldName << "));";
} else { } else {
out << "\n return Variant(" << castToVariant(prop.fieldName, prop.backingFieldType) << ");"; out << "\n return Variant(" << castToVariant(prop.fieldName, prop.backingFieldType) << ");";
} }
@ -193,7 +197,7 @@ static void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
std::string typeInfo = TYPEINFO_REFS[prop.backingFieldType]; std::string typeInfo = TYPEINFO_REFS[prop.backingFieldType];
if (typeInfo.empty()) typeInfo = prop.backingFieldType + "::TYPE"; if (typeInfo.empty()) typeInfo = prop.backingFieldType + "::TYPE";
if (!parseWeakPtr(prop.backingFieldType).empty()) typeInfo = "InstanceRef::TYPE"; if (!parseWeakPtr(prop.backingFieldType).empty()) typeInfo = "InstanceRef::TYPE";
if (prop.backingFieldType == "SurfaceType") typeInfo = "INT_TYPE"; if (prop.backingFieldType == "EnumItem") typeInfo = "EnumType::" + prop.backingFieldEnum;
std::string strFlags; std::string strFlags;
if (prop.flags & PropertyFlag_Readonly) if (prop.flags & PropertyFlag_Readonly)
@ -256,8 +260,8 @@ void object::writeCodeForClass(std::ofstream& out, std::string headerPath, Class
out << "#define __AUTOGEN_EXTRA_INCLUDES__\n"; out << "#define __AUTOGEN_EXTRA_INCLUDES__\n";
out << "#include \"" << state.headerPath << "\"\n\n"; out << "#include \"" << state.headerPath << "\"\n\n";
out << "#include \"datatypes/variant.h\"\n\n"; out << "#include \"datatypes/variant.h\"\n";
out << "#include \"datatypes/primitives.h\"\n\n"; out << "#include \"datatypes/primitives.h\"\n";
out << "const InstanceType " << state.name << "::TYPE = {\n" out << "const InstanceType " << state.name << "::TYPE = {\n"
<< " .super = &" << state.baseClass << "::TYPE,\n" << " .super = &" << state.baseClass << "::TYPE,\n"
<< " .className = \"" << state.name << "\",\n" << " .className = \"" << state.name << "\",\n"

View file

@ -38,11 +38,11 @@ struct InstanceType;
struct TypeMeta { struct TypeMeta {
const TypeDesc* descriptor; const TypeDesc* descriptor;
union { union {
Enum* enum_; // Applicable for EnumItem const Enum* enum_; // Applicable for EnumItem
InstanceType* instType; // Applicable for InstanceRef const InstanceType* instType; // Applicable for InstanceRef
}; };
inline TypeMeta(const TypeDesc* descriptor) : descriptor(descriptor) {} inline TypeMeta(const TypeDesc* descriptor) : descriptor(descriptor) {}
TypeMeta(Enum*); TypeMeta(const Enum*);
TypeMeta(InstanceType*); TypeMeta(const InstanceType*);
}; };

View file

@ -4,7 +4,7 @@
#include "error/data.h" #include "error/data.h"
#include <pugixml.hpp> #include <pugixml.hpp>
TypeMeta::TypeMeta(Enum* enum_) : enum_(enum_), descriptor(&EnumItem::TYPE) {} TypeMeta::TypeMeta(const Enum* enum_) : enum_(enum_), descriptor(&EnumItem::TYPE) {}
Enum::Enum(_EnumData* data) : data(data) {} Enum::Enum(_EnumData* data) : data(data) {}
@ -34,6 +34,12 @@ std::optional<EnumItem> Enum::FromValue(int value) const {
return {}; return {};
} }
EnumItem Enum::FromValueInternal(int value) const {
auto result = this->FromValue(value);
if (!result) return EnumItem(data, "", value);
return result.value();
}
EnumItem::EnumItem(_EnumData* parentData, std::string name, int value) : parentData(parentData), name(name), value(value) {} EnumItem::EnumItem(_EnumData* parentData, std::string name, int value) : parentData(parentData), name(name), value(value) {}
// //

View file

@ -27,6 +27,8 @@ public:
std::vector<EnumItem> GetEnumItems() const; std::vector<EnumItem> GetEnumItems() const;
std::optional<EnumItem> FromName(std::string) const; std::optional<EnumItem> FromName(std::string) const;
std::optional<EnumItem> FromValue(int) const; std::optional<EnumItem> FromValue(int) const;
EnumItem FromValueInternal(int) const;
std::string ToString() const; std::string ToString() const;
void PushLuaValue(lua_State*) const; void PushLuaValue(lua_State*) const;

View file

@ -10,7 +10,7 @@
#include "objects/base/member.h" #include "objects/base/member.h"
#include <pugixml.hpp> #include <pugixml.hpp>
TypeMeta::TypeMeta(InstanceType* instType) : instType(instType), descriptor(&InstanceRef::TYPE) {} TypeMeta::TypeMeta(const InstanceType* instType) : instType(instType), descriptor(&InstanceRef::TYPE) {}
InstanceRef::InstanceRef() {}; InstanceRef::InstanceRef() {};
InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {}; InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {};

3
core/src/enum/meta.h Normal file
View file

@ -0,0 +1,3 @@
#pragma once
#include "surface.h"