-
Notifications
You must be signed in to change notification settings - Fork 1
/
EventSystem.hpp
105 lines (85 loc) · 2.84 KB
/
EventSystem.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#pragma once
#include "Console.hpp"
#include "EventData.hpp"
namespace lite // types
{
// Function capable of handling events.
typedef function<void(EventData&)> EventHandlerFunction;
// Generic system for registering event handlers and invoking events.
class EventSystem : public Singleton<EventSystem>
{
private: // data
// Stores a handler function and its id.
typedef pair<size_t, EventHandlerFunction> IdHandlerPair;
// Stores all event handlers mapped by name.
unordered_map<string, vector<IdHandlerPair>> eventHandlerMap;
public: // methods
// Adds a handler given its event name, handler function, and an optional unique id.
size_t AddHandler(const string& eventName, EventHandlerFunction fn, size_t id = GenerateHandlerId())
{
eventHandlerMap[eventName].push_back(make_pair(id, move(fn)));
return id;
}
// Returns whether the event exists in the system.
bool Exists(const string& name) const
{
return eventHandlerMap.find(name) != eventHandlerMap.end();
}
// Returns a unique id for event handlers.
static size_t GenerateHandlerId()
{
static size_t id = 0;
return id++;
}
// Call an event with no data.
size_t Invoke(string name)
{
EventData data;
return Invoke(move(name), data);
}
// Call an event with data.
size_t Invoke(string name, EventData& data)
{
if (!Exists(name)) return 0;
// Get the map of event handlers, /then/ move
// 'name' into the EventData structure.
auto& handlers = eventHandlerMap[name];
data.eventName = move(name);
// Call all handlers registered for this event.
// Called in reverse order so on-destruction events will cleanup
// in the correct order.
for (auto it = handlers.rbegin(); it != handlers.rend(); ++it)
{
it->second(data);
}
return handlers.size();
}
// Removes an event handler given the event name and id.
// Note this automatically happens upon ~EventHandler().
void RemoveHandler(const string& eventName, size_t id)
{
vector<IdHandlerPair>& handlerPairs = eventHandlerMap[eventName];
// Find the handler matching the given id.
auto it = find_if(
handlerPairs.begin(),
handlerPairs.end(),
[&](IdHandlerPair& pair) { return pair.first == id; });
if (it == handlerPairs.end()) return;
// Erase the handler from the array.
handlerPairs.erase(it);
}
};
} // namespace lite
namespace lite // functions
{
// Call an event with no data.
inline size_t InvokeEvent(string name)
{
return EventSystem::Instance().Invoke(move(name));
}
// Call an event with data.
inline size_t InvokeEvent(string name, EventData& data)
{
return EventSystem::Instance().Invoke(move(name), data);
}
} // namespace lite