feat(autogen): integrate autogen and add method for setters
This commit is contained in:
parent
8049d45b43
commit
8f20c11b36
10 changed files with 100 additions and 31 deletions
|
@ -5,6 +5,8 @@ set(OpenGL_GL_PREFERENCE "GLVND")
|
|||
|
||||
set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" )
|
||||
|
||||
add_subdirectory(autogen)
|
||||
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
|
|
|
@ -211,13 +211,13 @@ void processClass(CXCursor cur, AnalysisState* state, std::string className, std
|
|||
|
||||
// https://clang.llvm.org/docs/LibClang.html
|
||||
bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state) {
|
||||
const char* cargs[] = { "-x", "c++", "-I", srcRoot.c_str(), 0 };
|
||||
const char* cargs[] = { "-x", "c++", "-I", srcRoot.c_str(), "-D__AUTOGEN__", 0 };
|
||||
// THANK YOU SO MUCH THIS STACKOVERFLOW ANSWER IS SO HELPFUL
|
||||
// https://stackoverflow.com/a/59206378/16255372
|
||||
CXIndex index = clang_createIndex(0, 0);
|
||||
CXTranslationUnit unit = clang_parseTranslationUnit(
|
||||
index,
|
||||
path.c_str(), cargs, 4,
|
||||
path.c_str(), cargs, 5,
|
||||
nullptr, 0,
|
||||
CXTranslationUnit_None);
|
||||
|
||||
|
|
|
@ -1,5 +1,54 @@
|
|||
#include "codegen.h"
|
||||
#include "analysis.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
std::map<std::string, std::string> MAPPED_TYPE = {
|
||||
{ "bool", "Data::Bool" },
|
||||
{ "int", "Data::Int" },
|
||||
{ "float", "Data::Float" },
|
||||
{ "std::string", "Data::String" },
|
||||
{ "std::weak_ptr<Instance>", "Data::InstanceRef" },
|
||||
{ "glm::vec3", "Vector3" },
|
||||
};
|
||||
|
||||
std::map<std::string, std::monostate> ENUM_TYPES = {
|
||||
{ "SurfaceType", std::monostate() }
|
||||
};
|
||||
|
||||
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>()";
|
||||
}
|
||||
|
||||
std::string mappedType = MAPPED_TYPE[fieldType];
|
||||
return valueStr + ".get<" + (!mappedType.empty() ? mappedType : fieldType) + ">()";
|
||||
}
|
||||
|
||||
void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "fallible<MemberNotFound, AssignToReadOnlyMember> " << state.name << "::InternalSetPropertyValue(std::string name, Data::Variant value) {";
|
||||
|
||||
out << "\n ";
|
||||
bool first = true;
|
||||
for (auto& prop : state.properties) {
|
||||
out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {";
|
||||
|
||||
if (prop.flags & PropertyFlag_Readonly) {
|
||||
out << "\n return AssignToReadOnlyMember(\"" << state.name << "\", name)";
|
||||
} else {
|
||||
out << "\n this->" << prop.fieldName << " = " << castFromVariant("value", prop.backingFieldType) << ";";
|
||||
}
|
||||
|
||||
out << "\n }";
|
||||
first = false;
|
||||
}
|
||||
|
||||
out << "\n return MemberNotFound(\"" << state.name << "\", name);";
|
||||
|
||||
out << "\n};\n\n";
|
||||
}
|
||||
|
||||
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
||||
std::string strFlags;
|
||||
|
@ -24,4 +73,6 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
|||
out << "const InstanceType* " << state.name << "::GetClass() {\n"
|
||||
<< " return &TYPE;\n"
|
||||
<< "};\n\n";
|
||||
|
||||
writePropertySetHandler(out, state);
|
||||
}
|
|
@ -40,17 +40,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
AnalysisState state;
|
||||
|
||||
analyzeClasses("../core/src/objects/part.h", argv[1], &state);
|
||||
|
||||
printf("[AUTOGEN] Generating cpp files...\n");
|
||||
for (auto& [_, clazz] : state.classes) {
|
||||
fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp");
|
||||
std::ofstream outStream(outPath);
|
||||
|
||||
writeCodeForClass(outStream, clazz);
|
||||
outStream.close();
|
||||
}
|
||||
|
||||
// analyzeClasses("../core/src/objects/part.h", argv[1], &state);
|
||||
// for (auto& [_, clazz] : state.classes) {
|
||||
// printf("Class: %s\n", clazz.name.c_str());
|
||||
// if (clazz.baseClass != "")
|
||||
|
@ -74,11 +64,21 @@ int main(int argc, char** argv) {
|
|||
// }
|
||||
|
||||
// First-pass: Analyze type hierarchy
|
||||
// for (std::string path : headerFiles) {
|
||||
// fs::path relpath = fs::relative(path, argv[1]);
|
||||
// printf("[AUTOGEN] Processing file %s...\n", relpath.c_str());
|
||||
// analyzeClasses(path, argv[1], &state);
|
||||
// }
|
||||
for (std::string path : headerFiles) {
|
||||
fs::path relpath = fs::relative(path, argv[1]);
|
||||
printf("[AUTOGEN] Processing file %s...\n", relpath.c_str());
|
||||
analyzeClasses(path, argv[1], &state);
|
||||
}
|
||||
|
||||
printf("[AUTOGEN] Generating cpp files...\n");
|
||||
for (auto& [_, clazz] : state.classes) {
|
||||
fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp");
|
||||
std::ofstream outStream(outPath);
|
||||
|
||||
writeCodeForClass(outStream, clazz);
|
||||
outStream.close();
|
||||
}
|
||||
|
||||
|
||||
flushCaches(argv[3]);
|
||||
}
|
|
@ -15,7 +15,12 @@ include_directories(${Stb_INCLUDE_DIR})
|
|||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LUAJIT REQUIRED luajit)
|
||||
|
||||
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
|
||||
# Run autogen
|
||||
add_custom_target(build_autogen ALL
|
||||
COMMAND "${CMAKE_BINARY_DIR}/autogen/autogen" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/objects" "${CMAKE_BINARY_DIR}/generated"
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h" "${CMAKE_BINARY_DIR}/generated/*.cpp")
|
||||
add_library(openblocks STATIC ${SOURCES})
|
||||
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
|
|
|
@ -2,9 +2,23 @@
|
|||
|
||||
// Markers for the autogen engine to generate getters, setters, lua, etc.
|
||||
|
||||
#ifdef __AUTOGEN__
|
||||
#define def_inst(...) clang::annotate("OB::def_inst", #__VA_ARGS__)
|
||||
|
||||
#define def_prop(...) clang::annotate("OB::def_prop", #__VA_ARGS__)
|
||||
|
||||
#define cframe_position_prop(...) clang::annotate("OB::cframe_position_prop", #__VA_ARGS__)
|
||||
#define cframe_rotation_prop(...) clang::annotate("OB::cframe_rotation_prop", #__VA_ARGS__)
|
||||
#define cframe_rotation_prop(...) clang::annotate("OB::cframe_rotation_prop", #__VA_ARGS__)
|
||||
#else
|
||||
#define def_inst(...)
|
||||
#define def_prop(...)
|
||||
#define cframe_position_prop(...)
|
||||
#define cframe_rotation_prop(...)
|
||||
#endif
|
||||
|
||||
#define AUTOGEN_PREAMBLE \
|
||||
private: \
|
||||
result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name) override; \
|
||||
fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value) override; \
|
||||
result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name) override; \
|
||||
private:
|
||||
|
|
|
@ -211,6 +211,9 @@ fallible<MemberNotFound, AssignToReadOnlyMember> Instance::SetPropertyValue(std:
|
|||
return {};
|
||||
}
|
||||
|
||||
if (InternalSetPropertyValue(name, value).isSuccess())
|
||||
return {};
|
||||
|
||||
auto meta_ = GetPropertyMeta(name);
|
||||
if (!meta_) return MemberNotFound(GetClass()->className, name);
|
||||
auto meta = meta_.expect();
|
||||
|
|
|
@ -70,6 +70,10 @@ 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<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name);
|
||||
|
||||
virtual void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent);
|
||||
virtual void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);
|
||||
virtual void OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace);
|
||||
|
|
|
@ -50,17 +50,6 @@ constexpr FieldCodec cframeRotationCodec() {
|
|||
};
|
||||
}
|
||||
|
||||
const InstanceType Part::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "Part",
|
||||
.constructor = &Part::CreateGeneric,
|
||||
.explorerIcon = "part",
|
||||
};
|
||||
|
||||
const InstanceType* Part::GetClass() {
|
||||
return &TYPE;
|
||||
}
|
||||
|
||||
Part::Part(): Part(PartConstructParams { .size = glm::vec3(2, 1.2, 4), .color = Color3(0.639216f, 0.635294f, 0.647059f) }) {
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ struct PartConstructParams {
|
|||
class Snap;
|
||||
|
||||
class [[ def_inst(explorer_icon="part") ]] Part : public Instance {
|
||||
AUTOGEN_PREAMBLE
|
||||
protected:
|
||||
// Joints where this part is Part0
|
||||
std::vector<std::weak_ptr<JointInstance>> primaryJoints;
|
||||
|
|
Loading…
Add table
Reference in a new issue