engine/include/event_system.h

116 lines
3.4 KiB
C
Raw Normal View History

2024-03-31 10:11:22 +00:00
#pragma once
2023-04-29 14:22:25 +00:00
#include <cstddef>
#include <cstdint>
#include <memory>
#include <queue>
#include <unordered_map>
namespace engine {
2023-04-29 14:22:25 +00:00
enum class EventSubscriberKind {
2024-06-04 22:31:22 +00:00
ENTITY,
2023-04-29 14:22:25 +00:00
};
// Event handler base-class
template <typename T>
class EventHandler {
2024-03-31 10:11:22 +00:00
public:
2024-06-04 22:31:22 +00:00
virtual void onEvent(T data) = 0;
2023-04-29 14:22:25 +00:00
};
// Event queue interface to allow for different type queues to be in the map
class IEventQueue {
2024-03-31 10:11:22 +00:00
public:
virtual ~IEventQueue() {}
2024-06-04 22:31:22 +00:00
virtual void despatchEvents() = 0;
2023-04-29 14:22:25 +00:00
};
template <typename T>
class EventQueue : public IEventQueue {
2024-03-31 10:11:22 +00:00
// holds events of type T and subscribers to those events
public:
2024-06-04 22:31:22 +00:00
void subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
2024-03-31 10:11:22 +00:00
{
// For the time being, ignore kind (TODO)
(void)kind;
2024-06-04 22:31:22 +00:00
assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
m_subscribers.emplace(id, handler);
2023-04-29 14:22:25 +00:00
}
2024-06-04 22:31:22 +00:00
void queueEvent(EventSubscriberKind kind, uint32_t id, T event)
2024-03-31 10:11:22 +00:00
{
// For the time being, ignore kind (TODO)
(void)kind;
2024-06-04 22:31:22 +00:00
assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
EventHandler<T>* handler = m_subscribers.at(id);
m_event_queue.emplace(handler, event);
2024-03-31 10:11:22 +00:00
}
2024-06-04 22:31:22 +00:00
void despatchEvents() override
2024-03-31 10:11:22 +00:00
{
2024-06-04 22:31:22 +00:00
while (m_event_queue.empty() == false) {
auto [handler, event] = m_event_queue.front();
handler->onEvent(event);
m_event_queue.pop();
2024-03-31 10:11:22 +00:00
}
}
2023-04-29 14:22:25 +00:00
2024-03-31 10:11:22 +00:00
private:
2024-06-04 22:31:22 +00:00
std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
2023-04-29 14:22:25 +00:00
2024-03-31 10:11:22 +00:00
struct QueuedEvent {
EventHandler<T>* handler;
T event;
};
2024-06-04 22:31:22 +00:00
std::queue<QueuedEvent> m_event_queue{};
2023-04-29 14:22:25 +00:00
};
class EventSystem {
2024-03-31 10:11:22 +00:00
public:
EventSystem() {}
EventSystem(const EventSystem&) = delete;
EventSystem& operator=(const EventSystem&) = delete;
~EventSystem() {}
template <typename T>
2024-06-04 22:31:22 +00:00
void registerEventType()
2024-03-31 10:11:22 +00:00
{
size_t hash = typeid(T).hash_code();
2024-06-04 22:31:22 +00:00
assert(m_event_queues.contains(hash) == false && "Registering an event queue more than once!");
m_event_queues.emplace(hash, std::make_unique<EventQueue<T>>());
2023-04-29 14:22:25 +00:00
}
2024-03-31 10:11:22 +00:00
template <typename T>
2024-06-04 22:31:22 +00:00
void subscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
2024-03-31 10:11:22 +00:00
{
size_t hash = typeid(T).hash_code();
2024-06-04 22:31:22 +00:00
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
2024-03-31 10:11:22 +00:00
assert(queue != nullptr && "This cast should work?!! wot");
2024-06-04 22:31:22 +00:00
queue->subscribe(kind, id, handler);
2024-03-31 10:11:22 +00:00
}
2023-04-29 14:22:25 +00:00
2024-03-31 10:11:22 +00:00
template <typename T>
2024-06-04 22:31:22 +00:00
void queueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
2024-03-31 10:11:22 +00:00
{
size_t hash = typeid(T).hash_code();
2024-06-04 22:31:22 +00:00
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
2024-03-31 10:11:22 +00:00
assert(queue != nullptr && "This cast should work?!! wot");
2024-06-04 22:31:22 +00:00
queue->queueEvent(kind, subscriber_id, event);
2024-03-31 10:11:22 +00:00
}
2024-06-04 22:31:22 +00:00
void despatchEvents()
2024-03-31 10:11:22 +00:00
{
2024-06-04 22:31:22 +00:00
for (auto& [hash, queue] : m_event_queues) {
queue->despatchEvents();
2024-03-31 10:11:22 +00:00
}
}
private:
2024-06-04 22:31:22 +00:00
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> m_event_queues{};
2024-03-31 10:11:22 +00:00
};
2023-04-29 14:22:25 +00:00
2024-03-31 10:11:22 +00:00
} // namespace engine