#pragma once #pragma warning(disable: 4251) #include "Facade.h" #include "Handle/Handle.h" #include "Utilities/TypeIDCounter.h" #include "Containers/ComponentContainer.h" namespace GECS{ class GECS_API ComponentManager { private: std::unordered_map m_componentTypeContainers; std::vector m_componentTableById; // Contains components' id. // Access by the index of the entity descriptor (Handle) // and the component type ID. std::vector> m_entityComponentsIdByTypes; object_id GetNewId(IComponent* component); void ReleaseId(object_id id); void AttachComponentToEntity(Handle entityHandle, object_id componentId, type_id componentTypeId); void DetachComponentToEntity(Handle entityHandle, object_id componentId, type_id componentTypeId); public: ComponentManager(); ~ComponentManager(); template T* AddComponent(const Handle entityHandle, Arguments&&... args) { uptr address = GetComponentContainer(m_componentTypeContainers)->CreateObject(); const object_id componentId = this->GetNewId((T*)address); // creating an object at a dedicated address IComponent* component = new (reinterpret_cast(address)) T (std::forward(args)...); component->m_componentID = componentId; component->m_entityOwner = entityHandle; AttachComponentToEntity(entityHandle, componentId, T::COMPONENT_TYPE_ID); L_(ldebug) << "Added a new component " << typeid(T).name() << " for the entity " << entityHandle.index; return static_cast(component); } template void ReleaseComponent(const Handle entityHandle) { const object_id componentId = this->m_entityComponentsIdByTypes[entityHandle.index][T::COMPONENT_TYPE_ID]; IComponent* component = this->m_componentTableById[componentId]; GetComponentContainer(m_componentTypeContainers)->ReleaseComponent(component); DetachComponentToEntity(entityHandle, componentId, T::COMPONENT_TYPE_ID); L_(ldebug) << "Released a component " << typeid(T).name() << " for the entity " << entityHandle.index; } template T* GetComponent(const Handle entityHandle) { const object_id componentId = this->m_entityComponentsIdByTypes[entityHandle.index][T::COMPONENT_TYPE_ID]; if (componentId == INVALID_OBJECT_ID) { return nullptr; } return static_cast(this->m_componentTableById[componentId]); } template inline typename ComponentContainer::iterator begin() { return GetComponentContainer(m_componentTypeContainers)->begin(); } template inline typename ComponentContainer::iterator end() { return GetComponentContainer(m_componentTypeContainers)->end(); } void ReleaseAllComponents(const Handle entityHandle); }; }