]> git.tdb.fi Git - libs/game.git/blobdiff - source/game/eventbus.h
Provide a way to request events for existing entities and components
[libs/game.git] / source / game / eventbus.h
index ce9c812e20b1593cbbe6489b537d4ad201f1f52f..a4de18f2bb24c699fb73aea61794b73578cdba77 100644 (file)
@@ -23,9 +23,10 @@ struct EventDispatcher
        { handlers.emplace_back(obs, std::move(cb)); }
 
        void remove_observer(EventObserver *obs)
-       { std::erase_if(handlers, [obs](const Handler &h){ return h.observer==obs; }); }
+       { std::erase_if(handlers, [obs](auto &h){ return h.observer==obs; }); }
 
        void dispatch(const T &) const;
+       void dispatch_to(EventObserver &, const T &) const;
 };
 
 
@@ -52,18 +53,21 @@ public:
 
 private:
        template<typename T>
-       EventDispatcher<T> &get_emitter();
+       EventDispatcher<T> &get_dispatcher();
 
 public:
        template<typename T>
        void add_observer(EventObserver &obs, std::function<void(const T &)> cb)
-       { get_emitter<T>().add_observer(obs, std::move(cb)); }
+       { get_dispatcher<T>().add_observer(&obs, std::move(cb)); }
 
        void replace_observer(EventObserver &, EventObserver &);
        void remove_observer(EventObserver &);
 
        template<typename T>
        void dispatch(const T &) const;
+
+       template<typename T>
+       void dispatch_to(EventObserver &, const T &) const;
 };
 
 
@@ -74,6 +78,14 @@ void EventDispatcher<T>::dispatch(const T &event) const
                h.callback(event);
 }
 
+template<typename T>
+void EventDispatcher<T>::dispatch_to(EventObserver &obs, const T &event) const
+{
+       for(const Handler &h: handlers)
+               if(h.observer==&obs)
+                       h.callback(event);
+}
+
 
 template<typename T>
 inline unsigned EventBus::get_event_id()
@@ -83,7 +95,7 @@ inline unsigned EventBus::get_event_id()
 }
 
 template<typename T>
-inline EventDispatcher<T> &EventBus::get_emitter()
+inline EventDispatcher<T> &EventBus::get_dispatcher()
 {
        unsigned id = get_event_id<T>();
        if(dispatchers.size()<=id)
@@ -94,10 +106,10 @@ inline EventDispatcher<T> &EventBus::get_emitter()
        {
                event.dispatcher = new EventDispatcher<T>;
                event.deleter = [](void *p){ delete static_cast<EventDispatcher<T> *>(p); };
-               event.remover = [](void *p, EventObserver &o){ static_cast<EventDispatcher<T> *>(p)->remove_observer(o); };
+               event.remover = [](void *p, EventObserver &o){ static_cast<EventDispatcher<T> *>(p)->remove_observer(&o); };
        }
 
-       return static_cast<EventDispatcher<T> *>(event.dispatcher);
+       return *static_cast<EventDispatcher<T> *>(event.dispatcher);
 }
 
 template<typename T>
@@ -108,6 +120,14 @@ inline void EventBus::dispatch(const T &event) const
                static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch(event);
 }
 
+template<typename T>
+inline void EventBus::dispatch_to(EventObserver &obs, const T &event) const
+{
+       unsigned id = get_event_id<T>();
+       if(id<dispatchers.size() && dispatchers[id].dispatcher)
+               static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch_to(obs, event);
+}
+
 } // namespace Msp::Game
 
 #endif