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 "analysis.h"
#include <fstream>
#include <map>
#include <string>
#include <variant>
#include <vector>
using namespace enum_;
@ -17,7 +15,7 @@ void enum_::writeCodeForClass(std::ofstream& out, std::string headerPath, EnumAn
out << " { " << entry.value << ", \"" << entry.name << "\" },\n";
}
out << "};";
out << "};\n\n";
out << "static _EnumData __data_" << state.name << " = {\n"
<< " \"" << state.name << "\",\n"
@ -26,6 +24,8 @@ void enum_::writeCodeForClass(std::ofstream& out, std::string headerPath, EnumAn
<< "};\n\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";
}

View file

@ -80,7 +80,13 @@ static void processField(CXCursor cur, ClassAnalysis* state) {
anly.flags = anly.flags | PropertyFlags::PropertyFlag_Readonly;
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);

View file

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

View file

@ -89,6 +89,8 @@ static void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
} else if (!subtype.empty()) {
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 if (prop.backingFieldType == "EnumItem") {
out << "\n this->" << prop.fieldName << " = (" << prop.backingFieldEnum << ")value.get<EnumItem>().Value();";
} else {
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());";
} else if (prop.cframeMember == CFrameMember_Rotation) {
out << "\n return Variant(" << prop.fieldName << ".ToEulerAnglesXYZ());";
} else if (prop.backingFieldType == "EnumItem") {
out << "\n return Variant(EnumType::" << prop.backingFieldEnum << ".FromValueInternal(" << prop.fieldName << "));";
} else {
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];
if (typeInfo.empty()) typeInfo = prop.backingFieldType + "::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;
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 << "#include \"" << state.headerPath << "\"\n\n";
out << "#include \"datatypes/variant.h\"\n\n";
out << "#include \"datatypes/primitives.h\"\n\n";
out << "#include \"datatypes/variant.h\"\n";
out << "#include \"datatypes/primitives.h\"\n";
out << "const InstanceType " << state.name << "::TYPE = {\n"
<< " .super = &" << state.baseClass << "::TYPE,\n"
<< " .className = \"" << state.name << "\",\n"

View file

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

View file

@ -4,7 +4,7 @@
#include "error/data.h"
#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) {}
@ -34,6 +34,12 @@ std::optional<EnumItem> Enum::FromValue(int value) const {
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) {}
//

View file

@ -28,6 +28,8 @@ public:
std::optional<EnumItem> FromName(std::string) const;
std::optional<EnumItem> FromValue(int) const;
EnumItem FromValueInternal(int) const;
std::string ToString() const;
void PushLuaValue(lua_State*) const;
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int);

View file

@ -10,7 +10,7 @@
#include "objects/base/member.h"
#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(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"