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);
|
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) {
|
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||||
ClassAnalysis anly;
|
ClassAnalysis anly;
|
||||||
|
|
||||||
|
@ -166,7 +182,8 @@ static void processClass(CXCursor cur, AnalysisState* state, std::string classNa
|
||||||
|
|
||||||
anly.name = className;
|
anly.name = className;
|
||||||
anly.serializedName = result["name"];
|
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 == "")
|
if (anly.serializedName == "")
|
||||||
anly.serializedName = className;
|
anly.serializedName = className;
|
||||||
|
|
|
@ -35,7 +35,8 @@ struct ClassAnalysis {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string serializedName;
|
std::string serializedName;
|
||||||
std::string headerPath;
|
std::string headerPath;
|
||||||
bool hasFromString = false;
|
bool hasFromString;
|
||||||
|
bool isSerializable;
|
||||||
std::vector<PropertyAnalysis> properties;
|
std::vector<PropertyAnalysis> properties;
|
||||||
std::vector<MethodAnalysis> methods;
|
std::vector<MethodAnalysis> methods;
|
||||||
std::vector<PropertyAnalysis> staticProperties;
|
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 reactphysics3d { class Vector3; };
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class DEF_DATA_(from_string) Vector3 : public Base {
|
class DEF_DATA Vector3 : public Base {
|
||||||
AUTOGEN_PREAMBLE_DATA
|
AUTOGEN_PREAMBLE_DATA
|
||||||
glm::vec3 vector;
|
glm::vec3 vector;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include "datatypes/cframe.h"
|
#include "datatypes/cframe.h"
|
||||||
#include "datatypes/color3.h"
|
#include "datatypes/color3.h"
|
||||||
|
#include "datatypes/signal.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "rendering/surface.h"
|
#include "rendering/surface.h"
|
||||||
|
@ -91,6 +92,7 @@ public:
|
||||||
DEF_PROP float frontParamB = 0.5;
|
DEF_PROP float frontParamB = 0.5;
|
||||||
DEF_PROP float backParamB = 0.5;
|
DEF_PROP float backParamB = 0.5;
|
||||||
|
|
||||||
|
SignalSource OnParentUpdated;
|
||||||
|
|
||||||
rp::RigidBody* rigidBody = nullptr;
|
rp::RigidBody* rigidBody = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue