Euphoria
ecs.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 #include <optional>
5 #include <memory>
6 #include <string_view>
7 #include <utility> // std::forward
8 #include <typeinfo>
9 
10 #include "assert/assert.h"
11 
12 #include "core/ecs.id.h"
13 
14 namespace eu::core::ecs
15 {
16  // todo(Gustav): move detail to detail namespace
17  std::size_t c_ent(EntityHandle v);
18  std::size_t c_comp(ComponentIndex v);
19 
20  template<typename T>
21  constexpr std::string_view get_component_base_name()
22  {
23  return typeid(T).name();
24  }
25 
27  {
28  std::string_view name;
29 
30  ComponentArrayBase(std::string_view n);
31  virtual ~ComponentArrayBase() = default;
32 
37 
38 
39  virtual void remove(EntityHandle) = 0;
40  [[nodiscard]] virtual bool has(EntityHandle) const= 0;
41  };
42 
43  // contains a list of components for a single component type
44  template<typename T>
46  {
47  // todo(Gustav): implement better sparse vector
48  std::vector<std::optional<T>> components;
49 
52  {
53  }
54 
55  void
56  add(EntityHandle entity, T&& component)
57  {
58  const auto index = c_ent(entity);
59  if(components.size() < index + 1)
60  {
61  components.resize(index + 1);
62  }
63  ASSERT(components[index].has_value() == false);
64  components[index] = std::move(component);
65  }
66 
67  T&
68  get(EntityHandle entity)
69  {
70  const auto index = c_ent(entity);
71  ASSERT(components.size() >= index);
72  ASSERT(components[index].has_value());
73  return *components[index];
74  }
75 
76  T*
78  {
79  const auto index = c_ent(entity);
80  if(has_value_for_index(index))
81  {
82  return &(*components[index]);
83  }
84  else
85  {
86  return nullptr;
87  }
88  }
89 
90  // todo(Gustav): rename to has_value_for_index
91  [[nodiscard]]
92  bool
93  has_value_for_index(std::size_t index) const
94  {
95  return false ==
96  (
97  components.size() <= index ||
98  components[index].has_value() == false
99  );
100  }
101 
102 
103  void
104  remove(EntityHandle entity) override
105  {
106  const auto index = c_ent(entity);
107  if(components.size() < index + 1)
108  {
109  return;
110  }
111 
112  ASSERT(components[index].has_value());
113  components[index] = std::nullopt;
114  }
115 
116  [[nodiscard]]
117  bool
118  has(EntityHandle entity) const override
119  {
120  const auto index = c_ent(entity);
121  return has_value_for_index(index);
122  }
123  };
124 
125 
127 
128 
129  struct RegistryPimpl;
130 
131 
132  struct Registry
133  {
134  Registry();
135  ~Registry();
136 
137  Registry(const Registry&) = delete;
138  Registry(Registry&&) = delete;
139  Registry& operator=(const Registry&) = delete;
141 
143  void destroy(EntityHandle entity);
144  ComponentIndex set_component_array(const std::string& name, std::unique_ptr<ComponentArrayBase>&& components);
145 
146 
147  template<typename T>
148  ComponentIndex register_component(const std::string& name)
149  {
150  return set_component_array(name, std::make_unique<GenericComponentArray<T>>());
151  }
152 
153 
154  template<typename T>
155  void add_component(EntityHandle entity, ComponentIndex comp_ind, T&& component)
156  {
157  get_components<T>(comp_ind)->add(entity, std::forward<T>(component));
158  on_added_component(entity, comp_ind);
159  }
160 
161 
162  template<typename T>
164  {
165  on_removed_component(entity, comp_ind);
166  get_components<T>(comp_ind)->remove(entity);
167  }
168 
169 
170  template<typename T>
172  {
173  return get_components<T>(comp_ind)->get(entity);
174  }
175 
176  template<typename T>
178  {
179  return get_components<T>(comp_ind)->get_or_null(entity);
180  }
181 
182  [[nodiscard]] std::string get_component_debug_name(ComponentIndex c) const;
183  [[nodiscard]] bool has_component(EntityHandle entity, ComponentIndex comp_ind) const;
184  [[nodiscard]] std::vector<EntityHandle> view(const std::vector<ComponentIndex>& matching_components) const;
185 
186  [[nodiscard]] int get_number_of_active_entities() const;
187  private:
188  std::unique_ptr<RegistryPimpl> pimpl;
189 
190  template<typename T>
191  [[nodiscard]] GenericComponentArray<T>* get_components(ComponentIndex comp_ind)
192  {
193  ComponentArrayBase* base = get_components_base(comp_ind);
194  ASSERTX(base->name == get_component_base_name<T>(), base->name, get_component_base_name<T>(), get_component_name(comp_ind));
195  return static_cast<GenericComponentArray<T>*>(base);
196  }
197 
198  ComponentArrayBase* get_components_base(ComponentIndex comp_ind);
199  void on_added_component(EntityHandle entity, ComponentIndex comp_ind);
200  void on_removed_component(EntityHandle entity, ComponentIndex comp_ind);
201 
202  [[nodiscard]] std::string get_component_name(ComponentIndex comp_ind) const;
203  };
204 }
ParserBase * base
Definition: argparse.cc:887
#define ASSERTX(x,...)
Definition: assert.h:48
#define ASSERT(x)
Definition: assert.h:29
constexpr std::string_view get_component_base_name()
Definition: ecs.h:21
std::size_t c_ent(EntityHandle v)
Definition: ecs.cc:13
std::size_t c_comp(ComponentIndex v)
Definition: ecs.cc:12
ComponentArrayBase & operator=(ComponentArrayBase &&)=delete
std::string_view name
Definition: ecs.h:28
virtual ~ComponentArrayBase()=default
ComponentArrayBase(const ComponentArrayBase &)=delete
virtual void remove(EntityHandle)=0
ComponentArrayBase(ComponentArrayBase &&)=delete
virtual bool has(EntityHandle) const =0
ComponentArrayBase(std::string_view n)
Definition: ecs.cc:18
ComponentArrayBase & operator=(const ComponentArrayBase &)=delete
std::vector< std::optional< T > > components
Definition: ecs.h:48
void add(EntityHandle entity, T &&component)
Definition: ecs.h:56
void remove(EntityHandle entity) override
Definition: ecs.h:104
T & get(EntityHandle entity)
Definition: ecs.h:68
bool has_value_for_index(std::size_t index) const
Definition: ecs.h:93
bool has(EntityHandle entity) const override
Definition: ecs.h:118
T * get_or_null(EntityHandle entity)
Definition: ecs.h:77
bool has_component(EntityHandle entity, ComponentIndex comp_ind) const
Definition: ecs.cc:258
ComponentIndex register_component(const std::string &name)
Definition: ecs.h:148
EntityHandle create()
Definition: ecs.cc:241
ComponentIndex set_component_array(const std::string &name, std::unique_ptr< ComponentArrayBase > &&components)
Definition: ecs.cc:263
Registry & operator=(const Registry &)=delete
void add_component(EntityHandle entity, ComponentIndex comp_ind, T &&component)
Definition: ecs.h:155
void remove_component(EntityHandle entity, ComponentIndex comp_ind)
Definition: ecs.h:163
T * get_component_or_null(EntityHandle entity, ComponentIndex comp_ind)
Definition: ecs.h:177
Registry(const Registry &)=delete
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
Registry & operator=(Registry &&)=delete
Registry(Registry &&)=delete
std::string get_component_debug_name(ComponentIndex c) const
Definition: ecs.cc:247
T & get_component(EntityHandle entity, ComponentIndex comp_ind)
Definition: ecs.h:171