Euphoria
ecs.cc
Go to the documentation of this file.
1 #include "core/ecs.h"
2 
3 
4 #include <unordered_map>
5 #include <algorithm>
6 
7 #include "base/cint.h"
8 
9 
10 namespace eu::core::ecs
11 {
12  std::size_t c_comp(ComponentIndex v) { return static_cast<std::size_t>(v); }
13  std::size_t c_ent(EntityHandle v) { return static_cast<std::size_t>(v); }
14  EntityHandle c_ent(std::size_t v) { return static_cast<EntityHandle>(v); }
15  ComponentIndex c_comp(std::size_t v) { return static_cast<ComponentIndex>(v); }
16 
17 
19  : name(n)
20  {
21  }
22 
23 
24  // what components a entity has
25  struct Signature
26  {
27  std::vector<bool> components;
28 
29  void set_component(ComponentIndex c, bool has)
30  {
31  components.resize(c+1, false);
32  components[c] = has;
33  }
34 
35  void destroy()
36  {
37  components.clear();
38  }
39 
40  [[nodiscard]] bool has_component(ComponentIndex c) const
41  {
42  if (c < components.size()) { return components[c]; }
43  else { return false; }
44  }
45  };
46 
47  // pool of "alive" entities
49  {
50  std::vector<Signature> signatures;
51  std::vector<EntityHandle> free_handles;
52 
54  {
55  if(free_handles.empty())
56  {
57  const auto r = signatures.size();
58  signatures.emplace_back();
59  return c_ent(r);
60  }
61  else
62  {
63  const auto r = free_handles.back();
64  free_handles.pop_back();
65  return r;
66  }
67  }
68 
70  {
71  signatures[h].destroy();
72  free_handles.emplace_back(h);
73  }
74 
75  void set_component(EntityHandle handle, ComponentIndex component, bool has)
76  {
77  ASSERT(handle < signatures.size());
78  signatures[handle].set_component(component, has);
79  }
80 
81  [[nodiscard]] std::vector<EntityHandle> view(const std::vector<ComponentIndex>& matching_components) const
82  {
83  ASSERT(matching_components.empty() == false);
84 
85  std::vector<EntityHandle> r;
86  for(int signature_index=0; signature_index<c_sizet_to_int(signatures.size()); signature_index += 1)
87  {
88  if(has_components(c_ent(signature_index), matching_components))
89  {
90  r.emplace_back(c_ent(signature_index));
91  }
92  }
93  return r;
94  }
95 
96  [[nodiscard]] bool has_components(EntityHandle handle, const std::vector<ComponentIndex>& components) const
97  {
98  ASSERT(components.empty() == false);
99 
100  const auto& sig = signatures[handle];
101  return std::all_of
102  (
103  components.begin(), components.end(),
104  [&](ComponentIndex comp) -> bool
105  {
106  return sig.has_component(comp);
107  }
108  );
109  }
110 
111  [[nodiscard]] int
112  get_count() const
113  {
114  const auto sign_count = c_sizet_to_int(signatures.size());
115  const auto free_count = c_sizet_to_int(free_handles.size());
116  ASSERT(sign_count >= free_count);
117  return sign_count - free_count;
118  }
119  };
120 
121  // map (internal) name -> index && index -> (debug) name
123  {
124  std::unordered_map<std::string, ComponentIndex> name_to_index;
125  std::vector<std::string> index_to_name;
126 
127  ComponentIndex add(const std::string& name)
128  {
129  const auto component = c_comp(index_to_name.size());
130 
131  name_to_index.insert({name, component});
132  index_to_name.emplace_back(name);
133 
134  return component;
135  }
136 
137  ComponentIndex get_index(const std::string& name)
138  {
139  const auto found = name_to_index.find(name);
140  ASSERT(found != name_to_index.end());
141  return found->second;
142  }
143 
144  std::string get_name(ComponentIndex c)
145  {
146  return index_to_name[c];
147  }
148  };
149 
150  // contains all the components for all entities
152  {
153  std::vector<std::unique_ptr<ComponentArrayBase>> component_arrays;
154 
155  void set_component_array(ComponentIndex comp_ind, std::unique_ptr<ComponentArrayBase>&& components)
156  {
157  if(component_arrays.size() <= comp_ind)
158  {
159  component_arrays.resize(comp_ind + 1);
160  }
161  component_arrays[comp_ind] = std::move(components);
162  }
163 
165  {
166  for (auto const& comp : component_arrays)
167  {
168  comp->remove(entity);
169  }
170  }
171 
173  {
174  ASSERT(comp_ind < component_arrays.size() && "Component not registered before use.");
175  ComponentArrayBase* r = component_arrays[comp_ind].get();
176  ASSERT(r);
177  return r;
178  }
179 
180  [[nodiscard]] const ComponentArrayBase* get_components_base(ComponentIndex comp_ind) const
181  {
182  ASSERT(comp_ind < component_arrays.size() && "Component not registered before use.");
183  ComponentArrayBase* r = component_arrays[comp_ind].get();
184  ASSERT(r);
185  return r;
186  }
187  };
188 
190  {
194 
196  {
197  return alive_entities.create();
198  }
199 
200  void destroy(EntityHandle entity)
201  {
203  alive_entities.destroy(entity);
204  }
205 
206  ComponentIndex set_component_array(const std::string& name, std::unique_ptr<ComponentArrayBase>&& components)
207  {
208  const auto comp_ind = known_component_types.add(name);
209  all_components.set_component_array(comp_ind, std::move(components));
210  return comp_ind;
211  }
212 
214  {
215  return all_components.get_components_base(comp_ind);
216  }
217 
218  std::vector<EntityHandle> view(const std::vector<ComponentIndex>& matching_components) const
219  {
220  return alive_entities.view(matching_components);
221  }
222  };
223 
224 
226  : pimpl(std::make_unique<RegistryPimpl>())
227  {
228  }
229 
231  {
232  pimpl.reset();
233  }
234 
235  int
237  {
238  return pimpl->alive_entities.get_count();
239  }
240 
242  {
243  return pimpl->create();
244  }
245 
246  [[nodiscard]] std::string
248  {
249  return pimpl->known_component_types.get_name(c);
250  }
251 
253  {
254  pimpl->destroy(entity);
255  }
256 
257  [[nodiscard]] bool
259  {
260  return pimpl->all_components.get_components_base(comp_ind)->has(entity);
261  }
262 
263  ComponentIndex Registry::set_component_array(const std::string& name, std::unique_ptr<ComponentArrayBase>&& components)
264  {
265  return pimpl->set_component_array(name, std::move(components));
266  }
267 
268  std::string
269  Registry::get_component_name(ComponentIndex comp_ind) const
270  {
271  return pimpl->known_component_types.get_name(comp_ind);
272  }
273 
274  ComponentArrayBase* Registry::get_components_base(ComponentIndex comp_ind)
275  {
276  return pimpl->get_components_base(comp_ind);
277  }
278 
279  std::vector<EntityHandle> Registry::view(const std::vector<ComponentIndex>& matching_components) const
280  {
281  return pimpl->view(matching_components);
282  }
283 
284  void
285  Registry::on_added_component(EntityHandle entity, ComponentIndex comp_ind)
286  {
287  pimpl->alive_entities.set_component(entity, comp_ind, true);
288  }
289 
290  void
291  Registry::on_removed_component(EntityHandle entity, ComponentIndex comp_ind)
292  {
293  pimpl->alive_entities.set_component(entity, comp_ind, false);
294  }
295 }
#define ASSERT(x)
Definition: assert.h:29
std::size_t c_ent(EntityHandle v)
Definition: ecs.cc:13
std::size_t c_comp(ComponentIndex v)
Definition: ecs.cc:12
int c_sizet_to_int(size_t t)
Definition: cint.cc:11
void set_component(EntityHandle handle, ComponentIndex component, bool has)
Definition: ecs.cc:75
EntityHandle create()
Definition: ecs.cc:53
std::vector< EntityHandle > view(const std::vector< ComponentIndex > &matching_components) const
Definition: ecs.cc:81
std::vector< EntityHandle > free_handles
Definition: ecs.cc:51
bool has_components(EntityHandle handle, const std::vector< ComponentIndex > &components) const
Definition: ecs.cc:96
int get_count() const
Definition: ecs.cc:112
std::vector< Signature > signatures
Definition: ecs.cc:50
void destroy(EntityHandle h)
Definition: ecs.cc:69
ComponentArrayBase * get_components_base(ComponentIndex comp_ind)
Definition: ecs.cc:172
std::vector< std::unique_ptr< ComponentArrayBase > > component_arrays
Definition: ecs.cc:153
void set_component_array(ComponentIndex comp_ind, std::unique_ptr< ComponentArrayBase > &&components)
Definition: ecs.cc:155
const ComponentArrayBase * get_components_base(ComponentIndex comp_ind) const
Definition: ecs.cc:180
void destroy_entity(EntityHandle entity)
Definition: ecs.cc:164
ComponentArrayBase(std::string_view n)
Definition: ecs.cc:18
std::string get_name(ComponentIndex c)
Definition: ecs.cc:144
ComponentIndex get_index(const std::string &name)
Definition: ecs.cc:137
std::vector< std::string > index_to_name
Definition: ecs.cc:125
std::unordered_map< std::string, ComponentIndex > name_to_index
Definition: ecs.cc:124
ComponentIndex add(const std::string &name)
Definition: ecs.cc:127
EntityHandle create()
Definition: ecs.cc:195
AllComponents all_components
Definition: ecs.cc:193
AliveEntities alive_entities
Definition: ecs.cc:191
ComponentIndex set_component_array(const std::string &name, std::unique_ptr< ComponentArrayBase > &&components)
Definition: ecs.cc:206
std::vector< EntityHandle > view(const std::vector< ComponentIndex > &matching_components) const
Definition: ecs.cc:218
KnownComponentTypes known_component_types
Definition: ecs.cc:192
void destroy(EntityHandle entity)
Definition: ecs.cc:200
ComponentArrayBase * get_components_base(ComponentIndex comp_ind)
Definition: ecs.cc:213
bool has_component(EntityHandle entity, ComponentIndex comp_ind) const
Definition: ecs.cc:258
EntityHandle create()
Definition: ecs.cc:241
ComponentIndex set_component_array(const std::string &name, std::unique_ptr< ComponentArrayBase > &&components)
Definition: ecs.cc:263
int get_number_of_active_entities() const
Definition: ecs.cc:236
std::vector< EntityHandle > view(const std::vector< ComponentIndex > &matching_components) const
Definition: ecs.cc:279
void destroy(EntityHandle entity)
Definition: ecs.cc:252
std::string get_component_debug_name(ComponentIndex c) const
Definition: ecs.cc:247
void set_component(ComponentIndex c, bool has)
Definition: ecs.cc:29
bool has_component(ComponentIndex c) const
Definition: ecs.cc:40
std::vector< bool > components
Definition: ecs.cc:27