117 lines
4 KiB
C++
117 lines
4 KiB
C++
#include "componentmanager.hpp"
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
|
|
/**
|
|
* ComponentArray
|
|
**/
|
|
|
|
template <typename T>
|
|
void ComponentArray<T>::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 <typename T> void ComponentArray<T>::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 <typename T> T &ComponentArray<T>::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 <typename T> void ComponentArray<T>::EntityDestroyed(Entity entity) {
|
|
if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end()) {
|
|
// Remove the entity's component if it existed
|
|
RemoveData(entity);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* ComponentManager
|
|
**/
|
|
|
|
// Private functions
|
|
template <typename T>
|
|
std::shared_ptr<ComponentArray<T>> ComponentManager::GetComponentArray() {
|
|
const char *typeName = typeid(T).name();
|
|
|
|
assert(mComponentTypes.find(typeName) != mComponentTypes.end() &&
|
|
"Component not registered before use.");
|
|
|
|
return std::static_pointer_cast<ComponentArray<T>>(
|
|
mComponentArrays[typeName]);
|
|
}
|
|
|
|
// Public functions
|
|
template <typename T> 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<ComponentArray<T>>()});
|
|
|
|
// Increment the value so that the next component registered will be different
|
|
++mNextComponentType;
|
|
};
|
|
template <typename T> 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 <typename T>
|
|
void ComponentManager::AddComponent(Entity entity, T component) {
|
|
// Add a component to the array for an entity
|
|
GetComponentArray<T>()->InsertData(entity, component);
|
|
}
|
|
template <typename T> void ComponentManager::RemoveComponent(Entity entity) {
|
|
// Remove a component from the array for an entity
|
|
GetComponentArray<T>()->RemoveData(entity);
|
|
}
|
|
template <typename T> T &ComponentManager::GetComponent(Entity entity) {
|
|
// Get a reference to a component from the array for an entity
|
|
return GetComponentArray<T>()->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);
|
|
}
|
|
};
|