feat(lua): added instance property and child access via reference
This commit is contained in:
parent
6bb1d8b3a4
commit
cbed2bac95
6 changed files with 88 additions and 5 deletions
|
@ -17,6 +17,12 @@ void Data::Variant::Serialize(pugi::xml_node node) const {
|
|||
}, this->wrapped);
|
||||
}
|
||||
|
||||
void Data::Variant::PushLuaValue(lua_State* state) const {
|
||||
return std::visit([&](auto&& it) {
|
||||
return it.PushLuaValue(state);
|
||||
}, this->wrapped);
|
||||
}
|
||||
|
||||
Data::Variant Data::Variant::Deserialize(pugi::xml_node node) {
|
||||
if (Data::TYPE_MAP.count(node.name()) == 0) {
|
||||
Logger::fatalErrorf("Unknown type for instance: '%s'", node.name());
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace Data {
|
|||
Data::String ToString() const;
|
||||
|
||||
void Serialize(pugi::xml_node node) const;
|
||||
void PushLuaValue(lua_State* state) const;
|
||||
static Data::Variant Deserialize(pugi::xml_node node);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "datatypes/ref.h"
|
||||
#include "color3.h"
|
||||
#include "datatypes/base.h"
|
||||
#include "logger.h"
|
||||
#include "meta.h" // IWYU pragma: keep
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include "objects/base/instance.h"
|
||||
#include "lua.h"
|
||||
|
||||
Data::InstanceRef::InstanceRef() {};
|
||||
Data::InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {};
|
||||
|
@ -33,7 +36,61 @@ void Data::InstanceRef::Serialize(pugi::xml_node node) const {
|
|||
// return Color3::FromHex(node.text().get());
|
||||
// }
|
||||
|
||||
static int inst_gc(lua_State*);
|
||||
static int inst_index(lua_State*);
|
||||
static const struct luaL_Reg metatable [] = {
|
||||
{"__gc", inst_gc},
|
||||
{"__index", inst_index},
|
||||
{NULL, NULL} /* end of array */
|
||||
};
|
||||
|
||||
void Data::InstanceRef::PushLuaValue(lua_State* L) const {
|
||||
// TODO:
|
||||
panic();
|
||||
if (ref.expired()) return lua_pushnil(L);
|
||||
|
||||
int n = lua_gettop(L);
|
||||
|
||||
auto userdata = (std::shared_ptr<Instance>**)lua_newuserdata(L, sizeof(void*));
|
||||
|
||||
// Create new pointer, and assign userdata a pointer to it
|
||||
std::shared_ptr<Instance>* ptr = new std::shared_ptr<Instance>(ref);
|
||||
*userdata = ptr;
|
||||
|
||||
// Create the instance's metatable
|
||||
luaL_newmetatable(L, "__mt_instance");
|
||||
luaL_register(L, NULL, metatable);
|
||||
|
||||
lua_setmetatable(L, n+1);
|
||||
}
|
||||
|
||||
static int inst_gc(lua_State* L) {
|
||||
// Destroy the contained shared_ptr
|
||||
auto userdata = (std::shared_ptr<Instance>**)lua_touserdata(L, -1);
|
||||
delete *userdata;
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inst_index(lua_State* L) {
|
||||
auto userdata = (std::shared_ptr<Instance>**)lua_touserdata(L, 1);
|
||||
std::shared_ptr<Instance> inst = **userdata;
|
||||
std::string key(lua_tostring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
// Read property
|
||||
std::optional<PropertyMeta> meta = inst->GetPropertyMeta(key);
|
||||
if (meta) {
|
||||
Data::Variant value = inst->GetPropertyValue(key).expect();
|
||||
value.PushLuaValue(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Look for child
|
||||
std::optional<std::shared_ptr<Instance>> child = inst->FindFirstChild(key);
|
||||
if (child) {
|
||||
Data::InstanceRef(child.value()).PushLuaValue(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return luaL_error(L, "'%s' is not a valid member of %s", key.c_str(), inst->GetClass()->className.c_str());
|
||||
}
|
|
@ -154,6 +154,14 @@ bool Instance::IsA(std::string className) {
|
|||
return cur != nullptr;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<Instance>> Instance::FindFirstChild(std::string name) {
|
||||
for (auto child : children) {
|
||||
if (child->name == name)
|
||||
return child;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static std::shared_ptr<Instance> DUMMY_INSTANCE;
|
||||
DescendantsIterator Instance::GetDescendantsStart() {
|
||||
return DescendantsIterator(GetChildren().size() > 0 ? GetChildren()[0] : DUMMY_INSTANCE);
|
||||
|
|
|
@ -102,6 +102,7 @@ public:
|
|||
DescendantsIterator GetDescendantsEnd();
|
||||
// Utility functions
|
||||
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
||||
std::optional<std::shared_ptr<Instance>> FindFirstChild(std::string);
|
||||
|
||||
// Properties
|
||||
result<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "objects/base/instance.h"
|
||||
#include "objects/base/member.h"
|
||||
#include "objects/script/scriptcontext.h"
|
||||
#include <luajit-2.1/lauxlib.h>
|
||||
#include <luajit-2.1/lua.h>
|
||||
#include "objects/workspace.h"
|
||||
#include "lua.h"
|
||||
|
||||
const InstanceType Script::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
|
@ -40,7 +40,17 @@ void Script::Run() {
|
|||
lua_State* L = dataModel().value()->GetService<ScriptContext>()->state;
|
||||
|
||||
// Initialize script globals
|
||||
lua_getglobal(L, "_G");
|
||||
|
||||
lua_pushstring(L, "game");
|
||||
Data::InstanceRef(dataModel().value()).PushLuaValue(L);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pushstring(L, "workspace");
|
||||
Data::InstanceRef(dataModel().value()->GetService<Workspace>()).PushLuaValue(L);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_loadstring(L, source.c_str());
|
||||
int status = lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue