.. _program_listing_file_PrismEngine_src_componentManager.h: Program Listing for File componentManager.h =========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``PrismEngine/src/componentManager.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include "entity.h" #include #include #include #include #include #include #include namespace prism { namespace scene { class ComponentManager { public: ComponentManager() = default; template bool addComponent(Entity entityId, T component) { auto& storage = getComponentStorage(); storage.components[entityId] = std::make_shared(component); getEntitiesWith().insert(entityId); return true; } template bool removeComponent(Entity entityId) { auto& storage = getComponentStorage(); auto it = storage.components.find(entityId); if (it == storage.components.end()) return false; storage.components.erase(it); getEntitiesWith().erase(entityId); return true; } template T* getComponent(Entity entityId) { auto& storage = getComponentStorage(); auto it = storage.components.find(entityId); if (it == storage.components.end()) return nullptr; return it->second.get(); } template const std::set& getEntitiesWith() const { static const std::set emptySet; auto typeIndex = std::type_index(typeid(T)); auto it = entitiesWithComponentSets.find(typeIndex); if (it == entitiesWithComponentSets.end()) return emptySet; return *it->second; } template std::set& getEntitiesWith() { auto typeIndex = std::type_index(typeid(T)); if (entitiesWithComponentSets.find(typeIndex) == entitiesWithComponentSets.end()) { entitiesWithComponentSets[typeIndex] = std::make_unique>(); } return *entitiesWithComponentSets[typeIndex]; } template std::set getEntitiesWithAll() const { if constexpr (sizeof...(ComponentTypes) == 0) { return std::set(); } else { // Получаем множества для каждого типа компонентов std::vector*> sets; (sets.push_back(&getEntitiesWith()), ...); // Находим наименьшее множество для оптимизации auto smallestIt = std::min_element(sets.begin(), sets.end(), [](const std::set* a, const std::set* b) { return a->size() < b->size(); }); std::set result = **smallestIt; // Пересекаем с остальными множествами for (const auto& entitySetPtr : sets) { if (entitySetPtr == *smallestIt) continue; std::set temp; std::set_intersection( result.begin(), result.end(), entitySetPtr->begin(), entitySetPtr->end(), std::inserter(temp, temp.begin()) ); result = std::move(temp); } return result; } } void removeAllComponents(Entity entityId); private: struct IComponentStorage { virtual ~IComponentStorage() = default; virtual void removeEntity(Entity entityId) = 0; }; template struct ComponentStorage : public IComponentStorage { std::unordered_map> components; void removeEntity(Entity entityId) override { components.erase(entityId); } }; template ComponentStorage& getComponentStorage() { auto typeIndex = std::type_index(typeid(T)); if (componentStorages.find(typeIndex) == componentStorages.end()) { componentStorages[typeIndex] = std::make_unique>(); } return static_cast&>(*componentStorages[typeIndex]); } std::unordered_map> componentStorages; std::unordered_map>> entitiesWithComponentSets; }; } }