.. _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.addComponent(entityId, std::forward(component)); return true; } template bool removeComponent(Entity entityId) { ComponentStorage& storage = getComponentStorage(); return storage.removeComponent(entityId); } template bool hasComponent(Entity entityId) const { const ComponentStorage* storage = getComponentStorageConst(); return storage ? storage->hasComponent(entityId) : false; } template T* getComponent(Entity entityId) { ComponentStorage& storage = getComponentStorage(); return storage.getComponent(entityId); } template const std::vector& getEntitiesWith() const { static const std::vector empty; const ComponentStorage* storage = getComponentStorageConst(); return storage ? storage->entities : empty; } template struct StorageView { const std::vector& components; const std::vector& entities; }; template StorageView view() const { const auto* storage = getComponentStorageConst(); if (storage) { return { storage->components, storage->entities }; } else { static const std::vector emptyComp; static const std::vector emptyEnt; return { emptyComp, emptyEnt }; } } template std::vector getEntitiesWithAll() const { if constexpr (sizeof...(ComponentTypes) == 0) return {}; else { // Собираем векторы сущностей для каждого типа std::vector*> entityVectors; (entityVectors.push_back(&getEntitiesWith()), ...); // Выбираем самый маленький вектор для итерации auto smallestIt = std::min_element(entityVectors.begin(), entityVectors.end(), [](const auto* a, const auto* b) { return a->size() < b->size(); }); const auto& smallestVec = **smallestIt; std::vector result; result.reserve(smallestVec.size()); for (Entity e : smallestVec) { if ((hasComponent(e) && ...)) { result.push_back(e); } } return result; } } void removeAllComponents(Entity entityId); private: struct IComponentStorage { virtual ~IComponentStorage() = default; virtual void removeEntity(Entity entityId) = 0; }; template struct ComponentStorage : public IComponentStorage { std::vector components; // @brief Сущности, соответствующие компонентам std::vector entities; // @brief Позиция в массивах std::unordered_map entityToIndex; template void addComponent(Entity entity, U&& component) { auto it = entityToIndex.find(entity); if (it != entityToIndex.end()) { components[it->second] = std::forward(component); return; } size_t index = components.size(); components.push_back(std::forward(component)); entities.push_back(entity); entityToIndex[entity] = index; } bool removeComponent(Entity entity) { auto it = entityToIndex.find(entity); if (it == entityToIndex.end()) return false; size_t index = it->second; size_t lastIndex = components.size() - 1; if (index != lastIndex) { components[index] = std::move(components[lastIndex]); entities[index] = entities[lastIndex]; entityToIndex[entities[index]] = index; } components.pop_back(); entities.pop_back(); entityToIndex.erase(it); return true; } T* getComponent(Entity entity) { auto it = entityToIndex.find(entity); if (it == entityToIndex.end()) return nullptr; return &components[it->second]; } bool hasComponent(Entity entity) const { return entityToIndex.find(entity) != entityToIndex.end(); } void removeEntity(Entity entityId) override { removeComponent(entityId); } }; template ComponentStorage& getComponentStorage() { auto typeIndex = std::type_index(typeid(T)); auto it = componentStorages.find(typeIndex); if (it == componentStorages.end()) { auto storage = std::make_unique>(); auto* ptr = storage.get(); componentStorages[typeIndex] = std::move(storage); return *ptr; } return static_cast&>(*it->second); } template const ComponentStorage* getComponentStorageConst() const { auto typeIndex = std::type_index(typeid(T)); auto it = componentStorages.find(typeIndex); if (it == componentStorages.end()) return nullptr; return static_cast*>(it->second.get()); } // Карта "тип -> хранилище" std::unordered_map> componentStorages; }; } }