#ifndef ENTITY_MANAGER_H_C5832F11 #define ENTITY_MANAGER_H_C5832F11 #include #include #include #include #include "component.h" #include "algorithms.h" class EntityManager { private: struct EntityData { std::map> components; }; std::map entities; std::map, std::set> cachedComponents; int nextEntityID = 0; template std::set getEntitiesWithComponentsHelper(std::set& componentTypes) { componentTypes.insert(typeid(T)); return getEntitiesWithComponents(componentTypes); } template std::set getEntitiesWithComponents(std::set& componentTypes) { return getEntitiesWithComponentsHelper(componentTypes); } public: EntityManager() = default; EntityManager(const EntityManager& copy) = delete; int emplaceEntity() { // Find a suitable entity ID while ((entities.count(nextEntityID) == 1) && (nextEntityID >= 0)) { nextEntityID++; } if (nextEntityID < 0) { nextEntityID = 0; while ((entities.count(nextEntityID) == 1) && (nextEntityID >= 0)) { nextEntityID++; } assert(nextEntityID >= 0); } // Initialize the data int id = nextEntityID++; entities[id]; return id; } void deleteEntity(int entity) { assert(entities.count(entity) == 1); // Uncache components for (auto& cache : cachedComponents) { cache.second.erase(entity); } // Destroy the data entities.erase(entity); } template T& emplaceComponent(int entity, Args&&... args) { assert(entities.count(entity) == 1); EntityData& data = entities[entity]; std::type_index componentType = typeid(T); assert(data.components.count(componentType) == 0); // Initialize the component std::unique_ptr ptr = std::unique_ptr(new T(std::forward(args)...)); T& component = *ptr; data.components[componentType] = std::move(ptr); // Invalidate related caches erase_if(cachedComponents, [&componentType] (std::pair, std::set>& cache) { return cache.first.count(componentType) == 1; }); return component; } template void removeComponent(int entity) { assert(entities.count(entity) == 1); EntityData& data = entities[entity]; std::type_index componentType = typeid(T); assert(data.components.count(componentType) == 1); // Destroy the component data.components.erase(componentType); // Uncache the component for (auto& cache : cachedComponents) { if (cache.first.count(componentType) == 1) { cache.second.erase(entity); } } } template T& getComponent(int entity) { assert(entities.count(entity) == 1); EntityData& data = entities[entity]; std::type_index componentType = typeid(T); assert(data.components.count(componentType) == 1); return *((T*)data.components[componentType].get()); } template std::set getEntitiesWithComponents() { std::set componentTypes; return getEntitiesWithComponentsHelper(componentTypes); } }; template <> std::set EntityManager::getEntitiesWithComponents<>(std::set& componentTypes); #endif /* end of include guard: ENTITY_MANAGER_H_C5832F11 */