#include "componentmanager.hpp" #include #include /** * ComponentArray **/ template void ComponentArray::InsertData(Entity entity, T component) { assert(mEntityToIndexMap.find(entity) == mEntityToIndexMap.end() && "Component added to same entity more than once."); // Put new entry at end and update the maps size_t newIndex = mSize; mEntityToIndexMap[entity] = newIndex; mIndexToEntityMap[newIndex] = entity; mComponentArray[newIndex] = component; ++mSize; }; template void ComponentArray::RemoveData(Entity entity) { assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && "Removing non-existent component."); // Copy element at end into deleted element's place to maintain density size_t indexOfRemovedEntity = mEntityToIndexMap[entity]; size_t indexOfLastElement = mSize - 1; mComponentArray[indexOfRemovedEntity] = mComponentArray[indexOfLastElement]; // Update map to point to moved spot Entity entityOfLastElement = mIndexToEntityMap[indexOfLastElement]; mEntityToIndexMap[entityOfLastElement] = indexOfRemovedEntity; mIndexToEntityMap[indexOfRemovedEntity] = entityOfLastElement; mEntityToIndexMap.erase(entity); mIndexToEntityMap.erase(indexOfLastElement); --mSize; }; template T &ComponentArray::GetData(Entity entity) { assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && "Retrieving non-existent component."); // Return a reference to the entity's component return mComponentArray[mEntityToIndexMap[entity]]; }; template void ComponentArray::EntityDestroyed(Entity entity) { if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end()) { // Remove the entity's component if it existed RemoveData(entity); } }; /** * ComponentManager **/ // Private functions template std::shared_ptr> ComponentManager::GetComponentArray() { const char *typeName = typeid(T).name(); assert(mComponentTypes.find(typeName) != mComponentTypes.end() && "Component not registered before use."); return std::static_pointer_cast>( mComponentArrays[typeName]); } // Public functions template void ComponentManager::RegisterComponent() { const char *typeName = typeid(T).name(); assert(mComponentTypes.find(typeName) == mComponentTypes.end() && "Registering component type more than once."); // Add this component type to the component type map mComponentTypes.insert({typeName, mNextComponentType}); // Create a ComponentArray pointer and add it to the component arrays map mComponentArrays.insert({typeName, std::make_shared>()}); // Increment the value so that the next component registered will be different ++mNextComponentType; }; template ComponentType ComponentManager::GetComponentType() { const char *typeName = typeid(T).name(); assert(mComponentTypes.find(typeName) != mComponentTypes.end() && "Component not registered before use."); // Return this component's type - used for creating signatures return mComponentTypes[typeName]; } template void ComponentManager::AddComponent(Entity entity, T component) { // Add a component to the array for an entity GetComponentArray()->InsertData(entity, component); } template void ComponentManager::RemoveComponent(Entity entity) { // Remove a component from the array for an entity GetComponentArray()->RemoveData(entity); } template T &ComponentManager::GetComponent(Entity entity) { // Get a reference to a component from the array for an entity return GetComponentArray()->GetData(entity); } void ComponentManager::EntityDestroyed(Entity entity) { // Notify each component array that an entity has been destroyed // If it has a component for that entity, it will remove it for (auto const &pair : mComponentArrays) { auto const &component = pair.second; component->EntityDestroyed(entity); } };