summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorancarola <raffaele.ancarola@epfl.ch>2019-01-22 03:09:51 +0100
committerancarola <raffaele.ancarola@epfl.ch>2019-01-22 03:09:51 +0100
commitbd7015d3dd2a3c0df62c552d447dda574543e895 (patch)
tree5e07ac7a6b6d8df30e2a0fcf47561bf588e4b5cf
parentSed (diff)
downloadflatland-bd7015d3dd2a3c0df62c552d447dda574543e895.tar.gz
flatland-bd7015d3dd2a3c0df62c552d447dda574543e895.zip
Woo
-rw-r--r--engine/include/signal.h112
-rw-r--r--engine/signal.cpp56
-rw-r--r--test/test3.cpp120
3 files changed, 271 insertions, 17 deletions
diff --git a/engine/include/signal.h b/engine/include/signal.h
new file mode 100644
index 0000000..db6638b
--- /dev/null
+++ b/engine/include/signal.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#include <map>
+#include <list>
+#include <set>
+#include <initializer_list>
+#include "object.hpp"
+#include "task.hpp"
+#include "types.h"
+#include <functional>
+
+namespace flat
+{
+ namespace core
+ {
+ class signal;
+ class channel;
+ }
+}
+
+class flat::core::signal : virtual public flat::core::object
+{
+
+public:
+
+ flat::core::object * sender;
+ priority prior;
+
+ signal( flat::core::object * sender,
+ const std::string& id = "",
+ priority prior = 5);
+
+ /* Alias to flat::core::channel::emit() */
+ bool emit(const std::string& channel) const;
+
+ enum class priority : uint8_t
+ {
+ instant = 0,
+ highest,
+ high,
+ none,
+ low,
+ lowest
+ };
+};
+
+
+/* Channel class */
+class flat::core::channel : virtual public flat::core::object
+{
+ /* Post processing signal stacking */
+ stack_t stack;
+
+ /* Listeners list */
+ std::list<flat::core::listener> listeners;
+
+ /* Synchronous task checking for signals */
+ task_s * checker;
+
+ /* Channel mapping */
+ static std::map<std::string, channel*> channels;
+
+public:
+
+ flat::core::channel(const std::string& id = "", flat::core::task::priority prior = flat::core::task::priority::none);
+ ~flat::core::channel();
+
+ void emit(const flat::core::signal&);
+
+ void connect(flat::core::listener_s*);
+ void disconnect(flat::core::listener_s*);
+
+ static flat::core::channel * find_channel(const std::string&);
+
+ void post_processing(void*);
+
+ /* Functor for order comparison */
+ struct sig_prior_cmp {
+
+ bool operator()(const flat::core::signal&, const flat::core::signal&) const;
+ };
+
+ typedef std::set<flat::core::signal, sig_prior_cmp> stack_t;
+};
+
+/* Listener class */
+class flat::core::listener : virtual public flat::core::object
+{
+ std::list<std::string> filters;
+
+ bool check_in_filters(const std::string&) const;
+
+ std::function<void(const flat::core::object*)> m_callback;
+
+ flat::core::channel * parent = 0;
+
+public:
+
+ listener( std::function<void()> m_callback,
+ const std::initializer_list<std::string>& filters = {});
+
+ ~listener();
+
+ void add_filter(const std::string&);
+ void remove_filter(const std::string&);
+
+ bool connect(const std::string&);
+ bool disconnect(const std::string&);
+
+ void invoke(const flat::core::signal&);
+};
+
diff --git a/engine/signal.cpp b/engine/signal.cpp
index d20d840..98f133e 100644
--- a/engine/signal.cpp
+++ b/engine/signal.cpp
@@ -45,33 +45,33 @@ void channel::emit(const signal& sig)
if (!sig.priority) {
/* Execute immediately */
- for (auto listener_s : listener_ss)
- listener_s->execute(sig);
+ for (auto lis : listeners)
+ lis->execute(sig);
} else
/* Insert in order of priority */
stack.insert(sig);
}
-void channel::connect(listener_s* l)
+void channel::connect(listener* l)
{
/* Control not to double */
- for (auto listener_s : listener_ss)
+ for (auto lis : listeners)
{
- if (listener_s == l)
+ if (lis == l)
return;
}
- listener_ss.push_back(l);
+ listeners.push_back(l);
}
-void channel::disconnect(listener_s* l)
+void channel::disconnect(listener* l)
{
- listener_ss.remove(l);
+ listeners.remove(l);
}
-channel * channel::findChannel(const string& id)
+channel * channel::find_channel(const string& id)
{
if (id.empty())
return 0;
@@ -88,8 +88,8 @@ void channel::post_processing(void*)
/* for each listener_s, catch signal */
for (const auto& signal : stack)
{
- for (auto listener_s : listener_ss)
- listener_s->execute(signal);
+ for (auto l : listeners)
+ l->execute(signal);
}
stack.clear();
@@ -123,10 +123,21 @@ bool signal::emit(const string& channel) const
/* listener_s class */
-listener_s::listener_s(const initializer_list<string>& filters)
- : filters(filters) {}
+listener::listener( std::function<void()> m_callback,
+ const std::initializer_list<std::string>& filters)
-bool listener_s::check_in_filters(const std::string& filter) const
+ : m_callback(m_callback), filters(filters)
+{
+
+}
+
+listener::~listener()
+{
+ if (parent != 0)
+ parent->disconnect(this);
+}
+
+bool listener::check_in_filters(const std::string& filter) const
{
for (const auto& f : filters)
{
@@ -137,23 +148,25 @@ bool listener_s::check_in_filters(const std::string& filter) const
return false;
}
-void listener_s::add_filter(const std::string& f)
+void listener::add_filter(const std::string& f)
{
filters.push_back(f);
}
-void listener_s::remove_filter(const std::string& f)
+void listener::remove_filter(const std::string& f)
{
filters.remove(f);
}
-bool listener_s::connect(const std::string& chan)
+bool listener::connect(const std::string& chan)
{
channel * c = channel::find_channel(chan);
if (!c)
c->connect(this);
+ parent = c;
+
return c != 0;
}
@@ -164,6 +177,15 @@ bool listener_s::disconnect(const std::string& chan)
if (!c)
c->connect(this);
+ parent = 0;
+
return c != 0;
}
+void listener::invoke(const flat::core::signal&)
+{
+ if ((!sig.get_id().empty() && check_in_filters(sig.get_id())) ||
+ (sig.get_id().empty() && filters.empty()))
+ m_callback(sig.sender);
+}
+
diff --git a/test/test3.cpp b/test/test3.cpp
new file mode 100644
index 0000000..0edd682
--- /dev/null
+++ b/test/test3.cpp
@@ -0,0 +1,120 @@
+#include "flatland.h"
+#include "flatwindow.h"
+#include "exceptions/forcequit.h"
+
+#include "serial/keyfocusable.h"
+#include <SDL2/SDL.h>
+
+#include <iostream>
+#include <string>
+
+#include "flatsignal.h"
+
+using namespace std;
+
+int count = 0;
+
+void loop(float);
+
+class KeyPrinter : public KeyFocusable
+{
+ virtual void key_cb(const SDL_KeyboardEvent* key) override
+ {
+ string msg = (key->type == SDL_KEYDOWN) ? "pressed" : "released";
+ cout << "KeyPrinter: key " << (char)key->keysym.sym << " " << msg << endl;
+ };
+
+public:
+
+ using KeyFocusable::KeyFocusable;
+};
+
+class KeyCaller : public KeyFocusable
+{
+ int counter;
+ char last;
+
+ virtual void key_cb(const SDL_KeyboardEvent* key) override
+ {
+ if (key->type == SDL_KEYDOWN) {
+
+ char c = key->keysym.sym;
+
+ if (c == last)
+ ++counter;
+ else {
+ last = c;
+ counter = 0;
+ cout << "KeyCaller: Counter set to 0" << endl;
+ }
+ }
+
+ if (counter == 20)
+ {
+ FlatSignal signal(this, "char", (void*)&last);
+ signal.emit("alpha");
+
+ cout << "KeyCaller: 20 times reached" << endl;
+ cout << "KeyCaller: sending " << last << endl;
+ }
+
+ if (counter == 50)
+ {
+ cout << "KeyCaller: 50 times pressed " << last << endl;
+
+ /* Exit application */
+ FlatSignal signal(this, "quit");
+ signal.emit("core");
+ }
+ };
+
+public:
+
+ KeyCaller() : counter(0), last('\0')
+ {
+ setID("CALLER");
+ }
+};
+
+class TwentyListener : public FlatListener
+{
+ virtual void callback(FlatObject *sender, void *data) override
+ {
+ char c = *(char*)data;
+ cout << "TwentyListener: received " << c << " from " << sender->getID() << endl;
+ }
+
+public:
+
+ TwentyListener() : FlatListener({"char"}) {}
+};
+
+KeyPrinter printer;
+KeyCaller caller;
+TwentyListener twlistener;
+
+SignalChannel alpha("alpha");
+
+int main()
+{
+ FlatWindow win(600, 900, "Test 3");
+ flat_status status;
+
+ /* Connect listener to alpha channel */
+ alpha.connect(&twlistener);
+
+ init_flatland(&win, loop, status, 60);
+
+ return 0;
+}
+
+void loop(float dt)
+{
+ ++count;
+
+ if (count == 10000)
+ throw ForceQuit("10000 steps reached");
+
+ //cout << "Loop number: " << count << endl;
+}
+