Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
SystemManager.cpp
Go to the documentation of this file.
1
2/*
3 Author : Tobias Stein
4 Date : 13th July, 2016
5 File : SystemManager.cpp
6
7 Manager class for systems
8
9 All Rights Reserved. (c) Copyright 2016.
10*/
11
12#include "SystemManager.h"
13#include "ISystem.h"
14
15namespace ECS
16{
18 {
19 DEFINE_LOGGER("SystemManager");
20
21 LOG_INFO("Initialize SystemManager!","");
22
23 // acquire global memory
25 }
26
28 {
29 for (SystemWorkOrder::reverse_iterator it = this->m_SystemWorkOrder.rbegin(); it != this->m_SystemWorkOrder.rend(); ++it)
30 {
31 (*it)->~ISystem();
32 *it = nullptr;
33 }
34
35 m_SystemWorkOrder.clear();
36 m_Systems.clear();
37
38 // free allocated global memory
40 delete this->m_SystemAllocator;
41 this->m_SystemAllocator = nullptr;
42
43 LOG_INFO("Release SystemManager!","");
44 }
45
47 {
49
50 for (ISystem* system : this->m_SystemWorkOrder)
51 {
52 // increase interval since last update
53 system->m_TimeSinceLastUpdate += dt_ms;
54
55 // check systems update state
56 system->m_NeedsUpdate = (system->m_UpdateInterval < 0.0f) || ((system->m_UpdateInterval > 0.0f) && (system->m_TimeSinceLastUpdate > system->m_UpdateInterval));
57
58 if (system->m_Enabled == true && system->m_NeedsUpdate == true)
59 {
60 system->PreUpdate(dt_ms);
61 }
62 }
63 }
64
66 {
68
69 for (ISystem* system : this->m_SystemWorkOrder)
70 {
71 if (system->m_Enabled == true && system->m_NeedsUpdate == true)
72 {
73 system->Update(dt_ms);
74
75 // reset interval
76 system->m_TimeSinceLastUpdate = 0.0f;
77 }
78 }
79 }
80
82 {
84
85 for (ISystem* system : this->m_SystemWorkOrder)
86 {
87 if (system->m_Enabled == true && system->m_NeedsUpdate == true)
88 {
89 system->PostUpdate(dt_ms);
90 }
91 }
92 }
94 {
96
97 for (ISystem* system : this->m_SystemWorkOrder) {
98 if (system->m_Enabled == true) {
99 system->OnFrameStart();
100 }
101 }
102 }
103
105 {
107
108 for (ISystem* system : this->m_SystemWorkOrder) {
109 if (system->m_Enabled == true) {
110 system->OnFrameEnd();
111 }
112 }
113 }
114
116 {
117 // depth-first-search function
118 static const std::function<void(SystemTypeId, eastl::vector<int>&, const eastl::vector<eastl::vector<bool>>&, eastl::vector<SystemTypeId>&)> DFS = [&](SystemTypeId vertex, eastl::vector<int>& VERTEX_STATE, const eastl::vector<eastl::vector<bool>>& EDGES, eastl::vector<SystemTypeId>& output)
119 {
120 VERTEX_STATE[vertex] = 1; // visited
121
122 for (size_t i = 0; i < VERTEX_STATE.size(); ++i)
123 {
124 if (EDGES[i][vertex] == true && VERTEX_STATE[i] == 0)
125 DFS(i, VERTEX_STATE, EDGES, output);
126 }
127
128 VERTEX_STATE[vertex] = 2; // done
129 output.push_back(vertex);
130 };
131
132 const int NUM_SYSTEMS = static_cast<int>(this->m_SystemDependencyMatrix.size());
133
134
135 // create index array
136 eastl::vector<int> INDICES(NUM_SYSTEMS);
137 for (int i = 0; i < NUM_SYSTEMS; ++i)
138 INDICES[i] = i;
139
140 // determine vertex-groups
141 eastl::vector<eastl::vector<SystemTypeId>> VERTEX_GROUPS;
142 eastl::vector<SystemPriority> GROUP_PRIORITY;
143
144 while (INDICES.empty() == false)
145 {
146 int idx = INDICES.back();
147 INDICES.pop_back();
148
149 if (idx == -1)
150 continue;
151
152 SystemTypeId index = static_cast<SystemTypeId>(idx);
153
154 eastl::vector<SystemTypeId> group;
155 eastl::vector<SystemTypeId> member;
156
158 member.push_back(index);
159
160 while (member.empty() == false)
161 {
162 index = member.back();
163 member.pop_back();
164
165 for (size_t i = 0; i < INDICES.size(); ++i)
166 {
167 if (INDICES[i] != -1 && (this->m_SystemDependencyMatrix[i][index] == true || this->m_SystemDependencyMatrix[index][i] == true))
168 {
169 member.push_back(i);
170 INDICES[i] = -1;
171 }
172 }
173
174 group.push_back(index);
175
176
177 ISystem* sys = this->m_Systems[index];
178 groupPriority = std::max((sys != nullptr ? sys->m_Priority : NORMAL_SYSTEM_PRIORITY), groupPriority);
179 }
180
181 VERTEX_GROUPS.push_back(group);
182 GROUP_PRIORITY.push_back(groupPriority);
183 }
184
185 const size_t NUM_VERTEX_GROUPS = VERTEX_GROUPS.size();
186
187 // do a topological sort on groups w.r.t. to groups priority!
188 eastl::vector<int> vertex_states(NUM_SYSTEMS, 0);
189
190 eastl::multimap<SystemPriority, eastl::vector<SystemTypeId>> VERTEX_GROUPS_SORTED;
191
192
193 for (size_t i = 0; i < NUM_VERTEX_GROUPS; ++i)
194 {
195 auto g = VERTEX_GROUPS[i];
196
197 eastl::vector<SystemTypeId> order;
198
199 for (size_t j = 0; j < g.size(); ++j)
200 {
201 if (vertex_states[g[j]] == 0)
202 DFS(g[j], vertex_states, this->m_SystemDependencyMatrix, order);
203 }
204
205 eastl::reverse(order.begin(), order.end());
206
207 // note: MAX - PRIORITY will frce the correct sorting behaviour in multimap (by default a multimap sorts int values from low to high)
208 VERTEX_GROUPS_SORTED.insert(eastl::pair<SystemPriority, eastl::vector<SystemTypeId>>(static_cast<SystemPriority>(std::numeric_limits<SystemPriority>::max() - GROUP_PRIORITY[i]), order));
209 }
210
211
212
213 LOG_INFO("Update system work order:", "");
214
215 // re-build system work order
216 this->m_SystemWorkOrder.clear();
217 for (auto group : VERTEX_GROUPS_SORTED)
218 {
219 for (auto m : group.second)
220 {
221 ISystem* sys = this->m_Systems[m];
222 if (sys != nullptr)
223 {
224 this->m_SystemWorkOrder.push_back(sys);
225 LOG_INFO("\t{}", sys->GetSystemTypeName());
226 }
227 }
228 }
229 }
230
232 {
233 SystemWorkStateMask mask(this->m_SystemWorkOrder.size());
234
235 for (size_t i = 0; i < this->m_SystemWorkOrder.size(); ++i)
236 {
237 mask[i] = this->m_SystemWorkOrder[i]->m_Enabled;
238 }
239
240 return mask;
241 }
242
244 {
245 assert(mask.size() == this->m_SystemWorkOrder.size() && "Provided mask does not match size of current system array.");
246
247 for (size_t i = 0; i < this->m_SystemWorkOrder.size(); ++i)
248 {
249 this->m_SystemWorkOrder[i]->m_Enabled = mask[i];
250 }
251 }
252
253} // namespace ECS
#define ECS_SYSTEM_MEMORY_BUFFER_SIZE
Definition: API.h:32
#define DEFINE_LOGGER(name)
Definition: LoggerMacro.h:18
#define LOG_INFO(format,...)
Definition: LoggerMacro.h:25
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
SystemPriority m_Priority
Definition: ISystem.h:60
virtual const char * GetSystemTypeName() const =0
const void * GetMemoryAddress0() const
Definition: IAllocator.h:80
void Free(void *pMem)
Definition: API.cpp:55
const void * Allocate(size_t memSize, const char *user=nullptr)
Definition: API.cpp:50
SystemDependencyMatrix m_SystemDependencyMatrix
Definition: SystemManager.h:49
SystemAllocator * m_SystemAllocator
Definition: SystemManager.h:45
SystemWorkStateMask GetSystemWorkState() const
Memory::Allocator::LinearAllocator SystemAllocator
Definition: SystemManager.h:41
void Update(f32 dt_ms)
SystemRegistry m_Systems
Definition: SystemManager.h:47
void SetSystemWorkState(SystemWorkStateMask mask)
~SystemManager() override
void PostUpdate(f32 dt_ms)
SystemWorkOrder m_SystemWorkOrder
Definition: SystemManager.h:51
void PreUpdate(f32 dt_ms)
constexpr Optick::Category::Type GameLogic
Definition: Profiler.h:63
float_t f32
Definition: Platform.h:59
static const SystemPriority LOWEST_SYSTEM_PRIORITY
Definition: ISystem.h:31
eastl::vector< bool > SystemWorkStateMask
Definition: SystemManager.h:27
static const SystemPriority NORMAL_SYSTEM_PRIORITY
Definition: ISystem.h:36
TypeID SystemTypeId
Definition: ISystem.h:22
u16 SystemPriority
Definition: ISystem.h:24