|
SleakEngine 1.0.0
C++23 multi-backend game engine
|
This page describes the event dispatch system and the state of hardware input handling in SleakEngine.
| Type | Role |
|---|---|
| Sleak::EventDispatcher | All-static dispatch hub; holds the handler registry and delivers events. |
| Sleak::Event | Base class for every event; carries type, name, category flags, and a Handled flag. |
| Sleak::Delegate<Args...> | std::function wrapper the registry stores handlers as. |
| Sleak::Events::* | Window and application events (resize, open, fullscreen, close, tick). |
| Sleak::Events::Input::* | Keyboard and mouse events. |
| Sleak::Input::KEY_CODE / MOUSE_CODE | Key and mouse button enumerations. |
| Sleak::Input::InputManager / Keyboard | Declared polling API with no implementation; see section 2. |
One SDL poll becomes a typed engine event, and the dispatcher hands it to every handler registered for that event type before returning.
The event dispatch hub is Sleak::EventDispatcher (include/public/Events/Event.hpp), an all-static class backed by an unordered_map<EventType, vector<shared_ptr<IDelegate>>>:
A free helper, Sleak::DispatchEvent<T>(Args&&... args), constructs a T and forwards it to EventDispatcher::DispatchEvent. src/Core/Window.cpp calls this to turn raw SDL input into engine events; game code registers handlers with EventDispatcher::RegisterEventHandler(this, &Class::Method), as used throughout src/Scene/FirstPersonController.cpp.
Sleak::Event (also Events/Event.hpp) is the base class: GetEventType(), GetName(), GetCategoryFlags(), ToString(), and a public Handled flag. Real subclasses:
The EventType enum also lists WindowFocus, WindowLostFocus, and WindowMoved, but no corresponding Event subclasses exist for them yet.
Underneath EventDispatcher, Sleak::Delegate<Args...> (include/public/Events/Delegate.hpp) wraps a std::function<void(Args...)>. It always returns void and is built on std::function, std::shared_ptr, and std::vector, so it is not allocation-free.
Two macros in Events/KeyboardEvent.hpp test a key inside an event handler:
if_key_press is edge-triggered (fires once per press, ignores repeats); if_key_down is level-triggered (fires on every repeat as well).
There is no working hardware-state polling API in the engine. Sleak::Input::InputManager (include/public/Input/InputManager.hpp) only declares RegisterListener / UnregisterListener for an InputEventListener; it has no key or mouse query methods, no .cpp implementation, and is referenced only by the equally unused InputAction.hpp. Sleak::Input::Keyboard (include/public/Input/Keyboard.hpp) declares IsKeyPressed / IsKeyHold / IsKeyReleased(KEY_CODE), but also has no implementation and no call sites anywhere in the engine. include/public/Input/Mouse.hpp is not a class at all; it contains only a commented-out code snippet.
In practice, held-key state is tracked ad hoc per component by registering OnKeyPressed / OnKeyReleased handlers through EventDispatcher and flipping local booleans, as FirstPersonController does. Key and mouse codes are Sleak::Input::KEY_CODE and Sleak::Input::MOUSE_CODE (include/public/Input/KeyCodes.hpp). KEY_CODE values line up with SDL scancodes, and MOUSE_CODE::ButtonLeft equals SDL's Button1 / SDL_BUTTON_LEFT.
Cursor capture has no engine-level API either; controllers toggle it directly with SDL calls, e.g. FirstPersonController::ToggleCursor() calling SDL_ShowCursor() / SDL_HideCursor().
Dispatch is synchronous and single-threaded. DispatchEvent runs every matching handler on the calling thread before it returns, so an event raised from Window::Update() is fully handled before the frame's scene update begins. There is no event queue, no deferred delivery, and no ordering guarantee between handlers beyond registration order.
DispatchEvent copies the handler vector before iterating it, so a handler may register or unregister handlers while it runs without invalidating the loop. Handlers added during dispatch do not receive the event currently being delivered.
RegisterEventHandler returns a std::string id. Keep it and pass it to UnregisterEvent(type, id) when the registering object dies. A handler bound to a destroyed this is a dangling call, and the dispatcher has no way to detect it. Unregister in the same place you destroy the object, typically a scene's destructor or OnDeactivate.
| Question | File |
|---|---|
| How registration and dispatch work | include/public/Events/Event.hpp |
| How a handler is stored and invoked | include/public/Events/Delegate.hpp |
| Where SDL events become engine events | src/Core/Window.cpp (Window::Update) |
| Which events exist | include/public/Events/ApplicationEvent.hpp, KeyboardEvent.hpp, MouseEvent.hpp |
| Key and mouse code values | include/public/Input/KeyCodes.hpp |
| A real handler-based controller | src/Scene/FirstPersonController.cpp |