I have written a very simple algorithm vizualizer where all input is coming from the mouse and I needed an event manager for that. Since I never wrote one before, I wrote a 30 min implementation to act as a placeholder. Now my question is, whether or not I get the idea of an event manager right, does it look the right way? if not can some of you give me some tipps or links to tutorials.
Mouse event:
#ifndef B9E46EEC_476A_469D_9500_CFB8E28280E2 #define B9E46EEC_476A_469D_9500_CFB8E28280E2 #include <SFML/Window/Event.hpp> namespace Pathfinding::Events { struct MouseEvent { MouseEvent(bool eventOnly_, sf::Event::EventType event_, sf::Mouse::Button button_) : eventOnly(eventOnly_), event(event_), button(button_) {} bool eventOnly = false; sf::Event::EventType event; sf::Mouse::Button button; }; } #endif /* B9E46EEC_476A_469D_9500_CFB8E28280E2 */
Mouse data:
#ifndef EF091C2C_702A_4E72_882C_6AB418436A17 #define EF091C2C_702A_4E72_882C_6AB418436A17 #include <SFML\System\Vector2.hpp> namespace Pathfinding::Events { struct MouseData { MouseData(sf::Vector2i cursorPosition_) : cursorPosition(cursorPosition_) {} MouseData(sf::Vector2i cursorPosition_, int32_t wheelDelta_) : cursorPosition(cursorPosition_), wheelDelta(wheelDelta_) {} sf::Vector2i cursorPosition; int32_t wheelDelta; }; } #endif /* EF091C2C_702A_4E72_882C_6AB418436A17 */
Event manager headaer
#ifndef D9DC23B1_9143_4917_B212_390EBA2EE1DF #define D9DC23B1_9143_4917_B212_390EBA2EE1DF #include <functional> #include <deque> #include <SFML/Window/Event.hpp> #include <SFML/Graphics/RenderWindow.hpp> #include <vector> #include "MouseEvent.hpp" #include "IEventManager.hpp" #include "MouseData.hpp" namespace Pathfinding::Events { class EventManager final : public Pathfinding::Abstract::IEventManager { public: EventManager() = default; explicit EventManager(sf::RenderWindow *window); void addBinding(MouseEvent event, std::function<void(MouseData)> callbackFunc) override; void pushEvent(sf::Event event) override; void processEvents() override; private: sf::RenderWindow *windowPtr; std::deque<sf::Event> eventQueue; std::vector<std::pair<MouseEvent, std::function<void(MouseData)>>> callBacks; }; } #endif /* D9DC23B1_9143_4917_B212_390EBA2EE1DF */
Event manager implementation:
#include "EventManager.hpp" #include <SFML/Window/Event.hpp> #include "MouseData.hpp" namespace Pathfinding::Events { EventManager::EventManager(sf::RenderWindow *window) : windowPtr(window) { } void EventManager::addBinding(MouseEvent event, std::function<void(MouseData)> callback) { callBacks.push_back({event, callback}); } void EventManager::pushEvent(sf::Event event) { if (event.type == sf::Event::EventType::Closed) { windowPtr->close(); } eventQueue.push_back(event); } void EventManager::processEvents() { while (!eventQueue.empty()) { sf::Event ¤tEvent = eventQueue[0]; sf::Vector2i mousePos = sf::Mouse::getPosition(*windowPtr); for (auto &callBack : callBacks) { if (currentEvent.type == callBack.first.event) { if (callBack.first.eventOnly || currentEvent.key.code == callBack.first.button) { callBack.second(MouseData(mousePos, currentEvent.mouseWheel.delta)); } } } eventQueue.pop_front(); } } }
Use case:
auto eventManagerUPtr = std::make_unique<EventManager>(&applicationUPtr->window); eventManagerUPtr->addBinding({EVENT_AND_KEY, MouseButtonPressed, sf::Mouse::Left}, std::bind(&IGraphOperations::leftMouseButtonPressed, applicationUPtr->graphOpsUPtr.get(), _1)); eventManagerUPtr->addBinding({EVENT_AND_KEY, MouseButtonPressed, sf::Mouse::Right}, std::bind(&IGraphOperations::rightMouseButtonPressed, applicationUPtr->graphOpsUPtr.get(), _1)); eventManagerUPtr->addBinding({EVENT_ONLY, MouseButtonReleased, NO_MOUSE_BUTTON}, std::bind(&IGraphOperations::mouseButtonReleased, applicationUPtr->graphOpsUPtr.get(), _1)); eventManagerUPtr->addBinding({EVENT_ONLY, MouseMoved, NO_MOUSE_BUTTON}, std::bind(&IGraphOperations::mouseMoved, applicationUPtr->graphOpsUPtr.get(), _1)); eventManagerUPtr->addBinding({EVENT_ONLY, MouseMoved, NO_MOUSE_BUTTON}, std::bind(&IGraphOperations::nodeUnderCursor, applicationUPtr->graphOpsUPtr.get(), _1)); eventManagerUPtr->addBinding({EVENT_ONLY, MouseWheelMoved, NO_MOUSE_BUTTON}, std::bind(&IGraphOperations::mouseWheelMoved, applicationUPtr->graphOpsUPtr.get(), _1)); ... while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { eventManagerUPtr->pushEvent(event); } eventManagerUPtr->processEvents(); draw(); } ...