feat(autogen): convert classes to new autogen annotations

This commit is contained in:
maelstrom 2025-04-26 13:19:47 +02:00
parent b8ee828d29
commit a2e2210998
31 changed files with 148 additions and 343 deletions

View file

@ -24,7 +24,8 @@ std::map<std::string, std::string> parseAnnotationString(std::string src) {
int i = 0; int i = 0;
for (; i < src.length(); i++) { for (; i < src.length(); i++) {
if (src[i] == ' ' && (stage != 2 || !quoted)) continue; // Ignore spaces if not in stage 2 and quoted if (src[i] == ' ' && (stage != 2 || !quoted)) continue; // Ignore spaces if not in stage 2 and quoted
if (src[i] == ',' && stage == 0) continue; // Let empty commas slip by
if (stage < 2 && (src[i] >= 'a' && src[i] <= 'z' || src[i] >= 'A' && src[i] <= 'Z' || src[i] >= '0' && src[i] <= '9' || src[i] == '_')) { if (stage < 2 && (src[i] >= 'a' && src[i] <= 'z' || src[i] >= 'A' && src[i] <= 'Z' || src[i] >= '0' && src[i] <= '9' || src[i] == '_')) {
currentIdent += src[i]; currentIdent += src[i];
stage = 1; stage = 1;
@ -228,6 +229,8 @@ void processClass(CXCursor cur, AnalysisState* state, std::string className, std
if (result.count("hidden")) if (result.count("hidden"))
anly.flags = anly.flags | ClassFlag_Hidden; anly.flags = anly.flags | ClassFlag_Hidden;
anly.abstract = result.count("abstract") > 0;
anly.explorerIcon = result["explorer_icon"]; anly.explorerIcon = result["explorer_icon"];
// Find annotated fields // Find annotated fields

View file

@ -46,6 +46,7 @@ struct ClassAnalysis {
std::string name; std::string name;
std::string baseClass; std::string baseClass;
std::string headerPath; std::string headerPath;
bool abstract = false;
std::vector<PropertyAnalysis> properties; std::vector<PropertyAnalysis> properties;
ClassFlags flags = (ClassFlags)0; ClassFlags flags = (ClassFlags)0;
std::string explorerIcon; std::string explorerIcon;

View file

@ -18,6 +18,7 @@ std::map<std::string, std::string> MAPPED_TYPE = {
{ "float", "Data::Float" }, { "float", "Data::Float" },
{ "std::string", "Data::String" }, { "std::string", "Data::String" },
{ "std::weak_ptr<Instance>", "Data::InstanceRef" }, { "std::weak_ptr<Instance>", "Data::InstanceRef" },
{ "std::weak_ptr<Part>", "Data::InstanceRef" },
{ "glm::vec3", "Vector3" }, { "glm::vec3", "Vector3" },
}; };
@ -57,7 +58,7 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {"; out << (first ? "" : " else ") << "if (name == \"" << prop.name << "\") {";
if (prop.flags & PropertyFlag_Readonly) { if (prop.flags & PropertyFlag_Readonly) {
out << "\n return AssignToReadOnlyMember(\"" << state.name << "\", name)"; out << "\n return AssignToReadOnlyMember(GetClass()->className, name)";
} else if (prop.cframeMember == CFrameMember_Position) { } else if (prop.cframeMember == CFrameMember_Position) {
out << "\n this->" << prop.fieldName << " = this->" << prop.fieldName << ".Rotation() + value.get<Vector3>();"; out << "\n this->" << prop.fieldName << " = this->" << prop.fieldName << ".Rotation() + value.get<Vector3>();";
} else if (prop.cframeMember == CFrameMember_Rotation) { } else if (prop.cframeMember == CFrameMember_Rotation) {
@ -72,7 +73,8 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
first = false; first = false;
} }
out << "\n return MemberNotFound(\"" << state.name << "\", name);"; out << "\n return " << state.baseClass << "::InternalSetPropertyValue(name, value);";
// out << "\n return MemberNotFound(\"" << state.name << "\", name);";
out << "\n};\n\n"; out << "\n};\n\n";
} }
@ -97,11 +99,23 @@ void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
first = false; first = false;
} }
out << "\n return MemberNotFound(\"" << state.name << "\", name);"; out << "\n return " << state.baseClass << "::InternalGetPropertyValue(name);";
// out << "\n return MemberNotFound(\"" << state.name << "\", name);";
out << "\n};\n\n"; out << "\n};\n\n";
} }
void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
out << "std::vector<string> " << state.name << "::InternalGetProperties() {\n";
out << " std::vector<string> properties = " << state.baseClass << "::InternalGetProperties();\n";
for (auto& prop : state.properties) {
out << " properties.push_back(\"" << prop.name << "\")l\n";
}
out << "};\n\n";
}
void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) { void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
out << "result<PropertyMeta, MemberNotFound> " << state.name << "::InternalGetPropertyMeta(std::string name) {"; out << "result<PropertyMeta, MemberNotFound> " << state.name << "::InternalGetPropertyMeta(std::string name) {";
@ -135,7 +149,8 @@ void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
first = false; first = false;
} }
out << "\n return MemberNotFound(\"" << state.name << "\", name);"; out << "\n return " << state.baseClass << "::InternalGetPropertyMeta(name);";
// out << "\n return MemberNotFound(\"" << state.name << "\", name);";
out << "\n};\n\n"; out << "\n};\n\n";
} }
@ -143,7 +158,7 @@ void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) { void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
std::string strFlags; std::string strFlags;
if (state.flags & ClassFlag_NotCreatable) if (state.flags & ClassFlag_NotCreatable)
strFlags += " | INSTANCE_NOT_CREATABLE"; strFlags += " | INSTANCE_NOTCREATABLE";
if (state.flags & ClassFlag_Service) if (state.flags & ClassFlag_Service)
strFlags += " | INSTANCE_SERVICE"; strFlags += " | INSTANCE_SERVICE";
if (state.flags & ClassFlag_Hidden) if (state.flags & ClassFlag_Hidden)
@ -155,11 +170,15 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
out << "// This file was automatically generated by autogen, and should not be edited manually //\n"; out << "// This file was automatically generated by autogen, and should not be edited manually //\n";
out << "/////////////////////////////////////////////////////////////////////////////////////////\n\n"; out << "/////////////////////////////////////////////////////////////////////////////////////////\n\n";
std::string constructorStr;
if (state.abstract) constructorStr = "nullptr";
else constructorStr = "&" + state.name + "::Create";
out << "#include \"" << state.headerPath << "\"\n\n"; out << "#include \"" << state.headerPath << "\"\n\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"
<< " .constructor = &" << state.name << "::CreateGeneric,\n" << " .constructor = " << constructorStr << ",\n"
<< " .explorerIcon = \"" << state.explorerIcon << "\",\n" << " .explorerIcon = \"" << state.explorerIcon << "\",\n"
<< " .flags = " << strFlags << ",\n" << " .flags = " << strFlags << ",\n"
<< "};\n\n"; << "};\n\n";
@ -168,6 +187,9 @@ void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
<< " return &TYPE;\n" << " return &TYPE;\n"
<< "};\n\n"; << "};\n\n";
// Special case for our Service class
if (state.baseClass == "Service") state.baseClass = "Instance";
writePropertySetHandler(out, state); writePropertySetHandler(out, state);
writePropertyGetHandler(out, state); writePropertyGetHandler(out, state);
writePropertyMetaHandler(out, state); writePropertyMetaHandler(out, state);

View file

@ -71,6 +71,7 @@ int main(int argc, char** argv) {
} }
printf("[AUTOGEN] Generating cpp files...\n"); printf("[AUTOGEN] Generating cpp files...\n");
fs::create_directories(argv[3]); // Make sure generated dir exists before we try writing to it
for (auto& [_, clazz] : state.classes) { for (auto& [_, clazz] : state.classes) {
fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp"); fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp");
std::ofstream outStream(outPath); std::ofstream outStream(outPath);
@ -79,6 +80,20 @@ int main(int argc, char** argv) {
outStream.close(); outStream.close();
} }
// // Write __all__.cpp file
// fs::path outPath = fs::path(argv[3]) / "__all__.cpp";
// std::ofstream outStream(outPath);
// // TODO: replace these with just direct filenames that can be converted by
// // CMake itself
// for (auto& [_, clazz] : state.classes) {
// std::string includeName = "class_" + clazz.name + ".cpp";
// outStream << "#include \"" << includeName << "\"\n";
// }
// outStream.close();
flushCaches(argv[3]); flushCaches(argv[3]);
} }

View file

@ -20,7 +20,7 @@ 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" 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") file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h" "${CMAKE_BINARY_DIR}/generated/__all__.cpp")
add_library(openblocks STATIC ${SOURCES}) add_library(openblocks STATIC ${SOURCES})
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks") set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml) target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)

View file

@ -4,6 +4,9 @@
#ifdef __AUTOGEN__ #ifdef __AUTOGEN__
#define def_inst(...) clang::annotate("OB::def_inst", #__VA_ARGS__) #define def_inst(...) clang::annotate("OB::def_inst", #__VA_ARGS__)
#define INSTANCE [[ def_inst() ]]
#define INSTANCE_WITH(...) [[ def_inst(__VA_ARGS__) ]]
#define INSTANCE_SERVICE(...) [[ def_inst(__VA_ARGS__, service) ]]
#define def_prop(...) clang::annotate("OB::def_prop", #__VA_ARGS__) #define def_prop(...) clang::annotate("OB::def_prop", #__VA_ARGS__)
@ -11,14 +14,18 @@
#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 #else
#define def_inst(...) #define def_inst(...)
#define INSTANCE
#define INSTANCE_WITH(...)
#define INSTANCE_SERVICE(...)
#define def_prop(...) #define def_prop(...)
#define cframe_position_prop(...) #define cframe_position_prop(...)
#define cframe_rotation_prop(...) #define cframe_rotation_prop(...)
#endif #endif
#define AUTOGEN_PREAMBLE \ #define AUTOGEN_PREAMBLE \
private: \ protected: \
result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name) override; \ result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name) override; \
fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value) override; \ fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value) override; \
result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name) override; \ result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name) override; \
std::vector<std::string> InternalGetProperties() override; \
private: private:

View file

@ -43,15 +43,6 @@ constexpr FieldCodec classNameCodec() {
Instance::Instance(const InstanceType* type) { Instance::Instance(const InstanceType* type) {
this->name = type->className; this->name = type->className;
this->memberMap = std::make_unique<MemberMap>( MemberMap {
.super = std::nullopt,
.members = {
{ "Name", { .backingField = &name, .type = &Data::String::TYPE, .codec = fieldCodecOf<Data::String, std::string>() } },
{ "Parent", { .backingField = &parent, .type = &Data::InstanceRef::TYPE, .codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>() } },
{ "ClassName", { .backingField = const_cast<InstanceType*>(type), .type = &Data::String::TYPE, .codec = classNameCodec(), .flags = (PropertyFlags)(PROP_READONLY | PROP_NOSAVE) } },
}
});
} }
Instance::~Instance () { Instance::~Instance () {
@ -195,83 +186,66 @@ void Instance::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
// Properties // Properties
result<Data::Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) { result<Data::Variant, MemberNotFound> Instance::GetPropertyValue(std::string name) {
auto meta_ = GetPropertyMeta(name); return InternalGetPropertyValue(name);
if (!meta_) return MemberNotFound(GetClass()->className, name);
auto meta = meta_.expect();
return meta.codec.read(meta.backingField);
} }
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::SetPropertyValue(std::string name, Data::Variant value) { fallible<MemberNotFound, AssignToReadOnlyMember> Instance::SetPropertyValue(std::string name, Data::Variant value) {
// Handle special case: Parent auto result = InternalSetPropertyValue(name, value);
if (name == "Parent") { if (result.isSuccess()) sendPropertyUpdatedSignal(shared_from_this(), name, value);
Data::InstanceRef ref = value.get<Data::InstanceRef>(); return result;
std::weak_ptr<Instance> inst = ref;
SetParent(inst.expired() ? std::nullopt : std::make_optional(inst.lock()));
return {};
}
if (InternalSetPropertyValue(name, value).isSuccess())
return {};
auto meta_ = GetPropertyMeta(name);
if (!meta_) return MemberNotFound(GetClass()->className, name);
auto meta = meta_.expect();
if (meta.flags & PROP_READONLY) AssignToReadOnlyMember(GetClass()->className, name);
meta.codec.write(value, meta.backingField);
if (meta.updateCallback) meta.updateCallback.value()(name);
sendPropertyUpdatedSignal(shared_from_this(), name, value);
return {};
} }
result<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name) { result<PropertyMeta, MemberNotFound> Instance::GetPropertyMeta(std::string name) {
MemberMap* current = &*memberMap; return InternalGetPropertyMeta(name);
while (true) {
// We look for the property in current member map
auto it = current->members.find(name);
// It is found, return it
if (it != current->members.end())
return it->second;
// It is not found, If there are no other maps to search, return null
if (!current->super.has_value())
return MemberNotFound(GetClass()->className, name);
// Search in the parent
current = current->super->get();
}
} }
result<Data::Variant, MemberNotFound> Instance::InternalGetPropertyValue(std::string name) { return MemberNotFound(GetClass()->className, name); } result<Data::Variant, MemberNotFound> Instance::InternalGetPropertyValue(std::string name) {
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyValue(std::string name, Data::Variant value) { return MemberNotFound(GetClass()->className, name); } if (name == "Name") {
return Data::Variant(Data::String(this->name));
} else if (name == "Parent") {
return Data::Variant(Data::InstanceRef(this->parent));
} else if (name == "ClassName") {
return Data::Variant(Data::String(GetClass()->className));
}
return MemberNotFound(GetClass()->className, name);
}
fallible<MemberNotFound, AssignToReadOnlyMember> Instance::InternalSetPropertyValue(std::string name, Data::Variant value) {
if (name == "Name") {
this->name = (std::string)value.get<Data::String>();
} else if (name == "Parent") {
std::weak_ptr<Instance> ref = value.get<Data::InstanceRef>();
SetParent(ref.expired() ? std::nullopt : std::make_optional(ref.lock()));
} else if (name == "ClassName") {
return AssignToReadOnlyMember(GetClass()->className, name);
}
return MemberNotFound(GetClass()->className, name);
}
std::vector<std::string> Instance::InternalGetProperties() {
std::vector<std::string> members;
members.push_back("Name");
members.push_back("Parent");
members.push_back("ClassName");
return members;
}
result<PropertyMeta, MemberNotFound> Instance::InternalGetPropertyMeta(std::string name) { return MemberNotFound(GetClass()->className, name); } result<PropertyMeta, MemberNotFound> Instance::InternalGetPropertyMeta(std::string name) { return MemberNotFound(GetClass()->className, name); }
void Instance::UpdateProperty(std::string name) { void Instance::UpdateProperty(std::string name) {
PropertyMeta meta = GetPropertyMeta(name).expect(); // TODO: temporary workaround because I'm too lazy to implement this in autogen
if (!meta.updateCallback) return; // Nothing to update, exit. InternalSetPropertyValue(name, InternalGetPropertyValue(name).expect()).expect();
meta.updateCallback.value()(name);
// PropertyMeta meta = GetPropertyMeta(name).expect();
// if (!meta.updateCallback) return; // Nothing to update, exit.
// meta.updateCallback.value()(name);
} }
std::vector<std::string> Instance::GetProperties() { std::vector<std::string> Instance::GetProperties() {
if (cachedMemberList.has_value()) return cachedMemberList.value(); if (cachedMemberList.has_value()) return cachedMemberList.value();
std::vector<std::string> memberList; std::vector<std::string> memberList = InternalGetProperties();
MemberMap* current = &*memberMap;
do {
for (auto const& [key, _] : current->members) {
// Don't add it if it's already in the list
if (std::find(memberList.begin(), memberList.end(), key) == memberList.end())
memberList.push_back(key);
}
if (!current->super.has_value())
break;
current = &*current->super.value();
} while (true);
cachedMemberList = memberList; cachedMemberList = memberList;
return memberList; return memberList;

View file

@ -65,7 +65,6 @@ private:
friend JointInstance; // This isn't ideal, but oh well friend JointInstance; // This isn't ideal, but oh well
protected: protected:
bool parentLocked = false; bool parentLocked = false;
std::unique_ptr<MemberMap> memberMap;
Instance(const InstanceType*); Instance(const InstanceType*);
virtual ~Instance(); virtual ~Instance();
@ -73,6 +72,7 @@ protected:
virtual result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name); virtual result<Data::Variant, MemberNotFound> InternalGetPropertyValue(std::string name);
virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value); virtual fallible<MemberNotFound, AssignToReadOnlyMember> InternalSetPropertyValue(std::string name, Data::Variant value);
virtual result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name); virtual result<PropertyMeta, MemberNotFound> InternalGetPropertyMeta(std::string name);
virtual std::vector<std::string> InternalGetProperties();
virtual void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent); 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 OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);

View file

@ -66,9 +66,4 @@ struct PropertyMeta {
PropertyCategory category = PROP_CATEGORY_DATA; PropertyCategory category = PROP_CATEGORY_DATA;
}; };
typedef std::variant<PropertyMeta> MemberMeta; typedef std::variant<PropertyMeta> MemberMeta;
struct MemberMap {
std::optional<std::unique_ptr<MemberMap>> super;
std::map<std::string, PropertyMeta> members;
};

View file

@ -13,16 +13,6 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
const InstanceType DataModel::TYPE = {
.super = &Instance::TYPE,
.className = "DataModel",
.constructor = nullptr,
};
const InstanceType* DataModel::GetClass() {
return &TYPE;
}
DataModel::DataModel() DataModel::DataModel()
: Instance(&TYPE) { : Instance(&TYPE) {
this->name = "Place"; this->name = "Place";

View file

@ -2,6 +2,7 @@
#include "error/instance.h" #include "error/instance.h"
#include "error/result.h" #include "error/result.h"
#include "objects/annotation.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "objects/base/refstate.h" #include "objects/base/refstate.h"
#include <memory> #include <memory>
@ -12,7 +13,8 @@ class DataModel;
class Service; class Service;
// The root instance to all objects in the hierarchy // The root instance to all objects in the hierarchy
class DataModel : public Instance { class INSTANCE_WITH(abstract) DataModel : public Instance {
AUTOGEN_PREAMBLE
private: private:
void DeserializeService(pugi::xml_node node); void DeserializeService(pugi::xml_node node);
static void cloneService(std::shared_ptr<DataModel> target, std::shared_ptr<Service>, RefState<_RefStatePropertyCell>); static void cloneService(std::shared_ptr<DataModel> target, std::shared_ptr<Service>, RefState<_RefStatePropertyCell>);

View file

@ -23,17 +23,6 @@ static CFrame XYZToZXY(glm::vec3(0, 0, 0), -glm::vec3(1, 0, 0), glm::vec3(0, 0,
static rp3d::PhysicsCommon common; static rp3d::PhysicsCommon common;
static rp3d::PhysicsWorld* world = common.createPhysicsWorld(); static rp3d::PhysicsWorld* world = common.createPhysicsWorld();
const InstanceType Handles::TYPE = {
.super = &Instance::TYPE,
.className = "Handles",
// .constructor = &Workspace::Create,
// .explorerIcon = "",
};
const InstanceType* Handles::GetClass() {
return &TYPE;
}
Handles::Handles(): Instance(&TYPE) { Handles::Handles(): Instance(&TYPE) {
} }

View file

@ -2,6 +2,7 @@
#include "base.h" #include "base.h"
#include "datatypes/cframe.h" #include "datatypes/cframe.h"
#include "objects/annotation.h"
#include "objects/base/service.h" #include "objects/base/service.h"
#include "objects/part.h" #include "objects/part.h"
#include <array> #include <array>
@ -30,7 +31,8 @@ enum HandlesType {
RotateHandles, RotateHandles,
}; };
class Handles : public Instance { class INSTANCE_WITH(abstract) Handles : public Instance {
AUTOGEN_PREAMBLE
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;

View file

@ -11,42 +11,7 @@
#include <reactphysics3d/engine/PhysicsWorld.h> #include <reactphysics3d/engine/PhysicsWorld.h>
#include "ptr_helpers.h" #include "ptr_helpers.h"
const InstanceType JointInstance::TYPE = {
.super = &Instance::TYPE,
.className = "JointInstance",
};
const InstanceType* JointInstance::GetClass() {
return &TYPE;
}
JointInstance::JointInstance(const InstanceType* type): Instance(type) { JointInstance::JointInstance(const InstanceType* type): Instance(type) {
this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap),
.members = {
{ "Part0", {
.backingField = &part0,
.type = &Data::InstanceRef::TYPE,
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "Part1", {
.backingField = &part1,
.type = &Data::InstanceRef::TYPE,
.codec = fieldCodecOf<Data::InstanceRef, std::weak_ptr<Instance>>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C0", {
.backingField = &c0,
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}}, { "C1", {
.backingField = &c1,
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&JointInstance::onUpdated, this),
}},
}
});
} }
JointInstance::~JointInstance() { JointInstance::~JointInstance() {

View file

@ -1,13 +1,16 @@
#pragma once #pragma once
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "../annotation.h"
#include <memory> #include <memory>
#include <optional> #include <optional>
class Part; class Part;
class Workspace; class Workspace;
class JointInstance : public Instance { class INSTANCE_SERVICE() JointInstance : public Instance {
AUTOGEN_PREAMBLE
std::weak_ptr<Part> oldPart0; std::weak_ptr<Part> oldPart0;
std::weak_ptr<Part> oldPart1; std::weak_ptr<Part> oldPart1;
protected: protected:
@ -23,9 +26,13 @@ protected:
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;
[[ def_prop(name="Part0", on_update=onUpdated) ]]
std::weak_ptr<Part> part0; std::weak_ptr<Part> part0;
[[ def_prop(name="Part1", on_update=onUpdated) ]]
std::weak_ptr<Part> part1; std::weak_ptr<Part> part1;
[[ def_prop(name="C0", on_update=onUpdated) ]]
CFrame c0; CFrame c0;
[[ def_prop(name="C1", on_update=onUpdated) ]]
CFrame c1; CFrame c1;
JointInstance(const InstanceType*); JointInstance(const InstanceType*);

View file

@ -10,16 +10,6 @@
#include <reactphysics3d/constraint/FixedJoint.h> #include <reactphysics3d/constraint/FixedJoint.h>
#include <reactphysics3d/engine/PhysicsWorld.h> #include <reactphysics3d/engine/PhysicsWorld.h>
const InstanceType Snap::TYPE = {
.super = &JointInstance::TYPE,
.className = "Snap",
.constructor = &Snap::Create,
};
const InstanceType* Snap::GetClass() {
return &TYPE;
}
Snap::Snap(): JointInstance(&TYPE) { Snap::Snap(): JointInstance(&TYPE) {
} }

View file

@ -1,10 +1,13 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "objects/joint/jointinstance.h" #include "objects/joint/jointinstance.h"
#include <memory> #include <memory>
class Snap : public JointInstance { class INSTANCE Snap : public JointInstance {
AUTOGEN_PREAMBLE
rp::FixedJoint* joint = nullptr; rp::FixedJoint* joint = nullptr;
virtual void buildJoint() override; virtual void buildJoint() override;

View file

@ -10,16 +10,6 @@
#include <reactphysics3d/constraint/FixedJoint.h> #include <reactphysics3d/constraint/FixedJoint.h>
#include <reactphysics3d/engine/PhysicsWorld.h> #include <reactphysics3d/engine/PhysicsWorld.h>
const InstanceType Weld::TYPE = {
.super = &JointInstance::TYPE,
.className = "Weld",
.constructor = &Weld::Create,
};
const InstanceType* Weld::GetClass() {
return &TYPE;
}
Weld::Weld(): JointInstance(&TYPE) { Weld::Weld(): JointInstance(&TYPE) {
} }

View file

@ -1,10 +1,13 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "objects/joint/jointinstance.h" #include "objects/joint/jointinstance.h"
#include <memory> #include <memory>
class Weld : public JointInstance { class INSTANCE Weld : public JointInstance {
AUTOGEN_PREAMBLE
rp::FixedJoint* joint = nullptr; rp::FixedJoint* joint = nullptr;
virtual void buildJoint() override; virtual void buildJoint() override;

View file

@ -2,18 +2,6 @@
#include "workspace.h" #include "workspace.h"
#include <memory> #include <memory>
const InstanceType JointsService::TYPE = {
.super = &Instance::TYPE,
.className = "JointsService",
.constructor = &JointsService::Create,
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE | INSTANCE_HIDDEN,
};
const InstanceType* JointsService::GetClass() {
return &TYPE;
}
JointsService::JointsService(): Service(&TYPE) { JointsService::JointsService(): Service(&TYPE) {
} }

View file

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/service.h" #include "objects/base/service.h"
class JointsService : public Service { class INSTANCE_SERVICE() JointsService : public Service {
AUTOGEN_PREAMBLE
private: private:
std::optional<std::shared_ptr<Workspace>> jointWorkspace(); std::optional<std::shared_ptr<Workspace>> jointWorkspace();
protected: protected:

View file

@ -55,102 +55,7 @@ Part::Part(): Part(PartConstructParams { .size = glm::vec3(2, 1.2, 4), .color =
Part::Part(PartConstructParams params): Instance(&TYPE), cframe(CFrame::FromEulerAnglesXYZ((Vector3)params.rotation) + params.position), Part::Part(PartConstructParams params): Instance(&TYPE), cframe(CFrame::FromEulerAnglesXYZ((Vector3)params.rotation) + params.position),
size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) { size(params.size), color(params.color), anchored(params.anchored), locked(params.locked) {
this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap),
.members = {
{ "Anchored", {
.backingField = &anchored,
.type = &Data::Bool::TYPE,
.codec = fieldCodecOf<Data::Bool, bool>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.category = PROP_CATEGORY_BEHAVIOR,
}}, { "Locked", {
.backingField = &locked,
.type = &Data::Bool::TYPE,
.codec = fieldCodecOf<Data::Bool, bool>(),
.category = PROP_CATEGORY_BEHAVIOR,
}}, { "Position", {
.backingField = &cframe,
.type = &Vector3::TYPE,
.codec = cframePositionCodec(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.flags = PROP_NOSAVE
}}, { "Rotation", {
.backingField = &cframe,
.type = &Vector3::TYPE,
.codec = cframeRotationCodec(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.flags = PROP_NOSAVE
}}, { "Velocity", {
.backingField = &velocity,
.type = &Vector3::TYPE,
.codec = fieldCodecOf<Vector3>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "CFrame", {
.backingField = &cframe,
.type = &CFrame::TYPE,
.codec = fieldCodecOf<CFrame>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
}}, { "Size", {
.backingField = &size,
.type = &Vector3::TYPE,
.codec = fieldCodecOf<Vector3, glm::vec3>(),
.updateCallback = memberFunctionOf(&Part::onUpdated, this),
.category = PROP_CATEGORY_PART,
}}, { "Color", {
.backingField = &color,
.type = &Color3::TYPE,
.codec = fieldCodecOf<Color3>(),
.category = PROP_CATEGORY_APPEARENCE,
}}, { "Transparency", {
.backingField = &transparency,
.type = &Data::Float::TYPE,
.codec = fieldCodecOf<Data::Float, float>(),
.flags = PROP_UNIT_FLOAT,
.category = PROP_CATEGORY_APPEARENCE,
}},
// Surfaces
{ "TopSurface", {
.backingField = &topSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}}, { "BottomSurface", {
.backingField = &bottomSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}}, { "FrontSurface", {
.backingField = &frontSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}}, { "BackSurface", {
.backingField = &backSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}}, { "RightSurface", {
.backingField = &rightSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}}, { "LeftSurface", {
.backingField = &leftSurface,
.type = &Data::Int::TYPE, // Replace with enum
.codec = fieldCodecOf<Data::Int, int>(),
.flags = PROP_HIDDEN,
.category = PROP_CATEGORY_SURFACE,
}},
}
});
} }
Part::~Part() { Part::~Part() {

View file

@ -28,7 +28,7 @@ struct PartConstructParams {
class Snap; class Snap;
class [[ def_inst(explorer_icon="part") ]] Part : public Instance { class INSTANCE_WITH(explorer_icon="part") Part : public Instance {
AUTOGEN_PREAMBLE AUTOGEN_PREAMBLE
protected: protected:
// Joints where this part is Part0 // Joints where this part is Part0
@ -51,10 +51,11 @@ protected:
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;
[[ def_prop(name="Velocity", on_update=onUpdated) ]]
Vector3 velocity; Vector3 velocity;
[[ def_prop(name="CFrame"), cframe_position_prop(name="Position"), cframe_rotation_prop(name="Rotation") ]] [[ def_prop(name="CFrame", on_update=onUpdated), cframe_position_prop(name="Position"), cframe_rotation_prop(name="Rotation") ]]
CFrame cframe; CFrame cframe;
[[ def_prop(name="Size", category=PART) ]] [[ def_prop(name="Size", category=PART, on_update=onUpdated) ]]
glm::vec3 size; glm::vec3 size;
[[ def_prop(name="Color", category=APPEARANCE) ]] [[ def_prop(name="Color", category=APPEARANCE) ]]
Color3 color; Color3 color;
@ -62,7 +63,7 @@ public:
float transparency = 0.f; float transparency = 0.f;
bool selected = false; bool selected = false;
[[ def_prop(name="Anchored", category=BEHAVIOR) ]] [[ def_prop(name="Anchored", category=BEHAVIOR, on_update=onUpdated) ]]
bool anchored = false; bool anchored = false;
[[ def_prop(name="Locked", category=BEHAVIOR) ]] [[ def_prop(name="Locked", category=BEHAVIOR) ]]
bool locked = false; bool locked = false;
@ -87,7 +88,7 @@ public:
static inline std::shared_ptr<Part> New() { return std::make_shared<Part>(); }; static inline std::shared_ptr<Part> New() { return std::make_shared<Part>(); };
static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); }; static inline std::shared_ptr<Part> New(PartConstructParams params) { return std::make_shared<Part>(params); };
static inline InstanceRef CreateGeneric() { return std::make_shared<Part>(); }; static inline InstanceRef Create() { return std::make_shared<Part>(); };
virtual const InstanceType* GetClass() override; virtual const InstanceType* GetClass() override;
inline Vector3 position() { return cframe.Position(); } inline Vector3 position() { return cframe.Position(); }

View file

@ -6,30 +6,7 @@
#include "objects/workspace.h" #include "objects/workspace.h"
#include "lua.h" #include "lua.h"
const InstanceType Script::TYPE = {
.super = &Instance::TYPE,
.className = "Script",
.constructor = &Script::Create,
.explorerIcon = "script",
};
const InstanceType* Script::GetClass() {
return &TYPE;
}
Script::Script(): Instance(&TYPE) { Script::Script(): Instance(&TYPE) {
this->memberMap = std::make_unique<MemberMap>(MemberMap {
.super = std::move(this->memberMap),
.members = {
{ "Source", {
.backingField = &source,
.type = &Data::String::TYPE,
.codec = fieldCodecOf<Data::String, std::string>(),
.flags = PROP_HIDDEN,
}},
}
});
source = "print \"Hello, world!\""; source = "print \"Hello, world!\"";
} }

View file

@ -1,15 +1,18 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include <memory> #include <memory>
class Script : public Instance { class INSTANCE_WITH(explorer_icon="script") Script : public Instance {
AUTOGEN_PREAMBLE
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;
Script(); Script();
~Script(); ~Script();
[[ def_prop(name="Source", hidden) ]]
std::string source; std::string source;
void Run(); void Run();
void Stop(); void Stop();

View file

@ -16,17 +16,6 @@ std::string unsafe_globals[] = {
"loadfile", "loadstring", "load", "dofile", "getfenv", "setfenv" "loadfile", "loadstring", "load", "dofile", "getfenv", "setfenv"
}; };
const InstanceType ScriptContext::TYPE = {
.super = &Instance::TYPE,
.className = "ScriptContext",
.constructor = &ScriptContext::Create,
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE | INSTANCE_HIDDEN,
};
const InstanceType* ScriptContext::GetClass() {
return &TYPE;
}
ScriptContext::ScriptContext(): Service(&TYPE) { ScriptContext::ScriptContext(): Service(&TYPE) {
} }

View file

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/service.h" #include "objects/base/service.h"
#include "lua.h" #include "lua.h"
class ScriptContext : public Service { class INSTANCE_SERVICE() ScriptContext : public Service {
private: AUTOGEN_PREAMBLE
protected: protected:
void InitService() override; void InitService() override;
bool initialized = false; bool initialized = false;

View file

@ -2,17 +2,6 @@
#include "objects/script.h" #include "objects/script.h"
#include "objects/workspace.h" #include "objects/workspace.h"
const InstanceType ServerScriptService::TYPE = {
.super = &Instance::TYPE,
.className = "ServerScriptService",
.constructor = &ServerScriptService::Create,
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE,
};
const InstanceType* ServerScriptService::GetClass() {
return &TYPE;
}
ServerScriptService::ServerScriptService(): Service(&TYPE) { ServerScriptService::ServerScriptService(): Service(&TYPE) {
} }

View file

@ -1,11 +1,12 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/service.h" #include "objects/base/service.h"
// Container class for server scripts // Container class for server scripts
// Also handles/manages running server scripts on run // Also handles/manages running server scripts on run
class ServerScriptService : public Service { class INSTANCE_SERVICE() ServerScriptService : public Service {
private: AUTOGEN_PREAMBLE
protected: protected:
void InitService() override; void InitService() override;
void OnRun() override; void OnRun() override;

View file

@ -5,18 +5,6 @@
#include "physics/util.h" #include "physics/util.h"
#include <reactphysics3d/engine/PhysicsCommon.h> #include <reactphysics3d/engine/PhysicsCommon.h>
const InstanceType Workspace::TYPE = {
.super = &Instance::TYPE,
.className = "Workspace",
.constructor = &Workspace::Create,
.explorerIcon = "workspace",
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE,
};
const InstanceType* Workspace::GetClass() {
return &TYPE;
}
rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon; rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon;
Workspace::Workspace(): Service(&TYPE) { Workspace::Workspace(): Service(&TYPE) {

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "objects/annotation.h"
#include "objects/base/service.h" #include "objects/base/service.h"
#include <memory> #include <memory>
#include <reactphysics3d/body/RigidBody.h> #include <reactphysics3d/body/RigidBody.h>
@ -29,7 +30,9 @@ class Weld;
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter; typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
class Workspace : public Service { class INSTANCE_SERVICE(explorer_icon="workspace") Workspace : public Service {
AUTOGEN_PREAMBLE
rp::PhysicsWorld* physicsWorld = nullptr; rp::PhysicsWorld* physicsWorld = nullptr;
static rp::PhysicsCommon* physicsCommon; static rp::PhysicsCommon* physicsCommon;