diff --git a/Aeon/Core/Events.cpp b/Aeon/Core/Events.cpp index 0498f40..55e32e8 100644 --- a/Aeon/Core/Events.cpp +++ b/Aeon/Core/Events.cpp @@ -117,14 +117,6 @@ int EventManager::RegisterSinkPush( EventListener* sink, std::string system ) int id = mNextHeighest; mListeners[id] = sink; - // if there is no sinks for the system, make sure there is one - if ( !mSinks.count( system ) ) - { - std::vector> v; - mSinks.insert( { system, v } ); - return -1; - } - auto& sinkVector = mSinks[system]; sinkVector.push_back( { sink, id } ); @@ -137,13 +129,6 @@ int EventManager::RegisterSinkPushStick( EventListener* sink, std::string system int id = mNextHeighest; mListeners[id] = sink; - if ( !mStickySinks.count( system ) ) - { - std::vector> v; - mStickySinks.insert( { system, v } ); - return -1; - } - auto& sinkVector = mStickySinks[system]; sinkVector.push_back( { sink, id } ); @@ -188,6 +173,35 @@ void EventManager::RemoveSink( int listenerID, std::string system ) } + +// it is important to reverse the lists so that the dispatching is done correctly +// this is more efficiently done at insert... lol +template +struct reverse_wrapper { + + C& c_; + reverse_wrapper(C& c) : c_(c) {} + + typename C::reverse_iterator begin() { return c_.rbegin(); } + typename C::reverse_iterator end() { return c_.rend(); } +}; + +template +struct reverse_wrapper< C[N] > { + + C(&c_)[N]; + reverse_wrapper(C(&c)[N]) : c_(c) {} + + typename std::reverse_iterator begin() { return std::rbegin(c_); } + typename std::reverse_iterator end() { return std::rend(c_); } +}; + + +template +reverse_wrapper r_wrap(C& c) { + return reverse_wrapper(c); +} + void EventManager::Dispatch( int dispatcherID, GenericEvent e ) { std::string targetSink = mSources[dispatcherID]; @@ -196,7 +210,7 @@ void EventManager::Dispatch( int dispatcherID, GenericEvent e ) if ( !stickySinks.empty() ) { - for ( auto& listenerPair : stickySinks ) + for ( auto& listenerPair : r_wrap(stickySinks)) { EventListener* listener = std::get<0>( listenerPair ); bool handled = listener->EventRecieved( e ); @@ -210,21 +224,37 @@ void EventManager::Dispatch( int dispatcherID, GenericEvent e ) } } - if ( sinks.empty() ) + if (!sinks.empty()) { - return; - } - - for ( auto& listenerPair : sinks ) - { - EventListener* listener = std::get<0>( listenerPair ); - bool handled = listener->EventRecieved(e); - if ( handled ) e.Handled = handled; - - if ( e.Handled ) + for (auto& listenerPair : r_wrap(sinks)) { - // destroy event - return; + EventListener* listener = std::get<0>(listenerPair); + bool handled = listener->EventRecieved(e); + if (handled) e.Handled = handled; + + if (e.Handled) + { + // destroy event + return; + } } } + +} + +void EventManager::DebugPrint() +{ + std::cout << "----- BEGIN EVENTS DEBUG -----" << std::endl; + for (auto const& [dispatcher, targetSink] : mSources) + { + auto stickySinks = mStickySinks[targetSink]; + auto sinks = mSinks[targetSink]; + + int sourceCount = 0; + for (auto const& [id, source] : mSources) + if (source == targetSink) sourceCount++; + + std::cout << targetSink << " has " << stickySinks.size() << " sticky and " << sinks.size() << " sink(s) and is being dispatched from " << sourceCount << " different source(s)" << std::endl; + } + std::cout << "----- END EVENTS DEBUG -----" << std::endl; } diff --git a/Aeon/Core/Events.hpp b/Aeon/Core/Events.hpp index 1ea147a..d533749 100644 --- a/Aeon/Core/Events.hpp +++ b/Aeon/Core/Events.hpp @@ -147,6 +147,9 @@ public: void RemoveSink( int listenerID, std::string system ); void Dispatch( int dispatcherID, GenericEvent e ); + + void DebugPrint(); + private: // indexed by listener ID for quick lookup diff --git a/DEVL.md b/DEVL.md index 8332b09..eebaad3 100644 --- a/DEVL.md +++ b/DEVL.md @@ -10,7 +10,7 @@ For milestones see the project notion page [here](https://www.notion.so/Aeon-e34 ## Status -### 2021-11-12 - Benjamin Kyd +### 2021-11-12 - Ben * Development restarts * Issue with SDL2 Resolved as well as the broken shit in d69b6a is fixed diff --git a/Game/ExampleGame.cpp b/Game/ExampleGame.cpp index 30cf46a..520ad32 100644 --- a/Game/ExampleGame.cpp +++ b/Game/ExampleGame.cpp @@ -6,10 +6,14 @@ #include #include -class Level : public Aeon::Core::GameLayer +class BottomestLevel : public Aeon::Core::GameLayer { public: - Level() { } + BottomestLevel() + { + UnshiftThisAsSink("GAME_LOL"); + Aeon::Core::EventManager::GetInstance().DebugPrint(); + } void Attach() override { @@ -26,9 +30,9 @@ public: } - bool EventRecieved( Aeon::Core::GenericEvent& e ) override + bool EventRecieved(Aeon::Core::GenericEvent& e) override { - + std::cout << "FROM BOTTOMESTLEVEL " << e.System << " " << e.Type << " " << e.Data << std::endl; return false; } @@ -38,10 +42,92 @@ public: } }; + +class BottomLevel : public Aeon::Core::GameLayer +{ +public: + BottomLevel() + { + PushThisAsSink("GAME_LOL"); + Aeon::Core::EventManager::GetInstance().DebugPrint(); + } + + void Attach() override + { + + } + + void FrameTick() override + { + + } + + void TimeTick() override + { + + } + + bool EventRecieved(Aeon::Core::GenericEvent& e) override + { + std::cout << "FROM BOTTOMLEVEL " << e.System << " " << e.Type << " " << e.Data << std::endl; + return false; + } + + void Detach() override + { + + } +}; + +class Level : public Aeon::Core::GameLayer +{ +public: + Level() + { + mEventDispatcher.RegisterAsSource("GAME_LOL"); + PushThisAsSink("GAME_LOL"); + Aeon::Core::EventManager::GetInstance().DebugPrint(); + } + + void Attach() override + { + + } + + void FrameTick() override + { + mEventDispatcher.Dispatch("Lmao gottem"); + + } + + void TimeTick() override + { + + } + + bool EventRecieved( Aeon::Core::GenericEvent& e ) override + { + std::cout << "FROM LEVEL " << e.System << " " << e.Type << " " << e.Data << std::endl; + return false; + } + + void Detach() override + { + + } + + Aeon::Core::EventDispatcher mEventDispatcher; + +}; + class TopLevel : public Aeon::Core::GameLayer { public: - TopLevel() { } + TopLevel() + { + PushAndStickThisAsSink("GAME_LOL"); + Aeon::Core::EventManager::GetInstance().DebugPrint(); + } void Attach() override { @@ -60,7 +146,43 @@ public: bool EventRecieved( Aeon::Core::GenericEvent& e ) override { + std::cout << "FROM TOPLEVEL " << e.System << " " << e.Type << " " << e.Data << std::endl; + return false; + } + void Detach() override + { + + } +}; + +class ToperLevel : public Aeon::Core::GameLayer +{ +public: + ToperLevel() + { + PushAndStickThisAsSink("GAME_LOL"); + Aeon::Core::EventManager::GetInstance().DebugPrint(); + } + + void Attach() override + { + + } + + void FrameTick() override + { + + } + + void TimeTick() override + { + + } + + bool EventRecieved(Aeon::Core::GenericEvent& e) override + { + std::cout << "FROM TOPERLEVEL " << e.System << " " << e.Type << " " << e.Data << std::endl; return false; } @@ -78,10 +200,16 @@ public: ExampleGame() : App( { "Example" }, { "Game with AEON!" } ) { + BottomestLevel* bottomestLevel = new BottomestLevel; + BottomLevel* bottomLevel = new BottomLevel; Level* level = new Level; TopLevel* topLevel = new TopLevel; + ToperLevel* toperLevel = new ToperLevel; + PushLayer( (Aeon::Core::GameLayer*)bottomestLevel ); + PushLayer( (Aeon::Core::GameLayer*)bottomLevel ); PushLayer( (Aeon::Core::GameLayer*)level ); PushLayer( (Aeon::Core::GameLayer*)topLevel ); + PushLayer( (Aeon::Core::GameLayer*)toperLevel); Run(); delete level; } diff --git a/docs/Events.md b/docs/Events.md index e69de29..d83d025 100644 --- a/docs/Events.md +++ b/docs/Events.md @@ -0,0 +1,3 @@ +# Events + +The event system of Aeon is a simple source/sink model similar to the subscriber/publisher model. Anything can register as a source and \ No newline at end of file