blob: 6d32edbdcbf09e674838b297081677cd1fc64d98 (
plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#pragma once
#include <type_traits>
#include "ComponentManager.h"
#include "types.h"
namespace crepe {
template <class T, typename... Args>
T & ComponentManager::add_component(game_object_id_t id, Args &&... args) {
using namespace std;
static_assert(
is_base_of<Component, T>::value,
"add_component must recieve a derivative class of Component"
);
// Determine the type of T (this is used as the key of the unordered_map<>)
type_index type = typeid(T);
// Check if this component type is already in the unordered_map<>
if (this->components.find(type) == this->components.end()) {
//If not, create a new (empty) vector<> of vector<unique_ptr<Component>>
this->components[type] = vector<vector<unique_ptr<Component>>>();
}
// Resize the vector<> if the id is greater than the current size
if (id >= this->components[type].size()) {
// Initialize new slots to nullptr (resize does automatically init to nullptr)
this->components[type].resize(id + 1);
}
// Create a new component of type T (arguments directly forwarded). The
// constructor must be called by ComponentManager.
T * instance_ptr = new T(id, forward<Args>(args)...);
if (instance_ptr == nullptr) throw std::bad_alloc();
T & instance_ref = *instance_ptr;
unique_ptr<T> instance = unique_ptr<T>(instance_ptr);
// Check if the vector size is not greater than get_instances_max
int max_instances = instance->get_instances_max();
if (max_instances != -1 && components[type][id].size() >= max_instances) {
throw std::runtime_error("Exceeded maximum number of instances for this component type"
);
}
// store its unique_ptr in the vector<>
this->components[type][id].push_back(std::move(instance));
return instance_ref;
}
template <typename T>
void ComponentManager::delete_components_by_id(game_object_id_t id) {
using namespace std;
// Do not delete persistent objects
if (this->persistent[id]) {
return;
}
// Determine the type of T (this is used as the key of the unordered_map<>)
type_index type = typeid(T);
// Find the type (in the unordered_map<>)
if (this->components.find(type) != this->components.end()) {
// Get the correct vector<>
vector<vector<unique_ptr<Component>>> & component_array = this->components[type];
// Make sure that the id (that we are looking for) is within the boundaries of the vector<>
if (id < component_array.size()) {
// Clear the whole vector<> of this specific type and id
component_array[id].clear();
}
}
}
template <typename T>
void ComponentManager::delete_components() {
// Determine the type of T (this is used as the key of the unordered_map<>)
std::type_index type = typeid(T);
if (this->components.find(type) == this->components.end()) return;
// Loop through the whole vector<> of this specific type
for (game_object_id_t i = 0; i < this->components[type].size(); ++i) {
// Do not delete persistent objects
if (!this->persistent[i]) {
this->components[type][i].clear();
}
}
}
template <typename T>
RefVector<T> ComponentManager::get_components_by_id(game_object_id_t id) const {
using namespace std;
static_assert(
is_base_of<Component, T>::value,
"get_components_by_id must recieve a derivative class of Component"
);
type_index type = typeid(T);
if (!this->components.contains(type)) return {};
const by_id_index<vector<unique_ptr<Component>>> & components_by_id
= this->components.at(type);
if (id >= components_by_id.size()) return {};
RefVector<T> out = {};
const vector<unique_ptr<Component>> & components = components_by_id.at(id);
for (auto & component_ptr : components) {
if (component_ptr == nullptr) continue;
Component & component = *component_ptr.get();
out.push_back(static_cast<T &>(component));
}
return out;
}
template <typename T>
RefVector<T> ComponentManager::get_components_by_type() const {
using namespace std;
// Determine the type of T (this is used as the key of the unordered_map<>)
type_index type = typeid(T);
// Create an empty vector<>
RefVector<T> component_vector;
// Find the type (in the unordered_map<>)
if (this->components.find(type) == this->components.end()) return component_vector;
// Get the correct vector<>
const vector<vector<unique_ptr<Component>>> & component_array = this->components.at(type);
// Loop through the whole vector<>
for (const vector<unique_ptr<Component>> & component : component_array) {
// Loop trough the whole vector<>
for (const unique_ptr<Component> & component_ptr : component) {
// Cast the unique_ptr to a raw pointer
T * casted_component = static_cast<T *>(component_ptr.get());
// Ensure that the cast was successful
if (casted_component == nullptr) continue;
// Add the dereferenced raw pointer to the vector<>
component_vector.emplace_back(ref(*casted_component));
}
}
// Return the vector<>
return component_vector;
}
template <typename T>
std::set<game_object_id_t>
ComponentManager::get_objects_by_predicate(const std::function<bool(const T &)> & pred) const {
using namespace std;
set<game_object_id_t> objects = {};
RefVector<T> components = this->get_components_by_type<T>();
for (const T & component : components) {
game_object_id_t id = dynamic_cast<const Component &>(component).game_object_id;
if (objects.contains(id)) continue;
if (!pred(component)) continue;
objects.insert(id);
}
return objects;
}
template <typename T>
RefVector<T> ComponentManager::get_components_by_ids(const std::set<game_object_id_t> & ids
) const {
using namespace std;
RefVector<T> out = {};
for (game_object_id_t id : ids) {
RefVector<T> components = get_components_by_id<T>(id);
out.insert(out.end(), components.begin(), components.end());
}
return out;
}
template <typename T>
RefVector<T> ComponentManager::get_components_by_name(const std::string & name) const {
return this->get_components_by_ids<T>(this->get_objects_by_name(name));
}
template <typename T>
RefVector<T> ComponentManager::get_components_by_tag(const std::string & tag) const {
return this->get_components_by_ids<T>(this->get_objects_by_tag(tag));
}
} // namespace crepe
|