|
|
- /*
- * Copyright (C) 2017-2019 Christopher J. Howard
- *
- * This file is part of Antkeeper Source Code.
- *
- * Antkeeper Source Code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Antkeeper Source Code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #ifndef ENTITY_GROUP_HPP
- #define ENTITY_GROUP_HPP
-
- #include "component-observer.hpp"
- #include "component-manager.hpp"
- #include "entity-group-member.hpp"
- #include "entity-group-observer.hpp"
- #include <list>
- #include <map>
- #include <set>
- #include <tuple>
- #include <utility>
-
- enum class ComponentType;
-
- /// A set of component types used to filter entities
- typedef std::set<ComponentType> ComponentFilter;
-
- /**
- * Abstract base class for entity groups.
- */
- class EntityGroupBase: protected ComponentObserver
- {
- public:
- /**
- * Creates a entity group base.
- *
- * @param componentManager The component manager with which to associate this entity group.
- * @param componentFilter Set of component types which an entity must possess in order to join this entity group.
- */
- EntityGroupBase(ComponentManager* componentManager, const ComponentFilter& componentFilter);
-
- /// Returns the set of components which an entity must possess in order to join this entity group.
- const ComponentFilter& getComponentFilter() const;
-
- /**
- * Returns true if the specified entity is registered with this entity group.
- *
- * @param entity ID of the entity to check.
- */
- virtual bool isRegistered(EntityID entity) const = 0;
-
- private:
- virtual void componentAdded(EntityID entity, ComponentBase* component);
- virtual void componentRemoved(EntityID entity, ComponentBase* component);
-
- /**
- * Called each time an entity joins the entity group by obtaining the necessary component types.
- *
- * @param entity Entity ID of the new member.
- */
- virtual void registerMember(EntityID entity) = 0;
-
- /**
- * Called each time an entity leaves an the entity group by no longer possessing the necessary component types.
- *
- * @param entity Entity ID of the former member.
- */
- virtual void unregisterMember(EntityID entity) = 0;
-
- ComponentFilter componentFilter;
- };
-
- inline const ComponentFilter& EntityGroupBase::getComponentFilter() const
- {
- return componentFilter;
- }
-
- /**
- * A group of entities which share a set of specified component types.
- *
- * @tparam T Set of components which are required for group membership.
- */
- template <typename... T>
- class EntityGroup: public EntityGroupBase
- {
- public:
- typedef EntityGroupMember<T...> Member;
- typedef EntityGroupObserver<T...> Observer;
-
- /**
- * Creates a entity group.
- *
- * @param componentManager Component manager with which to associate this entity group.
- */
- EntityGroup(ComponentManager* componentManager);
-
- /// Destroys a entity group.
- ~EntityGroup();
-
- /**
- * Adds a group observer.
- *
- * @param observer Observer to add.
- */
- void addGroupObserver(Observer* observer);
-
- /**
- * Removes a group observer.
- *
- * @param observer Observer to remove.
- */
- void removeGroupObserver(Observer* observer);
-
- /// Removes all group observers.
- void removeGroupObservers();
-
- /// @copydoc EntityGroupBase::isRegistered(EntityID) const
- virtual bool isRegistered(EntityID entity) const;
-
- /**
- * Returns the member list.
- *
- * @return List of members.
- */
- const std::list<Member*>* getMembers() const;
-
- /**
- * Returns the member with the specified ID.
- *
- * @param entity Entity ID of a group member.
- * @return Member with the specified ID, or nullptr if an entity with that ID is not registered.
- */
- const Member* getMemberByEntity(EntityID entity) const;
-
- private:
- template <std::size_t index, typename U, typename... V>
- typename std::enable_if<(sizeof...(V) == 0), void>::type attachComponents(Member* member)
- {
- std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
- }
-
- template <std::size_t index, typename U, typename... V>
- typename std::enable_if<(sizeof...(V) > 0), void>::type attachComponents(Member* member)
- {
- std::get<index>(member->components) = static_cast<U*>(componentManager->getComponent(member->entity, U::TYPE));
- attachComponents<index + 1, V...>(member);
- }
-
- virtual void registerMember(EntityID entity);
- virtual void unregisterMember(EntityID entity);
-
- std::list<Member*> members;
- std::map<EntityID, Member*> memberMap;
- std::list<Observer*> observers;
- };
-
- template <typename... T>
- EntityGroup<T...>::EntityGroup(ComponentManager* componentManager):
- EntityGroupBase(componentManager, ComponentFilter({(T::TYPE)...}))
- {}
-
- template <typename... T>
- EntityGroup<T...>::~EntityGroup()
- {
- while (!members.empty())
- {
- Member* member = members.back();
-
- members.pop_back();
- memberMap.erase(memberMap.find(member->entity));
-
- for (Observer* observer: observers)
- {
- observer->memberUnregistered(member);
- }
-
- delete member;
- }
- }
-
-
- template <typename... T>
- void EntityGroup<T...>::addGroupObserver(Observer* observer)
- {
- observers.push_back(observer);
- }
-
- template <typename... T>
- void EntityGroup<T...>::removeGroupObserver(Observer* observer)
- {
- observers.remove(observer);
- }
-
- template <typename... T>
- void EntityGroup<T...>::removeGroupObservers()
- {
- observers.clear();
- }
-
- template <typename... T>
- inline bool EntityGroup<T...>::isRegistered(EntityID entity) const
- {
- return (memberMap.find(entity) != memberMap.end());
- }
-
- template <typename... T>
- inline const std::list<typename EntityGroup<T...>::Member*>* EntityGroup<T...>::getMembers() const
- {
- return &members;
- }
-
- template <typename... T>
- inline const typename EntityGroup<T...>::Member* EntityGroup<T...>::getMemberByEntity(EntityID entity) const
- {
- auto it = memberMap.find(entity);
- if (it != memberMap.end())
- {
- return it->second;
- }
-
- return nullptr;
- }
-
- template <typename... T>
- void EntityGroup<T...>::registerMember(EntityID entity)
- {
- Member* member = new Member();
- member->entity = entity;
- attachComponents<0, T...>(member);
-
- members.push_back(member);
- memberMap[entity] = member;
-
- for (Observer* observer: observers)
- {
- observer->memberRegistered(member);
- }
- }
-
- template <typename... T>
- void EntityGroup<T...>::unregisterMember(EntityID entity)
- {
- auto it = memberMap.find(entity);
- Member* member = it->second;
-
- memberMap.erase(it);
- members.remove(member);
-
- for (Observer* observer: observers)
- {
- observer->memberUnregistered(member);
- }
-
- delete member;
- }
-
- #endif // ENTITY_GROUP_HPP
-
|