feat(lua): added Instance.new for object creation
This commit is contained in:
parent
9f97a90c12
commit
74b8bca10a
4 changed files with 80 additions and 1 deletions
77
core/src/lua/instancelib.cpp
Normal file
77
core/src/lua/instancelib.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "objects/base/instance.h"
|
||||
#include "datatypes/ref.h"
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include "objects/meta.h"
|
||||
#include <memory>
|
||||
|
||||
static int lib_Instance_index(lua_State*);
|
||||
static int lib_Instance_tostring(lua_State*);
|
||||
static const struct luaL_Reg lib_Instance_metatable [] = {
|
||||
{"__index", lib_Instance_index},
|
||||
{"__tostring", lib_Instance_tostring},
|
||||
{NULL, NULL} /* end of array */
|
||||
};
|
||||
|
||||
static int __lua_impl__Instance__new(lua_State* L) {
|
||||
int n = lua_gettop(L);
|
||||
|
||||
// First argument (className)
|
||||
std::string className = luaL_checkstring(L, 1);
|
||||
|
||||
// [Optional] Second argument (parent)
|
||||
std::shared_ptr<Instance> parent;
|
||||
if (n > 1) {
|
||||
parent = **(std::shared_ptr<Instance>**)luaL_checkudata(L, 2, "__mt_instance");
|
||||
}
|
||||
|
||||
// Look up class name
|
||||
if (INSTANCE_MAP.count(className) == 0)
|
||||
return luaL_error(L, "Attempt to create instance of unknown type '%s'", className.c_str());
|
||||
|
||||
const InstanceType* type = INSTANCE_MAP[className];
|
||||
|
||||
if (type->flags & (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE) || type->constructor == nullptr)
|
||||
return luaL_error(L, "Attempt to create Instance of type '%s', which is not creatable", className.c_str());
|
||||
|
||||
std::shared_ptr<Instance> object = type->constructor();
|
||||
|
||||
if (parent != nullptr)
|
||||
object->SetParent(parent);
|
||||
|
||||
InstanceRef(object).PushLuaValue(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Instance::PushLuaLibrary(lua_State* L) {
|
||||
lua_getglobal(L, "_G");
|
||||
lua_pushstring(L, "Instance");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
|
||||
// Create the library's metatable
|
||||
luaL_newmetatable(L, "__mt_lib_Instance");
|
||||
luaL_register(L, NULL, lib_Instance_metatable);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
||||
int lib_Instance_tostring(lua_State* L) {
|
||||
lua_pushstring(L, "Instance");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_Instance_index(lua_State* L) {
|
||||
std::string key(lua_tostring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (key == "new") {
|
||||
lua_pushcfunction(L, __lua_impl__Instance__new);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return luaL_error(L, "%s is not a valid member of %s\n", key.c_str(), "Instance");
|
||||
}
|
||||
|
|
@ -95,6 +95,7 @@ public:
|
|||
|
||||
// Instance is abstract, so it should not implement GetClass directly
|
||||
virtual const InstanceType* GetClass() = 0;
|
||||
static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp
|
||||
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
|
||||
std::optional<std::shared_ptr<Instance>> GetParent();
|
||||
bool IsParentLocked();
|
||||
|
|
|
@ -46,6 +46,7 @@ void ScriptContext::InitService() {
|
|||
Vector3::PushLuaLibrary(state);
|
||||
CFrame::PushLuaLibrary(state);
|
||||
Color3::PushLuaLibrary(state);
|
||||
Instance::PushLuaLibrary(state);
|
||||
|
||||
// TODO: custom os library
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class ObLuaLexer : public QsciLexerLua {
|
|||
//"foreach foreachi getn "
|
||||
|
||||
// Openblocks extensions
|
||||
"shared require game workspace "
|
||||
"shared require game workspace Instance Instance.new "
|
||||
|
||||
"_G _VERSION getfenv getmetatable ipairs loadstring "
|
||||
"next pairs pcall rawequal rawget rawset select "
|
||||
|
|
Loading…
Add table
Reference in a new issue