feat(lua): added signal type
This commit is contained in:
parent
1c70d2956f
commit
b0119ac89a
6 changed files with 202 additions and 3 deletions
|
@ -158,6 +158,22 @@ static void processProperty(CXCursor cur, ClassAnalysis* state) {
|
|||
state->properties.push_back(anly);
|
||||
}
|
||||
|
||||
static bool hasMethod(CXCursor cur, std::string methodName) {
|
||||
bool found = false;
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
if (kind != CXCursor_CXXMethod) return CXChildVisit_Continue;
|
||||
|
||||
if (x_clang_toString(clang_getCursorSpelling(cur)) == methodName) {
|
||||
found = true;
|
||||
return CXChildVisit_Break;
|
||||
}
|
||||
|
||||
return CXChildVisit_Continue;
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||
ClassAnalysis anly;
|
||||
|
||||
|
@ -166,7 +182,8 @@ static void processClass(CXCursor cur, AnalysisState* state, std::string classNa
|
|||
|
||||
anly.name = className;
|
||||
anly.serializedName = result["name"];
|
||||
anly.hasFromString = result.count("from_string") > 0;
|
||||
anly.hasFromString = hasMethod(cur, "FromString");
|
||||
anly.isSerializable = hasMethod(cur, "Serialize") && hasMethod(cur, "Deserialize");
|
||||
|
||||
if (anly.serializedName == "")
|
||||
anly.serializedName = className;
|
||||
|
|
|
@ -35,7 +35,8 @@ struct ClassAnalysis {
|
|||
std::string name;
|
||||
std::string serializedName;
|
||||
std::string headerPath;
|
||||
bool hasFromString = false;
|
||||
bool hasFromString;
|
||||
bool isSerializable;
|
||||
std::vector<PropertyAnalysis> properties;
|
||||
std::vector<MethodAnalysis> methods;
|
||||
std::vector<PropertyAnalysis> staticProperties;
|
||||
|
|
100
core/src/datatypes/signal.cpp
Normal file
100
core/src/datatypes/signal.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include "signal.h"
|
||||
#include "meta.h"
|
||||
#include "lua.h"
|
||||
#include <luajit-2.1/lua.h>
|
||||
#include <memory>
|
||||
|
||||
SignalSource::SignalSource() {}
|
||||
SignalSource::~SignalSource() = default;
|
||||
|
||||
Signal::Signal() {}
|
||||
Signal::~Signal() = default;
|
||||
|
||||
SignalConnection::~SignalConnection() = default;
|
||||
|
||||
// Only used for its address
|
||||
int __savedThreads;
|
||||
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);
|
||||
|
||||
lua_pushthread(thread); // key
|
||||
lua_pushboolean(thread, true); // value
|
||||
lua_rawset(thread, -3); // set
|
||||
|
||||
lua_pop(thread, 1); // Pop __savedThreads
|
||||
}
|
||||
|
||||
LuaSignalConnection::~LuaSignalConnection() {
|
||||
// Remove thread so that it can get properly GC'd
|
||||
lua_pushlightuserdata(thread, &__savedThreads);
|
||||
lua_gettable(thread, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_pushthread(thread); // key
|
||||
lua_pushnil(thread); // value
|
||||
lua_rawset(thread, -3); // set
|
||||
|
||||
lua_pop(thread, 1); // Pop __savedThreads
|
||||
}
|
||||
|
||||
void LuaSignalConnection::Call(std::vector<Data::Variant> args) {
|
||||
for (Data::Variant arg : args) {
|
||||
arg.PushLuaValue(thread);
|
||||
}
|
||||
|
||||
int status = lua_resume(thread, args.size());
|
||||
if (status > LUA_YIELD) {
|
||||
Logger::error(lua_tostring(thread, -1));
|
||||
lua_pop(thread, 1); // Pop return value
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
CSignalConnection::CSignalConnection(std::function<void(std::vector<Data::Variant>)> func) {
|
||||
this->function = func;
|
||||
}
|
||||
|
||||
void CSignalConnection::Call(std::vector<Data::Variant> args) {
|
||||
function(args);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void Signal::Connect(std::function<void(std::vector<Data::Variant>)> callback) {
|
||||
connections.push_back(std::dynamic_pointer_cast<SignalConnection>(std::make_shared<CSignalConnection>(callback)));
|
||||
}
|
||||
|
||||
void Signal::Connect(lua_State* state) {
|
||||
connections.push_back(std::dynamic_pointer_cast<SignalConnection>(std::make_shared<LuaSignalConnection>(state)));
|
||||
}
|
||||
|
||||
void Signal::Fire(std::vector<Data::Variant> args) {
|
||||
for (std::shared_ptr<SignalConnection> connection : connections) {
|
||||
connection->Call(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Signal::DisconnectAll() {
|
||||
for (std::shared_ptr<SignalConnection> connection : connections) {
|
||||
connection->parentSignal = {};
|
||||
}
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
void SignalConnection::Disconnect() {
|
||||
if (!Connected()) return;
|
||||
auto signal = parentSignal.lock();
|
||||
for(auto it = signal->connections.begin(); it != signal->connections.end();) {
|
||||
if (*it == shared_from_this())
|
||||
it = signal->connections.erase(it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
parentSignal = {};
|
||||
}
|
79
core/src/datatypes/signal.h
Normal file
79
core/src/datatypes/signal.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// Ultimately, there's two routes:
|
||||
// 1. Signals are tied to Instances and are basically just keys that refer to events in the instance
|
||||
// 2. Signals are independent of Instances, but intermingled.
|
||||
// I chose 2 because it gives Signals a higher class, and felt easier to implement
|
||||
// This means that they can be used independently of Instance if need be in the future
|
||||
|
||||
class Instance;
|
||||
class Signal;
|
||||
|
||||
class SignalConnection : public std::enable_shared_from_this<SignalConnection> {
|
||||
protected:
|
||||
std::weak_ptr<Signal> parentSignal;
|
||||
|
||||
virtual ~SignalConnection();
|
||||
|
||||
virtual void Call(std::vector<Data::Variant>);
|
||||
friend Signal;
|
||||
public:
|
||||
inline bool Connected() { return !parentSignal.expired(); };
|
||||
void Disconnect();
|
||||
};
|
||||
|
||||
class CSignalConnection : protected SignalConnection {
|
||||
std::function<void(std::vector<Data::Variant>)> function;
|
||||
|
||||
CSignalConnection(std::function<void(std::vector<Data::Variant>)>);
|
||||
|
||||
friend Signal;
|
||||
protected:
|
||||
void Call(std::vector<Data::Variant>) override;
|
||||
};
|
||||
|
||||
class LuaSignalConnection : protected SignalConnection {
|
||||
lua_State* thread;
|
||||
|
||||
LuaSignalConnection(lua_State*);
|
||||
~LuaSignalConnection();
|
||||
|
||||
friend Signal;
|
||||
protected:
|
||||
void Call(std::vector<Data::Variant>) override;
|
||||
};
|
||||
|
||||
class Signal {
|
||||
std::vector<std::shared_ptr<SignalConnection>> connections;
|
||||
|
||||
friend SignalConnection;
|
||||
public:
|
||||
Signal();
|
||||
virtual ~Signal();
|
||||
|
||||
void DisconnectAll();
|
||||
void Fire(std::vector<Data::Variant> args);
|
||||
void Connect(std::function<void(std::vector<Data::Variant>)> callback);
|
||||
void Connect(lua_State*);
|
||||
};
|
||||
|
||||
class SignalSource : public std::shared_ptr<Signal> {
|
||||
public:
|
||||
SignalSource();
|
||||
virtual ~SignalSource();
|
||||
};
|
||||
|
||||
namespace Data {
|
||||
class SignalRef : public Data::Base {
|
||||
std::weak_ptr<Signal> signal;
|
||||
};
|
||||
|
||||
class SignalConnectionRef : public Data::Base {
|
||||
std::weak_ptr<Signal> signal;
|
||||
};
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
namespace reactphysics3d { class Vector3; };
|
||||
|
||||
namespace Data {
|
||||
class DEF_DATA_(from_string) Vector3 : public Base {
|
||||
class DEF_DATA Vector3 : public Base {
|
||||
AUTOGEN_PREAMBLE_DATA
|
||||
glm::vec3 vector;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <glm/ext.hpp>
|
||||
#include "datatypes/cframe.h"
|
||||
#include "datatypes/color3.h"
|
||||
#include "datatypes/signal.h"
|
||||
#include "datatypes/vector.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "rendering/surface.h"
|
||||
|
@ -91,6 +92,7 @@ public:
|
|||
DEF_PROP float frontParamB = 0.5;
|
||||
DEF_PROP float backParamB = 0.5;
|
||||
|
||||
SignalSource OnParentUpdated;
|
||||
|
||||
rp::RigidBody* rigidBody = nullptr;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue