Files
Aeon/Aeon/Core/Events.cpp
2025-06-29 23:33:26 +01:00

269 lines
5.8 KiB
C++

#include "Events.hpp"
#include <Aeon/Assert.hpp>
#include <yolo/yolo.hpp>
using Core::EventDispatcher;
using Core::EventListener;
using Core::EventManager;
using Core::GenericEvent;
// TODO: Events should use pre-allocated memory ALWAYS!
// TODO: Look into Bump Allocation
EventListener::EventListener()
{
}
EventListener::~EventListener()
{
}
void EventListener::PushThisAsSink(std::string system)
{
mListenerID = EventManager::GetInstance().RegisterSinkPush(this, system);
AEON_ASSERT(mListenerID != -1, "Cannot register event sink");
}
void EventListener::PushAndStickThisAsSink(std::string system)
{
mListenerID = EventManager::GetInstance().RegisterSinkPushStick(this, system);
AEON_ASSERT(mListenerID != -1, "Cannot register event sink");
}
void EventListener::UnshiftThisAsSink(std::string system)
{
mListenerID = EventManager::GetInstance().RegisterSinkUnshift(this, system);
AEON_ASSERT(mListenerID != -1, "Cannot register event sink");
}
void EventListener::ShiftSinkLeft(std::string forSystem)
{
EventManager::GetInstance().MoveSinkLeft(this, forSystem);
}
void EventListener::ShiftSinkRight(std::string forSystem)
{
EventManager::GetInstance().MoveSinkRight(this, forSystem);
}
void EventListener::DeRegisterAsSink(std::string system)
{
}
EventDispatcher::EventDispatcher()
{
}
EventDispatcher::EventDispatcher(std::string system)
{
RegisterAsSource(system);
}
EventDispatcher::~EventDispatcher()
{
}
void EventDispatcher::RegisterAsSource(std::string system)
{
mDispatcherID = EventManager::GetInstance().RegisterSource(this, system);
AEON_ASSERT(mDispatcherID != -1, "Cannot register event source");
mSystem = system;
}
void EventDispatcher::DeRegisterAsSource(std::string system)
{
}
void EventDispatcher::Dispatch(GenericEvent e)
{
e.System = mSystem;
EventManager::GetInstance().Dispatch(mDispatcherID, e);
}
void EventDispatcher::Dispatch(std::string type)
{
GenericEvent e;
e.Type = type;
e.System = mSystem;
EventManager::GetInstance().Dispatch(mDispatcherID, e);
}
EventManager::EventManager()
{
}
EventManager::~EventManager()
{
}
int EventManager::RegisterSource(EventDispatcher* source, std::string system)
{
int id = mNextHeighest;
mSources[id] = system;
mNextHeighest++;
return id;
}
int EventManager::RegisterSinkPush(EventListener* sink, std::string system)
{
int id = mNextHeighest;
mListeners[id] = sink;
auto& sinkVector = mSinks[system];
sinkVector.push_back({sink, id});
mNextHeighest++;
return id;
}
int EventManager::RegisterSinkPushStick(EventListener* sink, std::string system)
{
int id = mNextHeighest;
mListeners[id] = sink;
auto& sinkVector = mStickySinks[system];
sinkVector.push_back({sink, id});
mNextHeighest++;
return id;
}
int EventManager::RegisterSinkUnshift(EventListener* sink, std::string system)
{
int id = mNextHeighest;
mListeners[id] = sink;
if (!mSinks.count(system))
{
return RegisterSinkPush(sink, system);
}
auto& sinkVector = mSinks[system];
sinkVector.insert(sinkVector.begin(), {sink, id});
mNextHeighest++;
return id;
}
void EventManager::MoveSinkLeft(EventListener* sink, std::string system)
{
}
void EventManager::MoveSinkRight(EventListener* sink, std::string system)
{
}
void EventManager::RemoveSource(int dispatcherID, std::string system)
{
}
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 <typename C>
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 <typename C, size_t N>
struct reverse_wrapper<C[N]>
{
C(&c_)
[N];
reverse_wrapper(C (&c)[N]) : c_(c)
{}
typename std::reverse_iterator<const C*> begin()
{
return std::rbegin(c_);
}
typename std::reverse_iterator<const C*> end()
{
return std::rend(c_);
}
};
template <typename C>
reverse_wrapper<C> r_wrap(C& c)
{
return reverse_wrapper<C>(c);
}
void EventManager::Dispatch(int dispatcherID, GenericEvent e)
{
std::string targetSink = mSources[dispatcherID];
auto stickySinks = mStickySinks[targetSink];
auto sinks = mSinks[targetSink];
if (!stickySinks.empty())
{
for (auto& listenerPair : r_wrap(stickySinks))
{
EventListener* listener = std::get<0>(listenerPair);
bool handled = listener->EventRecieved(e);
if (handled)
e.Handled = handled;
if (e.Handled)
{
// destroy event
return;
}
}
}
if (!sinks.empty())
{
for (auto& listenerPair : r_wrap(sinks))
{
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()
{
yolo::debug("----- BEGIN EVENTS DEBUG -----");
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++;
yolo::debug("{} has {} sticky and {} sink(s) and is being dispatched from {} dufferent source(s)", targetSink, stickySinks.size(), sinks.size(), sourceCount);
}
yolo::debug("----- END EVENTS DEBUG -----");
}