CORGI
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
component.h
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef CORGI_COMPONENT_H_
16 #define CORGI_COMPONENT_H_
17 
18 #include <unordered_map>
21 #include "corgi/entity.h"
22 #include "corgi/entity_common.h"
23 #include "corgi/entity_manager.h"
24 #include "corgi/vector_pool.h"
25 
26 namespace corgi {
27 
28 /// @file
29 /// @addtogroup corgi_component
30 /// @{
31 ///
32 /// @class Component
33 /// @brief A Component is an object that encapsulates all data and logic
34 /// for Entities of a particular type.
35 ///
36 /// @note On some of the API, EntityRef& parameters are non-const so that
37 /// the referenced Entity can be changed. The EntityRef itself is never
38 /// modified.
39 ///
40 /// @tparam T The structure of data that needs to be associated with each
41 /// Entity.
42 template <typename T>
43 class Component : public ComponentInterface {
44  public:
45  /// @struct ComponentData
46  /// @brief A structure of data that is associated with each Entity.
47  ///
48  /// It contains the template struct, as well as a pointer back to the
49  /// Entity that owns this data.
50  struct ComponentData {
51  /// @brief The default constructor for an empty ComponentData.
53 
54  /// @var entity
55  ///
56  /// @brief The Entity associated with this data.
58 
59  /// @var data
60  ///
61  /// @brief The data to associate with the Entity.
62  T data;
63 
64  /// @brief Construct a new ComponentData from an existing ComponentData.
65  ///
66  /// @param[in] src An existing ComponentData whose data should be moved
67  /// into the new ComponentData.
69  entity = std::move(src.entity);
70  data = std::move(src.data);
71  }
72 
73  /// @brief Move a referenced ComponentData into this ComponentData.
74  ///
75  /// Move operators are efficient since they allow referenced data to
76  /// be moved instead of copied.
77  ///
78  /// @param[in] src A referenced ComponentData to be moved into this
79  /// ComponentData.
81  entity = std::move(src.entity);
82  data = std::move(src.data);
83  return *this;
84  }
85 
86  private:
89  };
90 
91  /// @typedef EntityIterator
92  ///
93  /// @brief An iterator to iterate through all of the Entities in the
94  /// Component.
96 
97  /// @typedef value_type
98  ///
99  /// @brief The templated data type stored by this Component.
100  typedef T value_type;
101 
102  /// @brief Construct a Component without an EntityManager.
103  Component() : entity_manager_(nullptr) {}
104 
105  /// @brief Destructor for a Component.
106  virtual ~Component() {}
107 
108  /// @brief Provides an alternate way to add Entities if you do not
109  /// care about the returned data structure, and if you do not feel like
110  /// casting the BaseComponent into something more specific.
111  ///
112  /// @note AddEntity is a much better function, except we cannot have it in
113  /// the interface class, since it needs to know about type T for the return
114  /// value.
115  ///
116  /// @param[in,out] entity An EntityRef reference used to add an Entity.
117  virtual void AddEntityGenerically(EntityRef& entity) { AddEntity(entity); }
118 
119  /// @brief Adds an Entity to the list that this Component is tracking.
120  ///
121  /// @param[in,out] entity An EntityRef reference used to add an Entity to the
122  /// list of Entities that this Component keeps track of.
123  /// @param[in] alloc_location An Enum that specifies whether to allocate from
124  /// the beginning or end of the memory pool.
125  ///
126  /// @return Returns the data structure associated with the Component.
127  ///
128  /// @note If you have already registered for this Component, this
129  /// will just return a reference to the existing data and will not change
130  /// anything.
131  T* AddEntity(EntityRef& entity, AllocationLocation alloc_location) {
132  if (HasDataForEntity(entity)) {
133  return GetComponentData(entity);
134  }
135  // No existing data, so we allocate some and return it:
136  ComponentIndex index = static_cast<ComponentIndex>(
137  component_data_.GetNewElement(alloc_location).index());
138  component_index_lookup_[entity->entity_id()] = index;
139  ComponentData* component_data = component_data_.GetElementData(index);
140  component_data->entity = entity;
141  InitEntity(entity);
142  return &(component_data->data);
143  }
144 
145  /// @brief Adds an Entity to the list that this Component is tracking.
146  ///
147  /// @note Entities added through this function allocate from the back of the
148  /// memory pool.
149  ///
150  /// @param[in,out] entity An EntityRef reference used to add an Entity to the
151  /// list of Entities that this Component keeps track of.
152  ///
153  /// @return Returns the data structure associated with the Component.
154  T* AddEntity(EntityRef& entity) { return AddEntity(entity, kAddToBack); }
155 
156  /// @brief Removes an Entity from the list of Entities.
157  ///
158  /// This is done by marking the Entity as no longer using this Component,
159  /// calling the destructor on the data, and returning the memory to the
160  /// memory pool.
161  ///
162  /// @param[in,out] entity An EntityRef reference used to remove an Entity
163  /// from the list of Entities that this Component keeps track of.
164  virtual void RemoveEntity(EntityRef& entity) {
165  // Calling remove when there is no data is generally a sign that
166  // something has gone wrong and that something has lost track of which
167  // entities are associated with which components. Use HasDataForEntity()
168  // if you want to double-check if data exists before removing it.
169  assert(HasDataForEntity(entity));
170  RemoveEntityInternal(entity);
171  component_data_.FreeElement(GetComponentDataIndex(entity));
172  component_index_lookup_.erase(entity->entity_id());
173  }
174 
175  /// @brief Removes an Entity from the list of Entities.
176  ///
177  /// This is done by marking the Entity as no longer using this Component,
178  /// calling the destructor on the data, and returning the memory to the
179  /// memory pool.
180  ///
181  /// @param[in,out] iter An EntityIterator that references an Entity that
182  /// should
183  /// be removed.
184  ///
185  /// @return Returns an iterator to the next Entity after the one that was
186  /// just removed.
188  EntityRef entity = iter->entity;
189  RemoveEntityInternal(entity);
190  EntityIterator new_iter = component_data_.FreeElement(iter);
191  component_index_lookup_.erase(entity->entity_id());
192  return new_iter;
193  }
194 
195  /// @brief Gets an iterator that will iterate over every Entity associated
196  /// with the Component, starting from the beginning.
197  ///
198  /// @return Returns an iterator in the style of std that points to the first
199  /// Entity in the list of all Entities in the Component.
200  virtual EntityIterator begin() { return component_data_.begin(); }
201 
202  /// @brief Gets an iterator that points to the end of the list of all entites
203  /// in the Component.
204  ///
205  /// @return Returns an iterator in the style of std that points to the last
206  /// Entity in the list of all Entities in the Component.
207  virtual EntityIterator end() { return component_data_.end(); }
208 
209  /// @brief Updates all Entities. This is normally called, once per frame,
210  /// by the EntityManager.
211  virtual void UpdateAllEntities(WorldTime /*delta_time*/) {}
212 
213  /// @brief Checks if this component contains any data associated with the
214  /// supplied entity.
215  virtual bool HasDataForEntity(const EntityRef& entity) {
216  return GetComponentDataIndex(entity) != kInvalidComponentIndex;
217  }
218 
219  /// @brief Gets the data for a given Entity as a void pointer.
220  ///
221  /// @note When using GetComponentDataAsVoid, the calling function is expected
222  /// to know how to handle the data (since it is returned as a void pointer).
223  ///
224  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
225  /// AddEntityGenerically may force the storage class to resize,
226  /// shuffling around the location of this data.
227  ///
228  /// @param[in] entity An EntityRef reference to the Entity whose data should
229  /// be returned.
230  ///
231  /// @return Returns the Entity's data as a void pointer, or returns a nullptr
232  /// if the data does not exist.
233  virtual void* GetComponentDataAsVoid(const EntityRef& entity) {
234  return GetComponentData(entity);
235  }
236 
237  /// @brief Gets the data for a given Entity as a const void pointer.
238  ///
239  /// @note When using GetComponentDataAsVoid, the calling function is expected
240  /// to know how to handle the data (since it is returned as a const
241  /// void pointer).
242  ///
243  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
244  /// AddEntityGenerically may force the storage class to resize,
245  /// shuffling around the location of this data.
246  ///
247  /// @param[in] entity An EntityRef reference to the Entity whose data should
248  /// be returned.
249  ///
250  /// @return Returns the Entity's data as a const void pointer, or returns a
251  /// nullptr if the data does not exist.
252  virtual const void* GetComponentDataAsVoid(const EntityRef& entity) const {
253  return GetComponentData(entity);
254  }
255 
256  /// @brief Gets the Component data stored at a given index.
257  ///
258  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
259  /// AddEntityGenerically may force the storage class to resize,
260  /// shuffling around the location of this data.
261  ///
262  /// @param[in] data_index A size_t representing the index of the desired
263  /// Component data.
264  ///
265  /// @return Returns a pointer of the data structure associated with the
266  /// Component data, or returns a nullptr if given an invalid data_index.
267  T* GetComponentData(size_t data_index) {
268  if (data_index == kInvalidComponentIndex) {
269  return nullptr;
270  }
271  ComponentData* element_data = component_data_.GetElementData(data_index);
272  return (element_data != nullptr) ? &(element_data->data) : nullptr;
273  }
274 
275  /// @brief Gets the data for a given Entity.
276  ///
277  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
278  /// AddEntityGenerically may force the storage class to resize,
279  /// shuffling around the location of this data.
280  ///
281  /// @param[in] entity An EntityRef reference to the Entity whose data should
282  /// be returned.
283  ///
284  /// @return Returns the Entity's data as a pointer of the data structure
285  /// associated with the Component data, or returns a nullptr if the data
286  /// does not exist.
287  T* GetComponentData(const EntityRef& entity) {
288  size_t data_index = GetComponentDataIndex(entity);
289  if (data_index >= component_data_.Size()) {
290  return nullptr;
291  }
292  return GetComponentData(data_index);
293  }
294 
295  /// @brief Gets the Component data stored at a given index.
296  ///
297  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
298  /// AddEntityGenerically may force the storage class to resize,
299  /// shuffling around the location of this data.
300  ///
301  /// @param[in] data_index A size_t representing the index of the desired
302  /// Component data.
303  ///
304  /// @return Returns a const pointer of the data structure associated with the
305  /// Component data, or returns a nullptr if given an invalid data_index.
306  const T* GetComponentData(size_t data_index) const {
307  return const_cast<Component*>(this)->GetComponentData(data_index);
308  }
309 
310  /// @brief Gets the data for a given Entity.
311  ///
312  /// @warning This pointer is NOT stable in memory. Calls to AddEntity and
313  /// AddEntityGenerically may force the storage class to resize,
314  /// shuffling around the location of this data.
315  ///
316  /// @param[in] entity An EntityRef reference to the Entity whose data should
317  /// be returned.
318  ///
319  /// @return Returns the Entity's data as a const pointer of the data
320  /// structure associated with the Component data, or returns a nullptr
321  /// if the data does not exist.
322  const T* GetComponentData(const EntityRef& entity) const {
323  return const_cast<Component*>(this)->GetComponentData(entity);
324  }
325 
326  /// @brief Clears all tracked Component data.
327  void virtual ClearComponentData() {
328  for (auto iter = component_data_.begin(); iter != component_data_.end();
329  iter = RemoveEntity(iter)) {
330  }
331  }
332 
333  /// @brief A utility function for retrieving the Component data for an
334  /// Entity from a specific Component.
335  ///
336  /// @tparam ComponentDataType The data type of the Component whose data
337  /// is returned for the given Entity.
338  ///
339  /// @param[in] entity An EntityRef reference to the Entity whose Component
340  /// data should be returned.
341  ///
342  /// @return Returns a pointer to the data for the Component of the given
343  /// Entity or returns null if the Entity is not registered with the
344  /// Component.
345  template <typename ComponentDataType>
346  ComponentDataType* Data(const EntityRef& entity) {
347  return entity_manager_->GetComponentData<ComponentDataType>(entity);
348  }
349 
350  /// @brief A utility function for checking if an entity is registered with
351  /// a particular component.
352  ///
353  /// @tparam ComponentDataType The data type of the Component to be checked
354  /// for registration.
355  ///
356  /// @param[in] entity An EntityRef reference to the Entity whose Component
357  /// data is checked.
358  ///
359  /// @return Returns true if the entity has been registered with the Component,
360  /// false otherwise.
361  template <typename ComponentDataType>
362  bool IsRegisteredWithComponent(const EntityRef& entity) {
363  return entity_manager_
364  ->GetComponent(entity_manager_->GetComponentId<ComponentDataType>())
365  ->HasDataForEntity(entity);
366  }
367 
368  /// @brief A utility function for retrieving the Component data for an
369  /// Entity from a specific Component.
370  ///
371  /// @tparam ComponentDataType The data type of the Component whose data
372  /// is returned for the given Entity.
373  ///
374  /// @param[in] entity An EntityRef reference to the Entity whose Component
375  /// data should be returned.
376  ///
377  /// @return Returns a pointer to the data for the Component of the given
378  /// Entity or returns null if the Entity is not registered with the
379  /// Component.
380  template <typename ComponentDataType>
381  ComponentDataType* Data(const EntityRef& entity) const {
382  return entity_manager_->GetComponentData<ComponentDataType>(entity);
383  }
384 
385  /// @brief A utility function for retrieving a reference to a specific
386  /// Component object, by type.
387  ///
388  /// @tparam ComponentDataType The data type of the Component.
389  ///
390  /// @return Returns a pointer to the data for a specific Component.
391  template <typename ComponentDataType>
392  ComponentDataType* GetComponent() {
393  return static_cast<ComponentDataType*>(entity_manager_->GetComponent(
395  }
396 
397  // Virtual methods we inherited from component_interface:
398 
399  /// @brief Override this function with code that should be executed when
400  /// the Component is added to the EntityManager. (This typically
401  /// happens once, at the beginning of the game before any Entities are
402  /// added.)
403  virtual void Init() {}
404 
405  /// @brief Override this function with code that should be executed when an
406  /// Entity is added to the Component.
407  virtual void InitEntity(EntityRef& /*entity*/) {}
408 
409  /// @brief Override this function to return raw data that can be read back
410  /// later.
411  ///
412  /// @warning By default, Components do not support this functionality. If you
413  /// wish to support this, you will need to override this function.
414  ///
415  /// @return By default, this returns a nullptr.
416  virtual RawDataUniquePtr ExportRawData(const EntityRef& /*unused*/) const {
417  return nullptr;
418  }
419 
420  /// @brief Override this function with any code that executes when this
421  /// Component is removed from the EntityManager. (i.e. Usually when the
422  /// game/state is over and everything is shutting down.)
423  virtual void Cleanup() {}
424 
425  /// @brief Override this function with any code that needs to be executed
426  /// when an Entity is removed from this Component.
427  virtual void CleanupEntity(EntityRef& /*entity*/) {}
428 
429  /// @brief Set the EntityManager for this Component.
430  ///
431  /// @note The EntityManager is used as the main point of contact
432  /// for Components that need to talk to other things.
433  ///
434  /// @param[in] entity_manager A pointer to an EntityManager to associate
435  /// with this Component.
436  virtual void SetEntityManager(EntityManager* entity_manager) {
437  entity_manager_ = entity_manager;
438  }
439 
440  /// @brief Get the ID for this Component.
441  ///
442  /// @return Returns the Component ID for this Component.
444  return static_cast<ComponentId>(ComponentIdLookup<T>::component_id);
445  }
446 
447  /// @brief Sets the Component ID on the data type.
448  ///
449  /// @note This is usually only called by the EntityManager.
450  ///
451  /// @param[in] id The Component ID to set on the data type.
454  }
455 
456  private:
457  /// @brief Allows Components to handle any per-Entity clean up that may
458  /// be needed.
459  ///
460  /// @param[in] entity An EntityRef reference to the Entity that is being
461  /// removed and may need to be cleaned up.
462  void RemoveEntityInternal(EntityRef& entity) { CleanupEntity(entity); }
463 
464  protected:
465  /// @brief Get the index of the Component data for a given Entity.
466  ///
467  /// @param[in] entity An EntityRef reference to the Entity whose data
468  /// index will be returned.
469  ///
470  /// @return Returns a size_t corresponding to the index of the
471  /// Component data, or kInvalidComponentIndex if no data could be found.
472  size_t GetComponentDataIndex(const EntityRef& entity) const {
473  auto result = component_index_lookup_.find(entity->entity_id());
474  return (result != component_index_lookup_.end()) ? result->second
475  : kInvalidComponentIndex;
476  }
477 
478  /// @var component_data_
479  ///
480  /// @brief Storage for all of the data for the Component.
482 
483  /// @var entity_manager_
484  ///
485  /// @brief A pointer to the EntityManager for this Component. This is the
486  /// main point of contact for Components that need to talk to other things.
488 
489  /// @var component_index_lookup_
490  ///
491  /// @brief A map, for translating unique entity IDs into vectorpool
492  /// indexes.
493  std::unordered_map<EntityIdType, ComponentIndex> component_index_lookup_;
494 };
495 /// @}
496 
497 } // corgi
498 
499 #endif // CORGI_COMPONENT_H_
std::unique_ptr< uint8_t, std::function< void(uint8_t *)> > RawDataUniquePtr
A pointer type for exported raw data.
Definition: component_interface.h:63
std::unordered_map< EntityIdType, ComponentIndex > component_index_lookup_
A map, for translating unique entity IDs into vectorpool indexes.
Definition: component.h:493
A Component is an object that encapsulates all data and logic for Entities of a particular type...
Definition: component.h:43
virtual void SetComponentIdOnDataType(ComponentId id)
Sets the Component ID on the data type.
Definition: component.h:452
ComponentDataType * Data(const EntityRef &entity)
A utility function for retrieving the Component data for an Entity from a specific Component...
Definition: component.h:346
T * GetComponent()
A helper function for getting a particular Component, given the Component's data type.
Definition: entity_manager.h:111
ComponentDataType * GetComponent()
A utility function for retrieving a reference to a specific Component object, by type.
Definition: component.h:392
Component()
Construct a Component without an EntityManager.
Definition: component.h:103
virtual EntityIterator end()
Gets an iterator that points to the end of the list of all entites in the Component.
Definition: component.h:207
A templated struct for holding type-dependent data.
Definition: component_id_lookup.h:36
virtual void SetEntityManager(EntityManager *entity_manager)
Set the EntityManager for this Component.
Definition: component.h:436
ComponentData(ComponentData &&src)
Construct a new ComponentData from an existing ComponentData.
Definition: component.h:68
T * AddEntity(EntityRef &entity)
Adds an Entity to the list that this Component is tracking.
Definition: component.h:154
virtual void Cleanup()
Override this function with any code that executes when this Component is removed from the EntityMana...
Definition: component.h:423
virtual void ClearComponentData()
Clears all tracked Component data.
Definition: component.h:327
The EntityManager is the code that manages all Entities and Components in the game. Normally the game will instantiate EntityManager, and then use it to create and control all of its Entities.
Definition: entity_manager.h:61
int WorldTime
A typedef that represents time in the game.
Definition: entity_common.h:49
T * GetComponentData(const EntityRef &entity)
Helper function for marshalling data from a Component.
Definition: entity_manager.h:83
virtual void InitEntity(EntityRef &)
Override this function with code that should be executed when an Entity is added to the Component...
Definition: component.h:407
ComponentDataType * Data(const EntityRef &entity) const
A utility function for retrieving the Component data for an Entity from a specific Component...
Definition: component.h:381
virtual RawDataUniquePtr ExportRawData(const EntityRef &) const
Override this function to return raw data that can be read back later.
Definition: component.h:416
T data
The data to associate with the Entity.
Definition: component.h:62
virtual void UpdateAllEntities(WorldTime)
Updates all Entities. This is normally called, once per frame, by the EntityManager.
Definition: component.h:211
virtual const void * GetComponentDataAsVoid(const EntityRef &entity) const
Gets the data for a given Entity as a const void pointer.
Definition: component.h:252
T * GetComponentData(const EntityRef &entity)
Gets the data for a given Entity.
Definition: component.h:287
AllocationLocation
kAddToFront allocates from the front of the pool. kAddToBack allocates from the back of the pool...
Definition: vector_pool.h:34
virtual void CleanupEntity(EntityRef &)
Override this function with any code that needs to be executed when an Entity is removed from this Co...
Definition: component.h:427
A pool allocator, implemented as a vector-based pair of linked lists.
Definition: vector_pool.h:43
virtual EntityIterator begin()
Gets an iterator that will iterate over every Entity associated with the Component, starting from the beginning.
Definition: component.h:200
ComponentId GetComponentId()
A helper function to get the component ID for a given Component.
Definition: entity_manager.h:196
virtual void Init()
Override this function with code that should be executed when the Component is added to the EntityMan...
Definition: component.h:403
A reference object for pointing into the vector pool. It acts as a pointer for vector pool elements a...
Definition: vector_pool.h:72
virtual ~Component()
Destructor for a Component.
Definition: component.h:106
T * AddEntity(EntityRef &entity, AllocationLocation alloc_location)
Adds an Entity to the list that this Component is tracking.
Definition: component.h:131
static ComponentId GetComponentId()
Get the ID for this Component.
Definition: component.h:443
EntityManager * entity_manager_
A pointer to the EntityManager for this Component. This is the main point of contact for Components t...
Definition: component.h:487
virtual void RemoveEntity(EntityRef &entity)
Removes an Entity from the list of Entities.
Definition: component.h:164
virtual EntityIterator RemoveEntity(EntityIterator iter)
Removes an Entity from the list of Entities.
Definition: component.h:187
T value_type
The templated data type stored by this Component.
Definition: component.h:100
VectorPool< ComponentData >::Iterator EntityIterator
An iterator to iterate through all of the Entities in the Component.
Definition: component.h:95
uint16_t ComponentIndex
A ComponentIndex is a value used to represent the location of a piece of ComponentData, normally inside of a VectorPool.
Definition: entity_common.h:59
virtual void AddEntityGenerically(EntityRef &entity)
Provides an alternate way to add Entities if you do not care about the returned data structure...
Definition: component.h:117
A structure of data that is associated with each Entity.
Definition: component.h:50
size_t GetComponentDataIndex(const EntityRef &entity) const
Get the index of the Component data for a given Entity.
Definition: component.h:472
ComponentData & operator=(ComponentData &&src)
Move a referenced ComponentData into this ComponentData.
Definition: component.h:80
const T * GetComponentData(const EntityRef &entity) const
Gets the data for a given Entity.
Definition: component.h:322
const T * GetComponentData(size_t data_index) const
Gets the Component data stored at a given index.
Definition: component.h:306
VectorPool< ComponentData > component_data_
Storage for all of the data for the Component.
Definition: component.h:481
An Iterator for the VectorPool.
Definition: vector_pool.h:51
bool IsRegisteredWithComponent(const EntityRef &entity)
A utility function for checking if an entity is registered with a particular component.
Definition: component.h:362
virtual void * GetComponentDataAsVoid(const EntityRef &entity)
Gets the data for a given Entity as a void pointer.
Definition: component.h:233
T * GetComponentData(size_t data_index)
Gets the Component data stored at a given index.
Definition: component.h:267
uint16_t ComponentId
This represents the ID of a Component.
Definition: entity_common.h:36
An interface that provides basic Component functionality. All Components will inherit from this class...
Definition: component_interface.h:57
ComponentData()
The default constructor for an empty ComponentData.
Definition: component.h:52
virtual bool HasDataForEntity(const EntityRef &entity)
Checks if this component contains any data associated with the supplied entity.
Definition: component.h:215
EntityRef entity
The Entity associated with this data.
Definition: component.h:57