SleakEngine
0.1.0
C++23 multi-backend game engine
Toggle main menu visibility
Loading...
Searching...
No Matches
Event.hpp
Go to the documentation of this file.
1
#ifndef _EVENT_H_
2
#define _EVENT_H_
3
4
#include <
Core/OSDef.hpp
>
5
#include <string>
6
#include <functional>
7
#include <unordered_map>
8
#include <vector>
9
#include <
Events/Delegate.hpp
>
10
11
12
#define BIND_LAMBDA(fn) [this](auto&&... args) -> decltype(auto) { return this->fn(std::forward<decltype(args)>(args)...); }
13
#define BIND_FUNC_0(Function, class_name) std::bind(&class_name::Function, this)
14
#define BIND_FUNC_1(Function, class_name) std::bind(&class_name::Function, this, std::placeholders::_1)
15
#define BIND_FUNC_2(Function, class_name) std::bind(&class_name::Function, this, std::placeholders::_2)
16
#define BIND_FUNC_3(Function, class_name) std::bind(&class_name::Function, this, std::placeholders::_3)
17
18
#define GET_DISPATCHER Sleak::EventDispatcher::GetInstance()
19
20
namespace
Sleak
{
21
/// Concrete kind of Event; each Event subclass reports one of these via GetEventType().
22
/// @ingroup events
23
enum class
EventType
{
24
Unknown
= 0,
25
WindowOpen
,
WindowClose
,
WindowResize
,
WindowFullscreen
,
WindowFocus
,
WindowLostFocus
,
WindowMoved
,
26
Tick
,
Update
,
Render
,
27
KeyPressed
,
KeyReleased
,
KeyTyped
,
28
MousePressed
,
MouseReleased
,
MouseMoved
,
MouseScrolled
29
};
30
31
/// Bitmask groups an Event can belong to, queried via Event::IsInCategory().
32
/// @ingroup events
33
enum class
EventCategory
{
34
None
= (1 << 0),
35
Application
= (1 << 1),
36
Input
= (1 << 2),
37
Keyboard = (1 << 3),
38
Mouse
= (1 << 4),
39
MouseButton = (1 << 5)
40
};
41
42
#define EVENT_CLASS_TYPE(type) \
43
static EventType GetStaticType() \
44
{ \
45
return EventType::type;\
46
}\
47
virtual EventType GetEventType() const override \
48
{\
49
return GetStaticType();\
50
}\
51
virtual const char* GetName() const override \
52
{\
53
return #type;\
54
}
55
56
#define EVENT_CLASS_CATEGORY(category)\
57
virtual int GetCategoryFlags() const override \
58
{ return static_cast<int>(category); }
59
60
/// Base for all engine events; carries type/category identity and the
61
/// Handled flag consumers can set to stop further propagation.
62
/// @ingroup events
63
class
ENGINE_API
Event
{
64
public
:
65
Event
() {}
66
67
virtual
~Event
() =
default
;
68
69
bool
Handled
=
false
;
70
71
virtual
EventType
GetEventType
()
const
= 0;
72
virtual
const
char
*
GetName
()
const
= 0;
73
virtual
int
GetCategoryFlags
()
const
= 0;
74
virtual
std::string
ToString
()
const
{
return
GetName
(); }
75
76
bool
IsInCategory
(
EventCategory
category)
77
{
78
return
GetCategoryFlags
() & (uint16_t)category;
79
}
80
};
81
82
/// Static registry mapping EventType to subscribed handlers; dispatches
83
/// events synchronously to every handler registered for its type.
84
///
85
/// Everything here is static, so there is no dispatcher instance to
86
/// pass around: subscribe from anywhere, and the window layer's
87
/// keyboard, mouse, and window events reach you. RegisterEventHandler()
88
/// binds a member function and is the form you will use most;
89
/// RegisterEventCallback() takes a std::function for lambdas and free
90
/// functions.
91
///
92
/// Both return a string id. Keep it and pass it to UnregisterEvent()
93
/// when the subscriber goes away, typically in a scene's OnDeactivate()
94
/// or destructor. Handlers outlive the objects they were bound to
95
/// otherwise, and the next dispatch calls into freed memory.
96
///
97
/// Dispatch is synchronous and runs in registration order on the
98
/// calling thread. The handler list is copied before iteration, so a
99
/// handler may register or unregister during dispatch safely.
100
///
101
/// @code{.cpp}
102
/// class WorldScene : public Sleak::Scene {
103
/// public:
104
/// void Begin() override {
105
/// m_keyId = Sleak::EventDispatcher::RegisterEventHandler(
106
/// this, &WorldScene::OnKeyPressed);
107
/// Sleak::Scene::Begin();
108
/// }
109
///
110
/// void OnDeactivate() override {
111
/// if (!m_keyId.empty()) {
112
/// Sleak::EventDispatcher::UnregisterEvent(
113
/// Sleak::EventType::KeyPressed, m_keyId);
114
/// m_keyId.clear();
115
/// }
116
/// Sleak::Scene::OnDeactivate();
117
/// }
118
///
119
/// void OnKeyPressed(
120
/// const Sleak::Events::Input::KeyPressedEvent& e) {
121
/// if_key_press(KEY__F) { ToggleFlashlight(); }
122
/// }
123
///
124
/// private:
125
/// std::string m_keyId;
126
/// };
127
/// @endcode
128
///
129
/// @see Event, EventType, Events::Input::KeyPressedEvent,
130
/// Events::Input::MouseMovedEvent
131
/// @ingroup events
132
class
ENGINE_API
EventDispatcher
{
133
public
:
134
// Register a handler for any event type
135
/// Registers a free-function/lambda callback for EventT, returning an ID for later unregistration.
136
template
<
typename
EventT>
137
static
std::string
RegisterEventCallback
(std::function<
void
(
const
EventT&)> callback) {
138
EventType
type = EventT::GetStaticType();
139
140
auto
delegate = std::make_shared<EventDelegate<EventT>>(callback);
141
eventHandlers[type].push_back(delegate);
142
143
return
delegate->GetUUID();
144
}
145
146
// Register a member function handler
147
/// Registers a member-function handler bound to instance, returning an ID for later unregistration.
148
template
<
typename
T,
typename
EventT>
149
static
std::string
RegisterEventHandler
(T* instance,
void
(T::*memberFunction)(
const
EventT&)) {
150
EventType
type = EventT::GetStaticType();
151
152
auto
callback = [instance, memberFunction](
const
EventT& event) {
153
(instance->*memberFunction)(event);
154
};
155
156
auto
delegate = std::make_shared<EventDelegate<EventT>>(callback);
157
eventHandlers[type].push_back(delegate);
158
159
return
delegate->GetID();
160
}
161
162
/// Removes the single handler with matching id from type's handler list.
163
static
void
UnregisterEvent
(
EventType
type, std::string
id
) {
164
for
(
auto
it = eventHandlers[type].begin(); it != eventHandlers[type].end(); ++it) {
165
if
((*it)->GetID() ==
id
) {
166
eventHandlers[type].erase(it);
167
break
;
168
}
169
}
170
}
171
172
/// Drops every handler registered for type.
173
static
void
UnregisterEvents
(
EventType
type) {
174
eventHandlers[type].clear();
175
}
176
177
/// Drops every handler for every event type.
178
static
void
UnregisterAllEvents
() {
179
eventHandlers.clear();
180
}
181
182
// Dispatch an event to all registered handlers
183
/// Invokes every handler registered for event's type, in registration order.
184
template
<
typename
EventT>
185
static
void
DispatchEvent
(
const
EventT& event) {
186
EventType
type =
event
.GetEventType();
187
188
if
(eventHandlers.find(type) == eventHandlers.end())
189
return
;
190
191
// Copy the handler list so that handlers which add/remove entries
192
// during dispatch don't invalidate the iteration.
193
auto
handlers = eventHandlers[type];
194
for
(
auto
& handler : handlers) {
195
// Try to cast to the right event delegate type
196
auto
typedDelegate = std::dynamic_pointer_cast<EventDelegate<EventT>>(handler);
197
if
(typedDelegate) {
198
typedDelegate->SetEvent(event);
199
typedDelegate->Execute();
200
}
201
}
202
}
203
204
/// Drops every handler for every event type; equivalent to UnregisterAllEvents().
205
static
void
ClearEventHandlers
() {
206
eventHandlers.clear();
207
}
208
209
private
:
210
static
inline
std::unordered_map<EventType, std::vector<std::shared_ptr<IDelegate>>> eventHandlers;
211
};
212
213
214
// Helper function for easier event dispatching
215
/// Constructs a T from args and dispatches it through EventDispatcher.
216
template
<
typename
T,
typename
... Args>
217
void
DispatchEvent
(Args&&... args) {
218
T event(std::forward<Args>(args)...);
219
EventDispatcher::DispatchEvent
(event);
220
}
221
222
inline
std::ostream&
operator<<
(std::ostream& os,
const
Event
& e)
223
{
224
return
os << e.
ToString
();
225
}
226
}
227
228
#endif
Delegate.hpp
OSDef.hpp
Sleak::Application
Definition
Application.hpp:109
Sleak::EventDispatcher
Definition
Event.hpp:132
Sleak::EventDispatcher::RegisterEventCallback
static std::string RegisterEventCallback(std::function< void(const EventT &)> callback)
Registers a free-function/lambda callback for EventT, returning an ID for later unregistration.
Definition
Event.hpp:137
Sleak::EventDispatcher::ClearEventHandlers
static void ClearEventHandlers()
Drops every handler for every event type; equivalent to UnregisterAllEvents().
Definition
Event.hpp:205
Sleak::EventDispatcher::DispatchEvent
static void DispatchEvent(const EventT &event)
Invokes every handler registered for event's type, in registration order.
Definition
Event.hpp:185
Sleak::EventDispatcher::UnregisterAllEvents
static void UnregisterAllEvents()
Drops every handler for every event type.
Definition
Event.hpp:178
Sleak::EventDispatcher::UnregisterEvent
static void UnregisterEvent(EventType type, std::string id)
Removes the single handler with matching id from type's handler list.
Definition
Event.hpp:163
Sleak::EventDispatcher::RegisterEventHandler
static std::string RegisterEventHandler(T *instance, void(T::*memberFunction)(const EventT &))
Registers a member-function handler bound to instance, returning an ID for later unregistration.
Definition
Event.hpp:149
Sleak::EventDispatcher::UnregisterEvents
static void UnregisterEvents(EventType type)
Drops every handler registered for type.
Definition
Event.hpp:173
Sleak::Event
Definition
Event.hpp:63
Sleak::Event::Handled
bool Handled
Definition
Event.hpp:69
Sleak::Event::IsInCategory
bool IsInCategory(EventCategory category)
Definition
Event.hpp:76
Sleak::Event::Event
Event()
Definition
Event.hpp:65
Sleak::Event::~Event
virtual ~Event()=default
Sleak::Event::ToString
virtual std::string ToString() const
Definition
Event.hpp:74
Sleak::Event::GetCategoryFlags
virtual int GetCategoryFlags() const =0
Sleak::Event::GetName
virtual const char * GetName() const =0
Sleak::Event::GetEventType
virtual EventType GetEventType() const =0
Sleak::EventCategory
EventCategory
Definition
Event.hpp:33
Sleak::EventType
EventType
Definition
Event.hpp:23
Sleak::EventCategory::None
@ None
Definition
Event.hpp:34
Sleak::EventCategory::Mouse
@ Mouse
Definition
Event.hpp:38
Sleak::EventType::Update
@ Update
Definition
Event.hpp:26
Sleak::EventType::Tick
@ Tick
Definition
Event.hpp:26
Sleak::EventType::MousePressed
@ MousePressed
Definition
Event.hpp:28
Sleak::EventType::WindowLostFocus
@ WindowLostFocus
Definition
Event.hpp:25
Sleak::EventType::WindowFocus
@ WindowFocus
Definition
Event.hpp:25
Sleak::EventType::WindowOpen
@ WindowOpen
Definition
Event.hpp:25
Sleak::EventType::MouseReleased
@ MouseReleased
Definition
Event.hpp:28
Sleak::EventType::KeyReleased
@ KeyReleased
Definition
Event.hpp:27
Sleak::EventType::MouseScrolled
@ MouseScrolled
Definition
Event.hpp:28
Sleak::EventType::Render
@ Render
Definition
Event.hpp:26
Sleak::EventType::Unknown
@ Unknown
Definition
Event.hpp:24
Sleak::EventType::KeyTyped
@ KeyTyped
Definition
Event.hpp:27
Sleak::EventType::WindowResize
@ WindowResize
Definition
Event.hpp:25
Sleak::EventType::WindowFullscreen
@ WindowFullscreen
Definition
Event.hpp:25
Sleak::EventType::WindowMoved
@ WindowMoved
Definition
Event.hpp:25
Sleak::EventType::KeyPressed
@ KeyPressed
Definition
Event.hpp:27
Sleak::EventType::MouseMoved
@ MouseMoved
Definition
Event.hpp:28
Sleak::EventType::WindowClose
@ WindowClose
Definition
Event.hpp:25
Sleak::Input
Key and mouse-button code enumerations plus their name lookups.
Definition
InputAction.hpp:9
Sleak
Root namespace for everything the engine exposes.
Definition
Camera.hpp:10
Sleak::DispatchEvent
void DispatchEvent(Args &&... args)
Constructs a T from args and dispatches it through EventDispatcher.
Definition
Event.hpp:217
Sleak::operator<<
std::ostream & operator<<(std::ostream &os, const Event &e)
Definition
Event.hpp:222
include
public
Events
Event.hpp
Generated on
for SleakEngine by
1.18.0