#pragma once #include #include #include #include #include #include #include #include "Event.h" #include "EventHandler.h" //#include "keyCodes.h" class EventManager { public: EventManager(const EventManager &) = delete; const EventManager & operator=(const EventManager &) = delete; static EventManager & get_instance() { static EventManager instance; return instance; } template void subscribe(EventHandler && callback, int channel = 0); template void unsubscribe(const EventHandler &, int eventId); template void trigger_event(const EventType & event, int channel); template void queue_event(EventType&& event, int channel); void dispatch_events(); private: EventManager() = default; std::vector, int, std::type_index>> events_queue; std::unordered_map>> subscribers; std::unordered_map>>> subscribers_by_event_id; }; template void EventManager::subscribe(EventHandler && callback, int channel){ std::type_index event_type = typeid(EventType); auto handler = std::make_unique>(callback); if (channel) { auto & handlers_map = subscribers_by_event_id[event_type]; auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { handlers->second.emplace_back(std::move(handler)); } else { handlers_map[channel].emplace_back(std::move(handler)); } } else { subscribers[event_type].emplace_back(std::move(handler)); } } template void EventManager::queue_event(EventType&& event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); std::unique_ptr event_ptr = std::make_unique(std::forward(event)); std::tuple, int, std::type_index> tuple( std::move(event_ptr), channel, event_type ); events_queue.push_back(std::move(tuple)); } template void EventManager::trigger_event(const EventType & event, int eventId) { std::type_index event_type = std::type_index(typeid(EventType)); if (eventId > 0) { auto handlers_it = subscribers_by_event_id[event_type].find(eventId); if (handlers_it != subscribers_by_event_id[event_type].end()) { auto & callbacks = handlers_it->second; for (auto it = callbacks.begin(); it != callbacks.end();) { if ((*it)->exec(event)) { it = callbacks.erase(it); } else { ++it; } } } } else { auto & handlers = subscribers[event_type]; for (auto & handler : handlers) { handler->exec(event); } } } template void EventManager::unsubscribe(const EventHandler & callback, int channel) { std::type_index event_type(typeid(EventType)); const std::string handler_name = callback.target_type().name(); if (channel) { auto subscriber_list = subscribers_by_event_id.find(event_type); if (subscriber_list != subscribers_by_event_id.end()) { auto& handlers_map = subscriber_list->second; auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { auto& callbacks = handlers->second; for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { if ((*it)->get_type() == handler_name) { it = callbacks.erase(it); return; } } } } } else { auto handlers_it = subscribers.find(event_type); if (handlers_it != subscribers.end()) { auto& handlers = handlers_it->second; for (auto it = handlers.begin(); it != handlers.end(); ++it) { if ((*it)->get_type() == handler_name) { it = handlers.erase(it); return; } } } } }