diff --git a/core/src/datatypes/signal.cpp b/core/src/datatypes/signal.cpp index 82ee617..741c7f4 100644 --- a/core/src/datatypes/signal.cpp +++ b/core/src/datatypes/signal.cpp @@ -2,12 +2,10 @@ #include "datatypes/base.h" #include "meta.h" #include "lua.h" -#include -#include #include #include -SignalSource::SignalSource() {} +SignalSource::SignalSource() : std::shared_ptr(std::make_shared()) {} SignalSource::~SignalSource() = default; Signal::Signal() {} @@ -16,16 +14,22 @@ Signal::~Signal() = default; SignalConnection::~SignalConnection() = default; // Only used for its address -int __savedThreads; +int __savedThreads = 0; LuaSignalConnection::LuaSignalConnection(lua_State* L) { // Create thread from function at top of stack thread = lua_newthread(L); lua_xmove(L, thread, 1); - - // Save thread so it doesn't get GC'd - lua_pushlightuserdata(thread, &__savedThreads); - lua_gettable(thread, LUA_REGISTRYINDEX); + // https://stackoverflow.com/a/31952046/16255372 + // Create the table + if (__savedThreads == 0) { + lua_newtable(thread); + __savedThreads = luaL_ref(thread, LUA_REGISTRYINDEX); + } + + // Save thread so it doesn't get GC'd + lua_rawgeti(thread, LUA_REGISTRYINDEX, __savedThreads); + lua_pushthread(thread); // key lua_pushboolean(thread, true); // value lua_rawset(thread, -3); // set @@ -35,8 +39,7 @@ LuaSignalConnection::LuaSignalConnection(lua_State* L) { LuaSignalConnection::~LuaSignalConnection() { // Remove thread so that it can get properly GC'd - lua_pushlightuserdata(thread, &__savedThreads); - lua_gettable(thread, LUA_REGISTRYINDEX); + lua_rawgeti(thread, LUA_REGISTRYINDEX, __savedThreads); lua_pushthread(thread); // key lua_pushnil(thread); // value @@ -69,12 +72,16 @@ void CSignalConnection::Call(std::vector args) { // -void Signal::Connect(std::function)> callback) { - connections.push_back(std::dynamic_pointer_cast(std::make_shared(CSignalConnection(callback)))); +SignalConnectionRef Signal::Connect(std::function)> callback) { + auto conn = std::dynamic_pointer_cast(std::make_shared(CSignalConnection(callback))); + connections.push_back(conn); + return SignalConnectionRef(conn); } -void Signal::Connect(lua_State* state) { - connections.push_back(std::dynamic_pointer_cast(std::make_shared(LuaSignalConnection(state)))); +SignalConnectionRef Signal::Connect(lua_State* state) { + auto conn = std::dynamic_pointer_cast(std::make_shared(LuaSignalConnection(state))); + connections.push_back(conn); + return SignalConnectionRef(conn); } void Signal::Fire(std::vector args) { @@ -104,6 +111,8 @@ void SignalConnection::Disconnect() { // +static int signal_Connect(lua_State*); + static int signal_gc(lua_State*); static int signal_index(lua_State*); static int signal_tostring(lua_State*); @@ -114,26 +123,6 @@ static const struct luaL_Reg signal_metatable [] = { {NULL, NULL} /* end of array */ }; - -static int signal_gc(lua_State* L) { - // Destroy the contained shared_ptr - auto userdata = (std::weak_ptr*)luaL_checkudata(L, 1, "__mt_signal"); - delete userdata; - lua_pop(L, 1); - - return 0; -} - -// __index(t,k) -static int signal_index(lua_State* L) { - auto userdata = (std::weak_ptr*)luaL_checkudata(L, 1, "__mt_signal"); - std::weak_ptr signal = *userdata; - std::string key(lua_tostring(L, 2)); - lua_pop(L, 2); - - return luaL_error(L, "'%s' is not a valid member of %s", key.c_str(), "Signal"); -} - Data::SignalRef::SignalRef(std::weak_ptr ref) : signal(ref) {} Data::SignalRef::~SignalRef() = default; @@ -159,8 +148,8 @@ void Data::SignalRef::Serialize(pugi::xml_node node) const { void Data::SignalRef::PushLuaValue(lua_State* L) const { int n = lua_gettop(L); - auto userdata = (std::weak_ptr*)lua_newuserdata(L, sizeof(void*)); - new(userdata) std::weak_ptr(signal); + auto userdata = (std::weak_ptr*)lua_newuserdata(L, sizeof(std::weak_ptr)); + new(userdata) std::weak_ptr(signal); // Create the instance's metatable luaL_newmetatable(L, "__mt_signal"); @@ -175,12 +164,47 @@ result Data::SignalRef::FromLuaValue(lua_State* L, return Data::Variant(Data::SignalRef(*userdata)); } +static int signal_gc(lua_State* L) { + // Destroy the contained shared_ptr + auto userdata = (std::weak_ptr*)luaL_checkudata(L, 1, "__mt_signal"); + delete userdata; + lua_pop(L, 1); + + return 0; +} + +// __index(t,k) +static int signal_index(lua_State* L) { + auto userdata = (std::weak_ptr*)luaL_checkudata(L, 1, "__mt_signal"); + std::weak_ptr signal = *userdata; + std::string key(lua_tostring(L, 2)); + lua_pop(L, 2); + + if (key == "Connect") { + lua_pushcfunction(L, signal_Connect); + return 1; + } + + return luaL_error(L, "'%s' is not a valid member of %s", key.c_str(), "Signal"); +} + static int signal_tostring(lua_State* L) { lua_pop(L, 1); lua_pushstring(L, "Signal"); return 1; } +static int signal_Connect(lua_State* L) { + auto userdata = (std::weak_ptr*)luaL_checkudata(L, 1, "__mt_signal"); + std::shared_ptr signal = (*userdata).lock(); + luaL_checktype(L, 2, LUA_TFUNCTION); + + SignalConnectionRef ref = signal->Connect(L); + ref.PushLuaValue(L); + + return 1; +} + // static int signalconnection_gc(lua_State*); @@ -238,8 +262,8 @@ void Data::SignalConnectionRef::Serialize(pugi::xml_node node) const { void Data::SignalConnectionRef::PushLuaValue(lua_State* L) const { int n = lua_gettop(L); - auto userdata = (std::weak_ptr*)lua_newuserdata(L, sizeof(void*)); - new(userdata) std::weak_ptr(signalConnection); + auto userdata = (std::weak_ptr*)lua_newuserdata(L, sizeof(std::weak_ptr)); + new(userdata) std::weak_ptr(signalConnection); // Create the instance's metatable luaL_newmetatable(L, "__mt_signalconnection"); diff --git a/core/src/datatypes/signal.h b/core/src/datatypes/signal.h index 80222bc..3ccb0bd 100644 --- a/core/src/datatypes/signal.h +++ b/core/src/datatypes/signal.h @@ -15,6 +15,8 @@ class Instance; class Signal; +namespace Data { class SignalConnectionRef; } + class SignalConnection : public std::enable_shared_from_this { protected: std::weak_ptr parentSignal; @@ -60,8 +62,8 @@ public: void DisconnectAll(); void Fire(std::vector args); - void Connect(std::function)> callback); - void Connect(lua_State*); + Data::SignalConnectionRef Connect(std::function)> callback); + Data::SignalConnectionRef Connect(lua_State*); }; class SignalSource : public std::shared_ptr { diff --git a/core/src/objects/script.cpp b/core/src/objects/script.cpp index c41dc26..0d4410a 100644 --- a/core/src/objects/script.cpp +++ b/core/src/objects/script.cpp @@ -15,7 +15,9 @@ int script_wait(lua_State*); int script_delay(lua_State*); Script::Script(): Instance(&TYPE) { - source = "print \"Hello, world!\"\nwait(1)print \"Wait success! :D\""; + source = "workspace.Part.OnParentUpdated:Connect(function()\n\ + print(\"Yeux d'enfants\")\n\ +end)"; } Script::~Script() {