feat(autogen): implement tostring and miscellania
This commit is contained in:
parent
49dfeec18c
commit
f5727f3b03
10 changed files with 44 additions and 147 deletions
|
@ -83,7 +83,15 @@ static void processProperty(CXCursor cur, ClassAnalysis* state) {
|
|||
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||
ClassAnalysis anly;
|
||||
|
||||
std::string propertyDef = findAnnotation(cur, "OB::def_data").value();
|
||||
auto result = parseAnnotationString(propertyDef);
|
||||
|
||||
anly.name = className;
|
||||
anly.serializedName = result["name"];
|
||||
anly.hasFromString = result.count("from_string") > 0;
|
||||
|
||||
if (anly.serializedName == "")
|
||||
anly.serializedName = className;
|
||||
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
|
|
|
@ -33,7 +33,9 @@ struct MethodAnalysis {
|
|||
|
||||
struct ClassAnalysis {
|
||||
std::string name;
|
||||
std::string serializedName;
|
||||
std::string headerPath;
|
||||
bool hasFromString = false;
|
||||
std::vector<PropertyAnalysis> properties;
|
||||
std::vector<MethodAnalysis> methods;
|
||||
std::vector<PropertyAnalysis> staticProperties;
|
||||
|
|
|
@ -130,9 +130,11 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
|||
|
||||
out << "static int data_gc(lua_State*);\n"
|
||||
"static int data_index(lua_State*);\n"
|
||||
"static int data_tostring(lua_State*);\n"
|
||||
"static const struct luaL_Reg metatable [] = {\n"
|
||||
" {\"__gc\", data_gc},\n"
|
||||
" {\"__index\", data_index},\n"
|
||||
" {\"__tostring\", data_tostring},\n"
|
||||
" {NULL, NULL} /* end of array */\n"
|
||||
"};\n\n";
|
||||
|
||||
|
@ -152,6 +154,14 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
|||
" lua_setmetatable(L, n+1);\n"
|
||||
"}\n\n";
|
||||
|
||||
|
||||
out << "result<Data::Variant, LuaCastError> Data::" << 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"
|
||||
"}\n\n";
|
||||
|
||||
// Indexing methods and properties
|
||||
|
||||
out << "static int data_index(lua_State* L) {\n"
|
||||
|
@ -206,6 +216,14 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
|||
" return luaL_error(L, \"%s is not a valid member of %s\\n\", key.c_str(), \"" << state.name << "\");\n"
|
||||
"}\n\n";
|
||||
|
||||
// ToString
|
||||
|
||||
out << "\nint data_tostring(lua_State* L) {\n"
|
||||
" auto this_ = (" << fqn << "*)lua_touserdata(L, 1);\n"
|
||||
" lua_pushstring(L, std::string(this_->ToString()).c_str());\n"
|
||||
" return 1;\n"
|
||||
"}\n\n";
|
||||
|
||||
// Destructor
|
||||
|
||||
out << "\nint data_gc(lua_State* L) {\n"
|
||||
|
@ -215,7 +233,6 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
|||
"}\n\n";
|
||||
}
|
||||
|
||||
|
||||
void data::writeCodeForClass(std::ofstream& out, std::string headerPath, ClassAnalysis& state) {
|
||||
std::string fqn = "Data::" + state.name;
|
||||
|
||||
|
@ -224,9 +241,10 @@ void data::writeCodeForClass(std::ofstream& out, std::string headerPath, ClassAn
|
|||
out << "#include \"datatypes/meta.h\"\n";
|
||||
out << "#include \"lua.h\"\n\n";
|
||||
out << "const Data::TypeInfo " << fqn << "::TYPE = {\n"
|
||||
<< " .name = \"" << fqn << "\",\n"
|
||||
<< " .deserializer = &" << fqn << "::Deserialize,\n"
|
||||
<< " .fromLuaValue = &" << fqn << "::FromLuaValue,\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"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
// Helper macros
|
||||
#define DEF_DATA [[ def_data() ]] // Data declaration
|
||||
#define DEF_DATA_(...) [[ def_data(__VA_ARGS__) ]]
|
||||
#define DEF_DATA_PROP [[ def_data_prop() ]] // Property. Getter or field
|
||||
#define DEF_DATA_METHOD [[ def_data_method() ]] // Method
|
||||
#define DEF_DATA_CTOR [[ def_data_ctor() ]] // Constructor (i.e. .new)
|
||||
|
@ -28,4 +29,5 @@ 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); \
|
||||
private:
|
||||
|
|
|
@ -56,12 +56,6 @@ Data::CFrame::CFrame(Vector3 position, Vector3 lookAt, Vector3 up)
|
|||
}
|
||||
|
||||
Data::CFrame::~CFrame() = default;
|
||||
const Data::TypeInfo Data::CFrame::TYPE = {
|
||||
.name = "CoordinateFrame",
|
||||
.deserializer = &Data::CFrame::Deserialize,
|
||||
};
|
||||
|
||||
const Data::TypeInfo& Data::CFrame::GetType() const { return Vector3::TYPE; };
|
||||
|
||||
const Data::String Data::CFrame::ToString() const {
|
||||
return std::to_string(X()) + ", " + std::to_string(Y()) + ", " + std::to_string(Z());
|
||||
|
@ -150,8 +144,3 @@ Data::Variant Data::CFrame::Deserialize(pugi::xml_node node) {
|
|||
node.child("R22").text().as_float()
|
||||
);
|
||||
}
|
||||
|
||||
void Data::CFrame::PushLuaValue(lua_State* L) const {
|
||||
// TODO:
|
||||
panic();
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "datatypes/annotation.h"
|
||||
#include "datatypes/vector.h"
|
||||
#include <glm/ext/quaternion_float.hpp>
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
|
@ -11,7 +12,9 @@
|
|||
namespace rp = reactphysics3d;
|
||||
|
||||
namespace Data {
|
||||
class DEF_DATA CFrame : public Base {
|
||||
class DEF_DATA_(name="CoordinateFrame") CFrame : public Base {
|
||||
AUTOGEN_PREAMBLE_DATA
|
||||
|
||||
glm::vec3 translation;
|
||||
glm::mat3 rotation;
|
||||
|
||||
|
@ -33,22 +36,18 @@ namespace Data {
|
|||
DEF_DATA_PROP static const CFrame IDENTITY;
|
||||
static const CFrame YToZ;
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
virtual const Data::String ToString() const override;
|
||||
virtual void Serialize(pugi::xml_node parent) const override;
|
||||
static Data::Variant Deserialize(pugi::xml_node node);
|
||||
|
||||
virtual void PushLuaValue(lua_State*) const override;
|
||||
static void PushLuaLibrary(lua_State*);
|
||||
|
||||
operator glm::mat4() const;
|
||||
operator rp::Transform() const;
|
||||
|
||||
//inline static CFrame identity() { }
|
||||
DEF_DATA_METHOD inline Vector3 Position() const { return translation; }
|
||||
DEF_DATA_METHOD inline CFrame Rotation() const { return CFrame { glm::vec3(0, 0, 0), rotation }; }
|
||||
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; }
|
||||
|
|
|
@ -6,12 +6,6 @@ Data::Color3::Color3(float r, float g, float b) : r(std::clamp(r, 0.f, 1.f)), g(
|
|||
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)) {};
|
||||
|
||||
Data::Color3::~Color3() = default;
|
||||
const Data::TypeInfo Data::Color3::TYPE = {
|
||||
.name = "Color3",
|
||||
.deserializer = &Data::Color3::Deserialize,
|
||||
};
|
||||
|
||||
const Data::TypeInfo& Data::Color3::GetType() const { return Data::Color3::TYPE; };
|
||||
|
||||
const Data::String Data::Color3::ToString() const {
|
||||
return std::to_string(int(r*256)) + ", " + std::to_string(int(g*256)) + ", " + std::to_string(int(b*256));
|
||||
|
@ -46,9 +40,3 @@ void Data::Color3::Serialize(pugi::xml_node node) const {
|
|||
Data::Variant Data::Color3::Deserialize(pugi::xml_node node) {
|
||||
return Color3::FromHex(node.text().get());
|
||||
}
|
||||
|
||||
|
||||
void Data::Color3::PushLuaValue(lua_State* L) const {
|
||||
// TODO:
|
||||
panic();
|
||||
}
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
namespace Data {
|
||||
class DEF_DATA Color3 : public Base {
|
||||
AUTOGEN_PREAMBLE_DATA
|
||||
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
|
@ -19,15 +21,11 @@ namespace Data {
|
|||
|
||||
DEF_DATA_METHOD static Color3 FromHex(std::string hex);
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
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);
|
||||
|
||||
virtual void PushLuaValue(lua_State*) const override;
|
||||
static void PushLuaLibrary(lua_State*);
|
||||
|
||||
operator glm::vec3() const;
|
||||
|
|
|
@ -12,13 +12,6 @@ Data::Vector3::Vector3(const rp::Vector3& src) : vector(glm::vec3(src.x, src.y,
|
|||
Data::Vector3::Vector3(float x, const float y, float z) : vector(glm::vec3(x, y, z)) {};
|
||||
|
||||
Data::Vector3::~Vector3() = default;
|
||||
const Data::TypeInfo Data::Vector3::TYPE = {
|
||||
.name = "Vector3",
|
||||
.deserializer = &Data::Vector3::Deserialize,
|
||||
.fromString = &Data::Vector3::FromString,
|
||||
};
|
||||
|
||||
const Data::TypeInfo& Data::Vector3::GetType() const { return Data::Vector3::TYPE; };
|
||||
|
||||
Data::Vector3 Data::Vector3::ZERO(0, 0, 0);
|
||||
Data::Vector3 Data::Vector3::ONE(1, 1, 1);
|
||||
|
@ -112,99 +105,3 @@ std::optional<Data::Variant> Data::Vector3::FromString(std::string string) {
|
|||
|
||||
return Data::Vector3(components[0], components[1], components[2]);
|
||||
}
|
||||
|
||||
// Lua (TEMPORARY)
|
||||
#include "lua.h"
|
||||
|
||||
static int lib_index(lua_State*);
|
||||
static const struct luaL_Reg lib_metatable [] = {
|
||||
{"__index", lib_index},
|
||||
{NULL, NULL} /* end of array */
|
||||
};
|
||||
|
||||
static int lib_index(lua_State* L) {
|
||||
std::string key(lua_tostring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (key == "test") {
|
||||
Data::String("mabaref").PushLuaValue(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return luaL_error(L, "%s is not a valid member of %s\n", key.c_str(), "Vector3");
|
||||
}
|
||||
|
||||
static int data_index(lua_State*);
|
||||
static const struct luaL_Reg metatable [] = {
|
||||
{"__index", data_index},
|
||||
{NULL, NULL} /* end of array */
|
||||
};
|
||||
|
||||
static int data_index(lua_State* L) {
|
||||
auto this__ = (Data::Base*)lua_touserdata(L, 1);
|
||||
this__->GetType();
|
||||
if (&this__->GetType() != &Vector3::TYPE) return luaL_typerror(L, 0, "Vector3");
|
||||
Vector3* this_ = (Vector3*)this__;
|
||||
|
||||
std::string key(lua_tostring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (key == "X") {
|
||||
Data::Float(this_->X()).PushLuaValue(L);
|
||||
return 1;
|
||||
} else if (key == "Magnitude") {
|
||||
lua_pushcfunction(L, [](lua_State* L) {
|
||||
auto this__ = (Data::Base*)lua_touserdata(L, 1);
|
||||
if (&this__->GetType() != &Vector3::TYPE) return luaL_typerror(L, 0, "Vector3");
|
||||
Vector3* this_ = (Vector3*)this__;
|
||||
|
||||
Data::Float(this_->Magnitude()).PushLuaValue(L);
|
||||
return 1;
|
||||
});
|
||||
return 1;
|
||||
} else if (key == "Dot") {
|
||||
lua_pushcfunction(L, [](lua_State* L) {
|
||||
auto this__ = (Data::Base*)lua_touserdata(L, 1);
|
||||
if (&this__->GetType() != &Vector3::TYPE) return luaL_typerror(L, 0, "Vector3");
|
||||
Vector3* this_ = (Vector3*)this__;
|
||||
|
||||
auto arg0_ = (Data::Base*)lua_touserdata(L, 2);
|
||||
if (&arg0_->GetType() != &Vector3::TYPE) return luaL_typerror(L, 1, "Vector3");
|
||||
Vector3* arg0 = (Vector3*)arg0_;
|
||||
|
||||
Data::Float(this_->Dot(*arg0)).PushLuaValue(L);
|
||||
return 1;
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
return luaL_error(L, "%s is not a valid member of %s\n", key.c_str(), "Vector3");
|
||||
}
|
||||
|
||||
void Data::Vector3::PushLuaLibrary(lua_State* L) {
|
||||
int n = lua_gettop(L);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
|
||||
// Create the library's metatable
|
||||
luaL_newmetatable(L, "__mt_lib_Vector3");
|
||||
luaL_register(L, NULL, lib_metatable);
|
||||
|
||||
lua_setmetatable(L, n+1);
|
||||
}
|
||||
|
||||
void Data::Vector3::PushLuaValue(lua_State* L) const {
|
||||
int n = lua_gettop(L);
|
||||
|
||||
// I'm torn... should this be Data::Variant, or Data::Base?
|
||||
// If I ever decouple typing from Data::Base, I'll switch it to variant,
|
||||
// otherwise, it doesn't make much sense to represent it as one
|
||||
Vector3* userdata = (Vector3*)lua_newuserdata(L, sizeof(Vector3));
|
||||
new(userdata) Vector3(*this);
|
||||
|
||||
// Create the library's metatable
|
||||
luaL_newmetatable(L, "__mt_Vector3");
|
||||
luaL_register(L, NULL, metatable);
|
||||
|
||||
lua_setmetatable(L, n+1);
|
||||
}
|
|
@ -9,7 +9,8 @@
|
|||
namespace rp = reactphysics3d;
|
||||
|
||||
namespace Data {
|
||||
class DEF_DATA Vector3 : public Base {
|
||||
class DEF_DATA_(from_string) Vector3 : public Base {
|
||||
AUTOGEN_PREAMBLE_DATA
|
||||
glm::vec3 vector;
|
||||
|
||||
public:
|
||||
|
@ -19,9 +20,6 @@ namespace Data {
|
|||
DEF_DATA_CTOR Vector3(const rp::Vector3&);
|
||||
~Vector3();
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
|
||||
DEF_DATA_PROP static Data::Vector3 ZERO;
|
||||
DEF_DATA_PROP static Data::Vector3 ONE;
|
||||
|
||||
|
@ -31,8 +29,6 @@ namespace Data {
|
|||
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);
|
||||
virtual void PushLuaValue(lua_State*) const override;
|
||||
static void PushLuaLibrary(lua_State*);
|
||||
|
||||
operator glm::vec3() const;
|
||||
|
|
Loading…
Add table
Reference in a new issue