libultraship
Reimplementations of libultra (N64 SDK) functions for modern hardware
Loading...
Searching...
No Matches
EventActionList.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <memory>
5#include <unordered_map>
6#include <unordered_set>
7#include <vector>
8
13
14namespace Ship {
15
28 public:
29 using ActionList::ActionList;
30 using ActionList::Get;
32 using ActionList::Has;
33
39 bool Has(EventID eventId) const;
40
46 std::shared_ptr<std::vector<std::shared_ptr<Action>>> Get(EventID eventId) const;
47
53 std::shared_ptr<std::vector<std::shared_ptr<Action>>> Get(const std::vector<EventID>& eventIds) const;
54
55 protected:
61 void Added(std::shared_ptr<Action> action, const bool forced) override;
62
68 void Removed(std::shared_ptr<Action> action, const bool forced) override;
69
70 private:
71 static bool ShouldInsertBefore(const std::shared_ptr<Action>& existing, const std::shared_ptr<Action>& incoming);
72 void IndexEventAction(const std::shared_ptr<Action>& action);
73 void UnindexEventAction(const std::shared_ptr<Action>& action);
74
75 std::unordered_map<EventID, std::vector<std::shared_ptr<Action>>> mEventActions;
76};
77
78inline bool EventActionList::Has(EventID eventId) const {
79 auto it = mEventActions.find(eventId);
80 return it != mEventActions.end() && !it->second.empty();
81}
82
83inline std::shared_ptr<std::vector<std::shared_ptr<Action>>> EventActionList::Get(EventID eventId) const {
84 auto result = std::make_shared<std::vector<std::shared_ptr<Action>>>();
85 auto it = mEventActions.find(eventId);
86 if (it != mEventActions.end()) {
87 result->insert(result->end(), it->second.begin(), it->second.end());
88 }
89 return result;
90}
91
92inline std::shared_ptr<std::vector<std::shared_ptr<Action>>>
93EventActionList::Get(const std::vector<EventID>& eventIds) const {
94 auto result = std::make_shared<std::vector<std::shared_ptr<Action>>>();
95 std::unordered_set<EventID> seen;
96 for (const auto eventId : eventIds) {
97 if (!seen.insert(eventId).second) {
98 continue;
99 }
100 auto it = mEventActions.find(eventId);
101 if (it != mEventActions.end()) {
102 result->insert(result->end(), it->second.begin(), it->second.end());
103 }
104 }
105 return result;
106}
107
108inline void EventActionList::Added(std::shared_ptr<Action> action, const bool forced) {
109 ActionList::Added(action, forced);
110 IndexEventAction(action);
111
112 // Keep the flat list sorted by EventID so that the generic Get() returns
113 // actions in a predictable EventID-ascending order.
114 auto& list = GetList();
115 std::stable_sort(list.begin(), list.end(), [](const std::shared_ptr<Action>& a, const std::shared_ptr<Action>& b) {
116 const auto* ea = dynamic_cast<const EventAction*>(a.get());
117 const auto* eb = dynamic_cast<const EventAction*>(b.get());
118 if (!ea && !eb) {
119 return false;
120 }
121 if (!ea) {
122 return false;
123 }
124 if (!eb) {
125 return true;
126 }
127 return ea->GetEventId() < eb->GetEventId();
128 });
129}
130
131inline void EventActionList::Removed(std::shared_ptr<Action> action, const bool forced) {
132 UnindexEventAction(action);
133 ActionList::Removed(action, forced);
134}
135
136inline bool EventActionList::ShouldInsertBefore(const std::shared_ptr<Action>& existing,
137 const std::shared_ptr<Action>& incoming) {
138 auto* existingListener = dynamic_cast<ListenerAction*>(existing.get());
139 auto* incomingListener = dynamic_cast<ListenerAction*>(incoming.get());
140 if (existingListener == nullptr || incomingListener == nullptr) {
141 return false;
142 }
143
144 if (incomingListener->GetPriority() != existingListener->GetPriority()) {
145 return incomingListener->GetPriority() < existingListener->GetPriority();
146 }
147
148 return incomingListener->GetSequence() < existingListener->GetSequence();
149}
150
151inline void EventActionList::IndexEventAction(const std::shared_ptr<Action>& action) {
152 auto* eventAction = dynamic_cast<EventAction*>(action.get());
153 if (eventAction == nullptr) {
154 return;
155 }
156
157 auto& bucket = mEventActions[eventAction->GetEventId()];
158 auto insertIt = std::find_if(bucket.begin(), bucket.end(), [&action](const std::shared_ptr<Action>& existing) {
159 return ShouldInsertBefore(existing, action);
160 });
161 bucket.insert(insertIt, action);
162}
163
164inline void EventActionList::UnindexEventAction(const std::shared_ptr<Action>& action) {
165 auto* eventAction = dynamic_cast<EventAction*>(action.get());
166 if (eventAction == nullptr) {
167 return;
168 }
169
170 auto it = mEventActions.find(eventAction->GetEventId());
171 if (it == mEventActions.end()) {
172 return;
173 }
174
175 auto& bucket = it->second;
176 bucket.erase(std::remove_if(bucket.begin(), bucket.end(),
177 [&action](const std::shared_ptr<Action>& existing) {
178 return existing && action && existing->GetId() == action->GetId();
179 }),
180 bucket.end());
181
182 if (bucket.empty()) {
183 mEventActions.erase(it);
184 }
185}
186
187} // namespace Ship
int32_t EventID
Numeric identifier for an event. -1 is uninitialized, IDs < -1 are internally registered,...
Definition EventTypes.h:8
Generic ordered container of Action instances.
Definition ActionList.h:17
void Added(std::shared_ptr< Action > action, const bool forced) override
Starts the action after insertion.
Definition ActionList.h:40
ActionList specialization with indexed EventAction lookup by EventID.
Definition EventActionList.h:27
void Removed(std::shared_ptr< Action > action, const bool forced) override
Stops the action and removes it from the EventID index when applicable.
Definition EventActionList.h:131
void Added(std::shared_ptr< Action > action, const bool forced) override
Starts the action and updates the EventID index when applicable.
Definition EventActionList.h:108
Event-bus listener action executed by Events::Tick(EventID).
Definition ListenerAction.h:22
EventPriority GetPriority() const
Returns the dispatch priority used for ordering listeners.
bool Has() const
Checks whether any Part of type T is in the list.
Definition PartList.h:777
std::shared_ptr< std::vector< std::shared_ptr< Action > > > Get() const
Returns a snapshot (copy) of all currently live Parts in the list.
Definition PartList.h:825
std::enable_if< std::is_same< P, std::shared_ptr< Action > >::value, std::vector< P > & >::type GetList()
Direct access to the underlying vector for strong-storage lists.
Definition PartList.h:733
std::shared_ptr< T > GetFirst() const
Returns the first Part that can be dynamic_cast to T.
Definition PartList.h:864
Core namespace for the libultraship engine framework.
Definition gfx_direct3d_common.h:14