From 55a3a9e4e42e36cb313386355e68c74423bf4c9e Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 17 Aug 2021 22:14:10 +0100 Subject: [PATCH] eventz --- Aeon/Aeon.cpp | 2 +- Aeon/Assert.hpp | 1 + Aeon/Core/Display.cpp | 14 ++--- Aeon/Core/Events.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++ Aeon/Core/Events.hpp | 88 ++++++++++++++++++++++++++---- Aeon/Singleton.hpp | 1 + Game/ExampleGame.cpp | 29 +++++++++- 7 files changed, 238 insertions(+), 20 deletions(-) diff --git a/Aeon/Aeon.cpp b/Aeon/Aeon.cpp index 4aaf3a8..b364522 100644 --- a/Aeon/Aeon.cpp +++ b/Aeon/Aeon.cpp @@ -13,7 +13,7 @@ App::App( const DisplayProperties& props ) void App::Run() { - while ( !mSIGTERM ) + // while ( !mSIGTERM ) { } diff --git a/Aeon/Assert.hpp b/Aeon/Assert.hpp index cd2aea8..c22799c 100644 --- a/Aeon/Assert.hpp +++ b/Aeon/Assert.hpp @@ -2,6 +2,7 @@ #define AEON_ASSERT_H_ #include +#include #define AEON_ASSERT(x, m) \ if (! (x)) { \ diff --git a/Aeon/Core/Display.cpp b/Aeon/Core/Display.cpp index a9ddfed..a437bab 100644 --- a/Aeon/Core/Display.cpp +++ b/Aeon/Core/Display.cpp @@ -7,8 +7,13 @@ using Aeon::Core::Display; Display::Display() - : mWindow( nullptr ), - mContext( NULL ) + : mWindow( nullptr ) + , mContext( NULL ) +{ + +} + +Display::~Display() { } @@ -54,11 +59,6 @@ bool Display::Create( const DisplayProperties& properties ) return true; } -Display::~Display() -{ - -} - unsigned int Display::GetWidth() { return mWidth; diff --git a/Aeon/Core/Events.cpp b/Aeon/Core/Events.cpp index e69de29..67e8284 100644 --- a/Aeon/Core/Events.cpp +++ b/Aeon/Core/Events.cpp @@ -0,0 +1,123 @@ +#include "Aeon/Core/Events.hpp" + +#include "Aeon/Assert.hpp" + +using Aeon::Core::GenericEvent; +using Aeon::Core::EventListener; +using Aeon::Core::EventDispatcher; +using Aeon::Core::EventManager; + +EventListener::EventListener() +{ + +} + +EventListener::~EventListener() +{ + +} + +void EventListener::RegisterAsSink( std::string system, int layer ) +{ + +} + +void EventListener::DeRegisterAsSink( std::string system ) +{ + +} + +void EventListener::UpdateLayer( int layer ) +{ + +} + + +EventDispatcher::EventDispatcher() +{ + +} + +EventDispatcher::EventDispatcher( std::string system ) +{ + +} + +EventDispatcher::~EventDispatcher() +{ + +} + +void EventDispatcher::RegisterAsSource( std::string system ) +{ + mDispatcherID = EventManager::GetInstance().RegisterSource(*this, system); + AEON_ASSERT( mDispatcherID != -1, "Cannot register event source" ); +} + +void EventDispatcher::DeRegisterAsSource( std::string system ) +{ + +} + +void EventDispatcher::Dispatch( GenericEvent e ) +{ + +} + +void EventDispatcher::Dispatch( std::string data ) +{ + +} + + +EventManager::EventManager() +{ + +} + +EventManager::~EventManager() +{ + +} + +int EventManager::RegisterSource( EventDispatcher& source, std::string system ) +{ + int id = mNextHeighest; + mSources[id] = system; + + mNextHeighest++; + return id; +} + +int EventManager::RegisterSink( EventListener& source, std::string system ) +{ + return -1; +} + +void EventManager::RemoveSource( int dispatcherID, std::string system ) +{ + +} + +void EventManager::RemoveSink( int listenerID, std::string system ) +{ + +} + +void EventManager::Dispatch( int dispatcherID, GenericEvent e ) +{ + std::string targetSink = mSources[dispatcherID]; + auto sinks = mSinks[targetSink]; + + for ( auto& listenerPair : sinks ) + { + int handled = std::get<0>(listenerPair).EventRecieved(e); + if ( handled ) e.Handled = handled; + + if ( e.Handled ) + { + // destroy event + break; + } + } +} diff --git a/Aeon/Core/Events.hpp b/Aeon/Core/Events.hpp index 02bc8c2..b6ce09e 100644 --- a/Aeon/Core/Events.hpp +++ b/Aeon/Core/Events.hpp @@ -2,28 +2,46 @@ #define AEON_CORE_EVENTS_H_ /* - - events are typed and system'd using a subscriber/publisher-esque observer pattern - - systems can request to only receive events from a certain "system" category - - systems that dispatch events can create the event and register it as a type - - events are queued and non - blocking - - events propagate through game layers top - to - bottom - - once an event is flagged as handled by a receiving system, - it is discarded this is to prevent, say a "mouse click" - from propagating from the UI layer to the game layer + - Events have a source and a sink, where from and where too + - Event sinks are systems that events are dispatched to from + a source of the same system + - Event listeners are layered, 0 is front, larger is back so + events propogate from the front to the back, not going + further once handled + - Systems can request to only receive events from a certain + "system" category, or multiple + - Events are blocking for now */ +#include +#include +#include +#include + #include "Aeon/Singleton.hpp" namespace Aeon::Core { struct GenericEvent { + std::string Source; + std::string Sink; + std::string Type; + std::string Data; + bool Handled = false; + GenericEvent() { } }; -struct Dispatcher +struct KeyboardEvent : public GenericEvent { + int KeyCode; + int KeyStatus; + KeyboardEvent( int keyCode, int keyStatus ) + : GenericEvent() + , KeyCode(keyCode) + , KeyStatus(keyStatus) { } }; class EventListener @@ -31,16 +49,64 @@ class EventListener public: EventListener(); virtual ~EventListener(); + + void RegisterAsSink( std::string system, int layer ); + void DeRegisterAsSink( std::string system ); + + void UpdateLayer( int layer ); + + // return true = event handled + virtual bool EventRecieved(GenericEvent& e) = 0; + +private: + int mListenerID = -1; + + friend class EventManager; +}; + +class EventDispatcher +{ +public: + EventDispatcher(); + EventDispatcher( std::string system ); + ~EventDispatcher(); + + void RegisterAsSource( std::string system ); + void DeRegisterAsSource( std::string system ); + + void Dispatch( GenericEvent e ); + void Dispatch( std::string data ); + +private: + int mDispatcherID = -1; + + friend class EventManager; }; class EventManager : public Aeon::Helpers::Singleton { public: + EventManager(); + ~EventManager(); + int RegisterSource( EventDispatcher& source, std::string system ); + int RegisterSink( EventListener& sink, std::string system ); - void RegisterDispatcher(); + void RemoveSource( int dispatcherID, std::string system ); + void RemoveSink( int listenerID, std::string system ); - void Dispatch( GenericEvent& e ); + void Dispatch( int dispatcherID, GenericEvent e ); +private: + + // indexed by listener ID + std::map mListeners; + // indexed by dispatcher ID + std::map mSources; + // indexed by (sink) system ID + // their position in the vector is their layer + std::map>> mSinks; + + int mNextHeighest = 0; }; } diff --git a/Aeon/Singleton.hpp b/Aeon/Singleton.hpp index a2441d9..e905bd5 100644 --- a/Aeon/Singleton.hpp +++ b/Aeon/Singleton.hpp @@ -6,6 +6,7 @@ namespace Aeon::Helpers { template class Singleton { +public: static T& GetInstance() { static T instance; diff --git a/Game/ExampleGame.cpp b/Game/ExampleGame.cpp index 0f94495..f752511 100644 --- a/Game/ExampleGame.cpp +++ b/Game/ExampleGame.cpp @@ -1,7 +1,10 @@ // simple raycast shooter // shotgun fun fun yanno -#include "Aeon/Aeon.hpp" +#include + +#include +#include class ExampleGame : public Aeon::Core::App { @@ -21,9 +24,33 @@ public: }; +class SomeSystem : public Aeon::Core::EventListener +{ + SomeSystem() + { + RegisterAsSink( "System1", 0 ); + } + + ~SomeSystem() override + { + DeRegisterAsSink( "System1" ); + } + + bool EventRecieved( Aeon::Core::GenericEvent& e ) override + { + std::cout << e.Source << ":" << e.Type << ":" << e.Sink << ":" << e.Data << std::endl; + return true; + } + +}; + int main( int argc, char** argv ) { ExampleGame game; + Aeon::Core::EventDispatcher eventDispatcher; + eventDispatcher.RegisterAsSource( "System1" ); + eventDispatcher.Dispatch( Aeon::Core::KeyboardEvent( 12, 1 ) ); + return 0; }