💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
6.7 KiB

  1. /*
  2. * Copyright (C) 2017-2019 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ENTITY_GROUP_HPP
  20. #define ENTITY_GROUP_HPP
  21. #include "component-observer.hpp"
  22. #include "component-manager.hpp"
  23. #include "entity-group-member.hpp"
  24. #include "entity-group-observer.hpp"
  25. #include <list>
  26. #include <map>
  27. #include <set>
  28. #include <tuple>
  29. #include <utility>
  30. enum class ComponentType;
  31. /// A set of component types used to filter entities
  32. typedef std::set<ComponentType> ComponentFilter;
  33. /**
  34. * Abstract base class for entity groups.
  35. */
  36. class EntityGroupBase: protected ComponentObserver
  37. {
  38. public:
  39. /**
  40. * Creates a entity group base.
  41. *
  42. * @param componentManager The component manager with which to associate this entity group.
  43. * @param componentFilter Set of component types which an entity must possess in order to join this entity group.
  44. */
  45. EntityGroupBase(ComponentManager* componentManager, const ComponentFilter& componentFilter);
  46. /// Returns the set of components which an entity must possess in order to join this entity group.
  47. const ComponentFilter& getComponentFilter() const;
  48. /**
  49. * Returns true if the specified entity is registered with this entity group.
  50. *
  51. * @param entity ID of the entity to check.
  52. */
  53. virtual bool isRegistered(EntityID entity) const = 0;
  54. private:
  55. virtual void componentAdded(EntityID entity, ComponentBase* component);
  56. virtual void componentRemoved(EntityID entity, ComponentBase* component);
  57. /**
  58. * Called each time an entity joins the entity group by obtaining the necessary component types.
  59. *
  60. * @param entity Entity ID of the new member.
  61. */
  62. virtual void registerMember(EntityID entity) = 0;
  63. /**
  64. * Called each time an entity leaves an the entity group by no longer possessing the necessary component types.
  65. *
  66. * @param entity Entity ID of the former member.
  67. */
  68. virtual void unregisterMember(EntityID entity) = 0;
  69. ComponentFilter componentFilter;
  70. };
  71. inline const ComponentFilter& EntityGroupBase::getComponentFilter() const
  72. {
  73. return componentFilter;
  74. }
  75. /**
  76. * A group of entities which share a set of specified component types.
  77. *
  78. * @tparam T Set of components which are required for group membership.
  79. */
  80. template <typename... T>
  81. class EntityGroup: public EntityGroupBase
  82. {
  83. public:
  84. typedef EntityGroupMember<T...> Member;
  85. typedef EntityGroupObserver<T...> Observer;
  86. /**
  87. * Creates a entity group.
  88. *
  89. * @param componentManager Component manager with which to associate this entity group.
  90. */
  91. EntityGroup(ComponentManager* componentManager);
  92. /// Destroys a entity group.
  93. ~EntityGroup();
  94. /**
  95. * Adds a group observer.
  96. *
  97. * @param observer Observer to add.
  98. */
  99. void addGroupObserver(Observer* observer);
  100. /**
  101. * Removes a group observer.
  102. *
  103. * @param observer Observer to remove.
  104. */
  105. void removeGroupObserver(Observer* observer);
  106. /// Removes all group observers.
  107. void removeGroupObservers();
  108. /// @copydoc EntityGroupBase::isRegistered(EntityID) const
  109. virtual bool isRegistered(EntityID entity) const;
  110. /**
  111. * Returns the member list.
  112. *
  113. * @return List of members.
  114. */
  115. const std::list<Member*>* getMembers() const;
  116. /**
  117. * Returns the member with the specified ID.
  118. *
  119. * @param entity Entity ID of a group member.
  120. * @return Member with the specified ID, or nullptr if an entity with that ID is not registered.
  121. */
  122. const Member* getMemberByEntity(EntityID entity) const;
  123. private:
  124. template <std::size_t index, typename U, typename... V>
  125. typename std::enable_if<(sizeof...(V) == 0), void>::type attachComponents(Member* member)
  126. {
  127. std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
  128. }
  129. template <std::size_t index, typename U, typename... V>
  130. typename std::enable_if<(sizeof...(V) > 0), void>::type attachComponents(Member* member)
  131. {
  132. std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
  133. attachComponents<index + 1, V...>(member);
  134. }
  135. virtual void registerMember(EntityID entity);
  136. virtual void unregisterMember(EntityID entity);
  137. std::list<Member*> members;
  138. std::map<EntityID, Member*> memberMap;
  139. std::list<Observer*> observers;
  140. };
  141. template <typename... T>
  142. EntityGroup<T...>::EntityGroup(ComponentManager* componentManager):
  143. EntityGroupBase(componentManager, ComponentFilter({(T::TYPE)...}))
  144. {}
  145. template <typename... T>
  146. EntityGroup<T...>::~EntityGroup()
  147. {
  148. while (!members.empty())
  149. {
  150. Member* member = members.back();
  151. members.pop_back();
  152. memberMap.erase(memberMap.find(member->entity));
  153. for (Observer* observer: observers)
  154. {
  155. observer->memberUnregistered(member);
  156. }
  157. delete member;
  158. }
  159. }
  160. template <typename... T>
  161. void EntityGroup<T...>::addGroupObserver(Observer* observer)
  162. {
  163. observers.push_back(observer);
  164. }
  165. template <typename... T>
  166. void EntityGroup<T...>::removeGroupObserver(Observer* observer)
  167. {
  168. observers.remove(observer);
  169. }
  170. template <typename... T>
  171. void EntityGroup<T...>::removeGroupObservers()
  172. {
  173. observers.clear();
  174. }
  175. template <typename... T>
  176. inline bool EntityGroup<T...>::isRegistered(EntityID entity) const
  177. {
  178. return (memberMap.find(entity) != memberMap.end());
  179. }
  180. template <typename... T>
  181. inline const std::list<typename EntityGroup<T...>::Member*>* EntityGroup<T...>::getMembers() const
  182. {
  183. return &members;
  184. }
  185. template <typename... T>
  186. inline const typename EntityGroup<T...>::Member* EntityGroup<T...>::getMemberByEntity(EntityID entity) const
  187. {
  188. auto it = memberMap.find(entity);
  189. if (it != memberMap.end())
  190. {
  191. return it->second;
  192. }
  193. return nullptr;
  194. }
  195. template <typename... T>
  196. void EntityGroup<T...>::registerMember(EntityID entity)
  197. {
  198. Member* member = new Member();
  199. member->entity = entity;
  200. attachComponents<0, T...>(member);
  201. members.push_back(member);
  202. memberMap[entity] = member;
  203. for (Observer* observer: observers)
  204. {
  205. observer->memberRegistered(member);
  206. }
  207. }
  208. template <typename... T>
  209. void EntityGroup<T...>::unregisterMember(EntityID entity)
  210. {
  211. auto it = memberMap.find(entity);
  212. Member* member = it->second;
  213. memberMap.erase(it);
  214. members.remove(member);
  215. for (Observer* observer: observers)
  216. {
  217. observer->memberUnregistered(member);
  218. }
  219. delete member;
  220. }
  221. #endif // ENTITY_GROUP_HPP