diff options
author | Nao Pross <naopross@thearcway.org> | 2019-01-22 14:01:30 +0100 |
---|---|---|
committer | Nao Pross <naopross@thearcway.org> | 2019-01-22 14:01:30 +0100 |
commit | 59e71b7dbd321eb3dc2ed7afecb66840115c3c15 (patch) | |
tree | cc8dce2f732b90b12bbc5b46c50fd434df4aba14 | |
parent | Add test for task and job, fix bug in job (diff) | |
parent | Duplicate (diff) | |
download | flatland-59e71b7dbd321eb3dc2ed7afecb66840115c3c15.tar.gz flatland-59e71b7dbd321eb3dc2ed7afecb66840115c3c15.zip |
Merge remote-tracking branch 'raffa/master'
-rw-r--r-- | engine/flatcomponent.cpp | 4 | ||||
-rw-r--r-- | engine/flatland.cpp | 16 | ||||
-rw-r--r-- | engine/flatobject.cpp | 61 | ||||
-rw-r--r-- | engine/flatserial.cpp | 2 | ||||
-rw-r--r-- | engine/flatsignal.cpp | 176 | ||||
-rw-r--r-- | engine/flatsurface.cpp | 10 | ||||
-rw-r--r-- | engine/flatwindow.cpp | 14 | ||||
-rw-r--r-- | engine/include/flatbound.h | 4 | ||||
-rw-r--r-- | engine/include/flatcollector.h | 4 | ||||
-rw-r--r-- | engine/include/flatcomponent.h | 4 | ||||
-rw-r--r-- | engine/include/flatobject.h | 36 | ||||
-rw-r--r-- | engine/include/flatserial.h | 4 | ||||
-rw-r--r-- | engine/include/flatsignal.h | 100 | ||||
-rw-r--r-- | engine/include/flatsurface.h | 8 | ||||
-rw-r--r-- | engine/include/flatwindow.h | 6 | ||||
-rw-r--r-- | engine/include/object.hpp | 42 | ||||
-rw-r--r-- | engine/include/serial/focusable.h | 8 | ||||
-rw-r--r-- | engine/include/serial/keyfocusable.h | 2 | ||||
-rw-r--r-- | engine/include/signal.hpp | 112 | ||||
-rw-r--r-- | engine/include/types.hpp (renamed from engine/include/types.h) | 13 | ||||
-rw-r--r-- | engine/keyfocusable.cpp | 2 | ||||
-rw-r--r-- | engine/object.cpp | 62 | ||||
-rw-r--r-- | engine/signal.cpp | 191 | ||||
-rw-r--r-- | test/test3.cpp | 120 |
24 files changed, 581 insertions, 420 deletions
diff --git a/engine/flatcomponent.cpp b/engine/flatcomponent.cpp index 33cfbbc..06b558c 100644 --- a/engine/flatcomponent.cpp +++ b/engine/flatcomponent.cpp @@ -1,5 +1,5 @@ #include "flatcomponent.h" -#include "flatsignal.h" +#include "signal.h" Component::Component(Component *parent, const std::string& id) : parent(parent) @@ -7,7 +7,7 @@ Component::Component(Component *parent, const std::string& id) // TODO, check flatland initialization if (id.empty()) - setID(FlatObject::randomID()); + setID(flat::core::object::randomID()); if (parent == 0) { diff --git a/engine/flatland.cpp b/engine/flatland.cpp index 2f1c920..628331b 100644 --- a/engine/flatland.cpp +++ b/engine/flatland.cpp @@ -10,14 +10,14 @@ using namespace std; #include "flattask.h" -#include "flatsignal.h" +#include "signal.h" #include "flatwindow.h" #include "flatexception.h" #include "exceptions/forcequit.h" float flatland_dt; -set<FlatObject*> objects; +set<flat::core::object*> objects; FlatWindow * window = 0; SignalChannel * core = 0; @@ -29,9 +29,9 @@ flat_status status; float fps; float fps_pause = 5; -Uint32 status_to_flags(const flat_status& s) +uint32_t status_to_flags(const flat_status& s) { - Uint32 flags = 0; + uint32_t flags = 0; if (s.audio) flags |= SDL_INIT_AUDIO; @@ -60,7 +60,7 @@ Uint32 status_to_flags(const flat_status& s) /* Listen to simple quit calls */ class QuitListener : public FlatListener { - virtual void callback(FlatObject*, void*) override + virtual void callback(flat::core::object*, void*) override { /* Order to quit */ quit_flatland(); @@ -97,7 +97,7 @@ int init_flatland(FlatWindow* w, gameloop loop, const flat_status& s, float _fps cout << "Flatland: Initializing SDL" << endl; - Uint32 flags = status_to_flags(s); + uint32_t flags = status_to_flags(s); if ( SDL_Init(flags | SDL_INIT_NOPARACHUTE) < 0) { @@ -170,13 +170,13 @@ int init_flatland(FlatWindow* w, gameloop loop, const flat_status& s, float _fps quit_flatland(); } - SDL_Delay((Uint32) (1000.0f / fps)); + SDL_Delay((uint32_t) (1000.0f / fps)); delay -= clock(); } while (status.loop); - SDL_Delay((Uint32)(1000 / fps_pause)); + SDL_Delay((uint32_t)(1000 / fps_pause)); } while(status.running); diff --git a/engine/flatobject.cpp b/engine/flatobject.cpp deleted file mode 100644 index a325942..0000000 --- a/engine/flatobject.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "flatobject.h" - -#include <stdlib.h> - -using namespace std; - -list<FlatObject*> FlatObject::allObjects; - -FlatObject::FlatObject() -{ - /* Collect this object */ - FlatObject::allObjects.push_back(this); -} - -FlatObject::~FlatObject() -{ - /* Eliminate this object reference */ - FlatObject::allObjects.remove(this); -} - -void FlatObject::setID(const string& id) -{ - this->id = id; -} - -const string& FlatObject::getID() const -{ - return id; -} - -string FlatObject::randomID(Uint8 length) { - - string out; - - for (Uint8 i = 0; i < length; ++i) - out += (char)(rand() % 93 + 33); - - return out; -} - -bool FlatObject::isAllocated(FlatObject *obj) -{ - for (FlatObject * o : FlatObject::allObjects) - { - if (o == obj) - return true; - } - - return false; -} - -vector<FlatObject*>& FlatObject::getByID(const string& id, vector<FlatObject*>& l) -{ - for (FlatObject * obj : FlatObject::allObjects) - { - if (id == obj->getID()) - l.push_back(obj); - } - - return l; -} diff --git a/engine/flatserial.cpp b/engine/flatserial.cpp index 9c49787..7259bf1 100644 --- a/engine/flatserial.cpp +++ b/engine/flatserial.cpp @@ -62,7 +62,7 @@ void SDL_EventCollector::erase(void*) user.clear(); } -const std::vector<SDL_Event>& SDL_EventCollector::getStack(Uint32 id) const +const std::vector<SDL_Event>& SDL_EventCollector::getStack(uint32_t id) const { switch(id) { diff --git a/engine/flatsignal.cpp b/engine/flatsignal.cpp deleted file mode 100644 index a739efc..0000000 --- a/engine/flatsignal.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "flatsignal.h" -#include "flattask.h" - -using namespace std; - -bool sig_prior_cmp::operator()(const FlatSignal& s, const FlatSignal& g) const -{ - return s.priority <= g.priority; -} - -map<string, SignalChannel*> SignalChannel::channels; - -SignalChannel::SignalChannel(const string& id, bool pre_process) -{ - SignalChannel * other = findChannel(id); - - if (!other) - //TODO throw exception - ; - - /* Initialize task, post-process, fifth priority */ - checker = new FlatTask<SignalChannel>( this, - &SignalChannel::post_processing, - 0, - pre_process, - pre_process ? 2 : 10); - - string ID = (id.empty()) ? FlatObject::randomID() : id; - - setID(ID); - - channels.insert(pair<string, SignalChannel*>(ID, this)); -} - -SignalChannel::~SignalChannel() -{ - channels.erase(getID()); - - /* Finalize task */ - delete checker; -} - -void SignalChannel::emit(const FlatSignal& sig) -{ - if (!sig.priority) { - - /* Execute immediately */ - for (auto listener : listeners) - listener->execute(sig); - - } else - /* Insert in order of priority */ - stack.insert(sig); -} - -void SignalChannel::connect(FlatListener* l) -{ - /* Control not to double */ - for (auto listener : listeners) - { - if (listener == l) - return; - } - - listeners.push_back(l); -} - -void SignalChannel::disconnect(FlatListener* l) -{ - listeners.remove(l); -} - - -SignalChannel * SignalChannel::findChannel(const string& id) -{ - if (id.empty()) - return 0; - - auto it = channels.find(id); - - return (it == channels.end()) ? 0 : (*it).second; -} - -void SignalChannel::post_processing(void*) -{ - if (!stack.empty()) { - - /* for each listener, catch signal */ - for (const auto& signal : stack) - { - for (auto listener : listeners) - listener->execute(signal); - } - - stack.clear(); - } -} - - - -/* FlatSignal class */ - -FlatSignal::FlatSignal(FlatObject *sender, const string& id, void *data, Uint8 priority) - : sender(sender), data(data), priority(priority) -{ - setID(id); -} - -bool FlatSignal::emit(const string& channel) const -{ - SignalChannel * chan = SignalChannel::findChannel(channel); - - if (!chan) - return false; - - /* Finally emit in channel */ - chan->emit(*this); - - return true; -} - - - -/* FlatListener class */ - -FlatListener::FlatListener(const initializer_list<string>& filters) - : filters(filters) {} - -bool FlatListener::checkInFilters(const std::string& filter) const -{ - for (const auto& f : filters) - { - if (filter == f) - return true; - } - - return false; -} - -void FlatListener::execute(const FlatSignal& sig) -{ - if ((!sig.getID().empty() && checkInFilters(sig.getID())) || - (sig.getID().empty() && filters.empty())) - callback(sig.sender, sig.data); -} - -void FlatListener::addFilter(const std::string& f) -{ - filters.push_back(f); -} - -void FlatListener::removeFilter(const std::string& f) -{ - filters.remove(f); -} - -bool FlatListener::connect(const std::string& chan) -{ - SignalChannel * c = SignalChannel::findChannel(chan); - - if (!c) - c->connect(this); - - return c != 0; -} - -bool FlatListener::disconnect(const std::string& chan) -{ - SignalChannel * c = SignalChannel::findChannel(chan); - - if (!c) - c->connect(this); - - return c != 0; -} - diff --git a/engine/flatsurface.cpp b/engine/flatsurface.cpp index 1970b71..b3291d6 100644 --- a/engine/flatsurface.cpp +++ b/engine/flatsurface.cpp @@ -4,9 +4,9 @@ using namespace std; -FlatSurface::FlatSurface(const char *filename, Uint32 format, SDL_Surface *parent) +FlatSurface::FlatSurface(const char *filename, uint32_t format, SDL_Surface *parent) - : FlatObject(), parent(parent), hide(false) + : flat::core::object(), parent(parent), hide(false) { setID(filename); @@ -35,7 +35,7 @@ FlatSurface::FlatSurface(const char *filename, Uint32 format, SDL_Surface *paren FlatSurface::FlatSurface(SDL_Surface *surface, SDL_Surface *parent) - : FlatObject(), parent(parent), hide(false) + : flat::core::object(), parent(parent), hide(false) { this->surface = new SDL_Surface(*surface); @@ -56,7 +56,7 @@ FlatSurface::FlatSurface(SDL_Surface *surface, SDL_Surface *parent) FlatSurface::FlatSurface(const FlatSurface &sprite) - : FlatObject(sprite), parent(sprite.parent), + : flat::core::object(sprite), parent(sprite.parent), hide(sprite.hide) { offset = new SDL_Rect(*sprite.offset); @@ -146,7 +146,7 @@ void FlatSurface::blit() SDL_BlitSurface(surface, viewport, parent, offset); } -SDL_Surface * FlatSurface::loadOptimizedSurface(const char *filename, Uint32 format) +SDL_Surface * FlatSurface::loadOptimizedSurface(const char *filename, uint32_t format) { SDL_Surface * optimized = 0; diff --git a/engine/flatwindow.cpp b/engine/flatwindow.cpp index ff17274..40cf1e3 100644 --- a/engine/flatwindow.cpp +++ b/engine/flatwindow.cpp @@ -3,7 +3,7 @@ #include <SDL2/SDL.h> #include <iostream> #include "flatlayer.h" -#include "flatsignal.h" +#include "signal.hpp" using namespace std; @@ -15,7 +15,7 @@ FlatWindow::FlatWindow( int x, int y, : title(title), status(status), sdl_window(0), screen(0) { - setID(title.c_str()); + set_id(title); bounds = new SDL_Rect; @@ -47,7 +47,7 @@ FlatWindow::FlatWindow( int width, int height, FlatWindow::FlatWindow(const FlatWindow& win) - : FlatObject(win), + : flat::core::object(win), title(win.title), status(win.status), sdl_window(0), screen(0) { @@ -68,7 +68,7 @@ FlatWindow::~FlatWindow() int FlatWindow::open() { - Uint32 win_flags = winstatus_to_flags(status); + uint32_t win_flags = winstatus_to_flags(status); sdl_window = SDL_CreateWindow( title.c_str(), bounds->x, @@ -166,14 +166,14 @@ void FlatWindow::key_cb(const SDL_KeyboardEvent *event) close(); /* Say flatland to quit */ - FlatSignal quit(this, "quit", 0, 0xff); + flat::core::signal quit(this, "quit", 0, 0xff); quit.emit("core"); } } -Uint32 FlatWindow::winstatus_to_flags(window_status s) +uint32_t FlatWindow::winstatus_to_flags(window_status s) { - Uint32 flags = 0; + uint32_t flags = 0; if (s.fullscreen) flags |= SDL_WINDOW_FULLSCREEN; diff --git a/engine/include/flatbound.h b/engine/include/flatbound.h index a80cd6e..f5a2c0d 100644 --- a/engine/include/flatbound.h +++ b/engine/include/flatbound.h @@ -1,12 +1,12 @@ #ifndef __FLATBOUND_H__ #define __FLATBOUND_H__ -#include "flatobject.h" +#include "object.hpp" #include "svector.h" typedef SVector<int, 2> pixel; -class FlatBound : virtual public FlatObject +class FlatBound : virtual public flat::core::object { pixel location; diff --git a/engine/include/flatcollector.h b/engine/include/flatcollector.h index ed9a824..d7edf55 100644 --- a/engine/include/flatcollector.h +++ b/engine/include/flatcollector.h @@ -1,10 +1,10 @@ #ifndef __FLATCOLLECTOR_H__ #define __FLATCOLLECTOR_H__ -#include "flatobject.h" +#include "object.hpp" #include <set> -class FlatCollector : virtual public FlatObject +class FlatCollector : virtual public flat::core::object { FlatCollector * parent; diff --git a/engine/include/flatcomponent.h b/engine/include/flatcomponent.h index 8a14d90..807bcaa 100644 --- a/engine/include/flatcomponent.h +++ b/engine/include/flatcomponent.h @@ -1,10 +1,10 @@ #ifndef __FLAT_COMPONENT_H__ #define __FLAT_COMPONENT_H__ -#include "flatobject.h" +#include "object.hpp" #include <string> -class Component : virtual public FlatObject +class Component : virtual public flat::core::object { Component * parent; diff --git a/engine/include/flatobject.h b/engine/include/flatobject.h deleted file mode 100644 index 7ad1ddd..0000000 --- a/engine/include/flatobject.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __FLATOBJECT_H__ -#define __FLATOBJECT_H__ - -#include <list> -#include <vector> -#include <string> -#include <initializer_list> - -#include "types.h" - -class FlatObject -{ - std::string id; - - /* Common list of objects */ - static std::list<FlatObject*> allObjects; - -public: - - FlatObject(); - ~FlatObject(); - - void setID(const std::string&); - - const std::string& getID() const; - - /* Static accessors to allObject */ - - static bool isAllocated(FlatObject*); - - static std::vector<FlatObject*>& getByID(const std::string& id, std::vector<FlatObject*>&); - - static std::string randomID(Uint8 length = 8); -}; - -#endif diff --git a/engine/include/flatserial.h b/engine/include/flatserial.h index f034690..b9e003f 100644 --- a/engine/include/flatserial.h +++ b/engine/include/flatserial.h @@ -1,7 +1,7 @@ #ifndef __FLATSERIAL_H__ #define __FLATSERIAL_H__ -#include "types.h" +#include "types.hpp" #include <vector> #include "SDL2/SDL.h" @@ -33,7 +33,7 @@ struct SDL_EventCollector void collect(void*); void erase(void*); - const std::vector<SDL_Event>& getStack(Uint32 id) const; + const std::vector<SDL_Event>& getStack(uint32_t id) const; }; namespace FlatSerial { diff --git a/engine/include/flatsignal.h b/engine/include/flatsignal.h deleted file mode 100644 index b20d082..0000000 --- a/engine/include/flatsignal.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __FLAT_SIGNAL_H__ -#define __FLAT_SIGNAL_H__ - -#include <map> -#include <list> -#include <set> -#include <initializer_list> -#include "flatobject.h" -#include "types.h" - -/* Post-process signal delivery when it's emitted */ -#define FSIG_PRIOR_INSTANT 0 - -/* Process and emitted signal instantaneously */ -#define FSIG_PRIOR_DEFAULT 5 - -class FlatSignal : virtual public FlatObject -{ - -public: - - FlatObject * sender; - void * data; - Uint8 priority; - - FlatSignal( FlatObject * sender, - const std::string& id = "", - void *data = 0, - Uint8 priority = 5); - - /* Alias to SignalChannel::emit() */ - bool emit(const std::string& channel) const; -}; - -class FlatListener; - -/* Functor for order comparison */ -struct sig_prior_cmp { - - bool operator()(const FlatSignal&, const FlatSignal&) const; -}; - -typedef std::set<FlatSignal, sig_prior_cmp> SignalStack; - -/* Channel class */ -class SignalChannel : virtual public FlatObject -{ - /* Post processing signal stacking */ - SignalStack stack; - - /* Listeners list */ - std::list<FlatListener*> listeners; - - /* Synchronous task checking for signals */ - task_s * checker; - - /* Channel mapping */ - static std::map<std::string, SignalChannel*> channels; - -public: - - SignalChannel(const std::string& id = "", bool pre_process = false); - ~SignalChannel(); - - void emit(const FlatSignal&); - - void connect(FlatListener*); - void disconnect(FlatListener*); - - static SignalChannel * findChannel(const std::string&); - - void post_processing(void*); -}; - -/* Listener class */ -class FlatListener : virtual public FlatObject -{ - std::list<std::string> filters; - - bool checkInFilters(const std::string&) const; - -protected: - - virtual void callback(FlatObject *sender, void *) = 0; - -public: - - FlatListener(const std::initializer_list<std::string>& filters = {}); - virtual ~FlatListener() {} - - void execute(const FlatSignal&); - - void addFilter(const std::string&); - void removeFilter(const std::string&); - - bool connect(const std::string&); - bool disconnect(const std::string&); -}; - -#endif diff --git a/engine/include/flatsurface.h b/engine/include/flatsurface.h index bc04385..3b64734 100644 --- a/engine/include/flatsurface.h +++ b/engine/include/flatsurface.h @@ -1,10 +1,10 @@ #ifndef __FLATSURFACE_H__ #define __FLATSURFACE_H__ -#include "flatobject.h" +#include "object.hpp" #include <SDL2/SDL.h> -class FlatSurface : public FlatObject +class FlatSurface : public flat::core::object { SDL_Surface * surface; SDL_Surface * parent; @@ -16,7 +16,7 @@ class FlatSurface : public FlatObject public: - FlatSurface(const char *filename, Uint32 format = SDL_PIXELFORMAT_RGBA32, SDL_Surface *parent = 0); + FlatSurface(const char *filename, uint32_t format = SDL_PIXELFORMAT_RGBA32, SDL_Surface *parent = 0); FlatSurface(SDL_Surface *surface, SDL_Surface *parent = 0); FlatSurface(const FlatSurface&); @@ -47,7 +47,7 @@ public: void blit(); - static SDL_Surface * loadOptimizedSurface(const char* filename, Uint32 format); + static SDL_Surface * loadOptimizedSurface(const char* filename, uint32_t format); static SDL_Surface * copySurface(SDL_Surface*); }; diff --git a/engine/include/flatwindow.h b/engine/include/flatwindow.h index 11d7134..c03a3a9 100644 --- a/engine/include/flatwindow.h +++ b/engine/include/flatwindow.h @@ -26,7 +26,7 @@ struct window_status unsigned char focus:1; }; -#include "flatobject.h" +#include "object.hpp" #include "serial/keyfocusable.h" class SDL_Window; @@ -34,7 +34,7 @@ class FlatLayer; class SDL_KeyEvent; -class FlatWindow : virtual public FlatObject, public KeyFocusable +class FlatWindow : virtual public flat::core::object, public KeyFocusable { std::string title; window_status status; @@ -91,7 +91,7 @@ public: void setWindowStatus(window_status); - static Uint32 winstatus_to_flags(window_status); + static uint32_t winstatus_to_flags(window_status); }; #endif diff --git a/engine/include/object.hpp b/engine/include/object.hpp new file mode 100644 index 0000000..1992d2a --- /dev/null +++ b/engine/include/object.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include <list> +#include <vector> +#include <string> +#include <initializer_list> + +#include "types.hpp" + +namespace flat +{ + namespace core + { + class object; + } +} + +class flat::core::object +{ + std::string id; + + /* Common list of objects */ + static std::list<object*> all_objects; + +public: + + object(); + ~object(); + + void set_id(const std::string&); + + const std::string& get_id() const; + + /* Static accessors to allObject */ + + static bool is_allocated(object*); + + static std::vector<object*>& get_by_id(const std::string& id, std::vector<object*>&); + + static std::string random_id(uint8_t length = 8); +}; + diff --git a/engine/include/serial/focusable.h b/engine/include/serial/focusable.h index 6478ed4..4880ff8 100644 --- a/engine/include/serial/focusable.h +++ b/engine/include/serial/focusable.h @@ -1,13 +1,13 @@ #ifndef __FOCUSABLE_H__ #define __FOCUSABLE_H__ -#include "flatobject.h" -#include "types.h" +#include "object.hpp" +#include "types.hpp" class task_s; union SDL_Event; -class Focusable : virtual public FlatObject +class Focusable : virtual public flat::core::object { bool focused; @@ -19,7 +19,7 @@ protected: virtual void serial_cb(const SDL_Event*) = 0; /* Event stack specification */ - virtual Uint32 stackID() const = 0; + virtual uint32_t stackID() const = 0; public: diff --git a/engine/include/serial/keyfocusable.h b/engine/include/serial/keyfocusable.h index c97c791..44c1f1b 100644 --- a/engine/include/serial/keyfocusable.h +++ b/engine/include/serial/keyfocusable.h @@ -10,7 +10,7 @@ class KeyFocusable : virtual public Focusable virtual void serial_cb(const SDL_Event*) override; - virtual Uint32 stackID() const override; + virtual uint32_t stackID() const override; protected: diff --git a/engine/include/signal.hpp b/engine/include/signal.hpp new file mode 100644 index 0000000..db6638b --- /dev/null +++ b/engine/include/signal.hpp @@ -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/include/types.h b/engine/include/types.hpp index 003c114..436cc7c 100644 --- a/engine/include/types.h +++ b/engine/include/types.hpp @@ -3,7 +3,14 @@ /* Flatland types */ -class FlatObject; +namespace flat +{ + namespace core + { + class object; + } + +} class FlatActor; class FlatSprite; @@ -26,8 +33,8 @@ class task_s; /* SDL types */ -typedef unsigned char Uint8; -typedef unsigned int Uint32; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; struct SDL_Surface; struct SDL_Rect; diff --git a/engine/keyfocusable.cpp b/engine/keyfocusable.cpp index 39f4b01..29271dc 100644 --- a/engine/keyfocusable.cpp +++ b/engine/keyfocusable.cpp @@ -6,7 +6,7 @@ void KeyFocusable::serial_cb(const SDL_Event *event) key_cb(&event->key); } -Uint32 KeyFocusable::stackID() const +uint32_t KeyFocusable::stackID() const { // Set SDL_KEYDOWN by default return SDL_KEYDOWN; diff --git a/engine/object.cpp b/engine/object.cpp new file mode 100644 index 0000000..990c403 --- /dev/null +++ b/engine/object.cpp @@ -0,0 +1,62 @@ +#include "object.hpp" + +#include <stdlib.h> + +using namespace std; +using namespace flat::core; + +list<object*> object::all_objects; + +object::object() +{ + /* Collect this object */ + object::all_objects.push_back(this); +} + +object::~object() +{ + /* Eliminate this object reference */ + object::all_objects.remove(this); +} + +void object::set_id(const string& id) +{ + this->id = id; +} + +const string& object::get_id() const +{ + return id; +} + +string object::random_id(uint8_t length) { + + string out; + + for (Uint8 i = 0; i < length; ++i) + out += (char)(rand() % 93 + 33); + + return out; +} + +bool object::is_allocated(object *obj) +{ + for (object * o : object::all_objects) + { + if (o == obj) + return true; + } + + return false; +} + +vector<object*>& object::get_by_id(const string& id, vector<object*>& l) +{ + for (object * obj : object::all_objects) + { + if (id == obj->getID()) + l.push_back(obj); + } + + return l; +} diff --git a/engine/signal.cpp b/engine/signal.cpp new file mode 100644 index 0000000..98f133e --- /dev/null +++ b/engine/signal.cpp @@ -0,0 +1,191 @@ +#include "signal.hpp" +#include "task.hpp" + +using namespace std; +using namespace flat::core; + +bool channel::sig_prior_cmp::operator()(const signal& s, const signal& g) const +{ + return s.prior <= g.prior; +} + +map<string, channel*> channel::channels; + +channel::channel(const string& id, task::priority prior) +{ + channel * other = find_channel(id); + + if (!other) + //TODO throw exception + ; + + /* Initialize task, post-process, fifth priority */ + checker = new task<channel>( this, + &channel::post_processing, + 0, + prior); + + string ID = (id.empty()) ? object::random_id() : id; + + set_id(ID); + + channels.insert(pair<string, channel*>(ID, this)); +} + +channel::~channel() +{ + channels.erase(get_id()); + + /* Finalize task */ + delete checker; +} + +void channel::emit(const signal& sig) +{ + if (!sig.priority) { + + /* Execute immediately */ + for (auto lis : listeners) + lis->execute(sig); + + } else + /* Insert in order of priority */ + stack.insert(sig); +} + +void channel::connect(listener* l) +{ + /* Control not to double */ + for (auto lis : listeners) + { + if (lis == l) + return; + } + + listeners.push_back(l); +} + +void channel::disconnect(listener* l) +{ + listeners.remove(l); +} + + +channel * channel::find_channel(const string& id) +{ + if (id.empty()) + return 0; + + auto it = channels.find(id); + + return (it == channels.end()) ? 0 : (*it).second; +} + +void channel::post_processing(void*) +{ + if (!stack.empty()) { + + /* for each listener_s, catch signal */ + for (const auto& signal : stack) + { + for (auto l : listeners) + l->execute(signal); + } + + stack.clear(); + } +} + + + +/* signal class */ + +signal::signal(flat::core::object *sender, const string& id, void *data, Uint8 priority) + : sender(sender), data(data), priority(priority) +{ + set_id(id); +} + +bool signal::emit(const string& channel) const +{ + channel * chan = channel::find_channel(channel); + + if (!chan) + return false; + + /* Finally emit in channel */ + chan->emit(*this); + + return true; +} + + + +/* listener_s class */ + +listener::listener( std::function<void()> m_callback, + const std::initializer_list<std::string>& filters) + + : 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) + { + if (filter == f) + return true; + } + + return false; +} + +void listener::add_filter(const std::string& f) +{ + filters.push_back(f); +} + +void listener::remove_filter(const std::string& f) +{ + filters.remove(f); +} + +bool listener::connect(const std::string& chan) +{ + channel * c = channel::find_channel(chan); + + if (!c) + c->connect(this); + + parent = c; + + return c != 0; +} + +bool listener_s::disconnect(const std::string& chan) +{ + channel * c = channel::find_channel(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; +} + |