From 2bd37e7d98728d72ba44da18eefea91547a7885a Mon Sep 17 00:00:00 2001 From: Max-001 <80035972+Max-001@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:26:24 +0200 Subject: Refactored componentManager (it now uses smart pointer, does not return raw pointers (it only returns references) and it is now possible to store multiple components of the same type for the same entity) --- mwe/ecs-homemade/inc/ComponentManager.h | 33 +++++++------ mwe/ecs-homemade/inc/ComponentManager.hpp | 77 +++++++++++++++---------------- 2 files changed, 56 insertions(+), 54 deletions(-) (limited to 'mwe/ecs-homemade/inc') diff --git a/mwe/ecs-homemade/inc/ComponentManager.h b/mwe/ecs-homemade/inc/ComponentManager.h index 5b0629f..763c28e 100644 --- a/mwe/ecs-homemade/inc/ComponentManager.h +++ b/mwe/ecs-homemade/inc/ComponentManager.h @@ -6,31 +6,38 @@ #include #include #include -#include +#include class ComponentManager { public: - static ComponentManager& GetInstance(); + static ComponentManager& GetInstance(); //Singleton - ComponentManager(const ComponentManager&) = delete; - ComponentManager(ComponentManager&&) = delete; - ComponentManager& operator=(const ComponentManager&) = delete; - ComponentManager& operator=(ComponentManager&&) = delete; + ComponentManager(const ComponentManager&) = delete; //Singleton + ComponentManager(ComponentManager&&) = delete; //Singleton + ComponentManager& operator=(const ComponentManager&) = delete; //Singleton + ComponentManager& operator=(ComponentManager&&) = delete; //Singleton template - void AddComponent(std::uint32_t id, Args&&... args); + void AddComponent(std::uint32_t id, Args&&... args); //Add a component + //TODO: void DeleteAllComponentsOfId(std::uint32_t id); //Deletes all components of a specific id + //TODO: void DeleteAllComponents(); //Deletes all components + template - std::vector> GetComponentsOfID(std::uint32_t id); - /*template - std::vector GetAllComponentIDs(); + std::vector> GetComponentsByID(std::uint32_t id) const; //Get a vector<> of all components at specific id template - std::vector GetAllComponentPointer();*/ + std::vector, std::uint32_t>> GetComponentsByType() const; //Get a vector<> of all components of a specific type private: - static ComponentManager mInstance; + static ComponentManager mInstance; //Singleton - ComponentManager(); + ComponentManager(); //Singleton + /* + * The std::unordered_map>>> below might seem a bit strange, let me explain this structure: + * The std::unordered_map<> has a key and value. The key is a std::type_index and the value is a std::vector. So, a new std::vector will be created for each new std::type_index. + * The first std::vector<> stores another vector<>. This first vector<> is to bind the entity's id to a component. + * The second std::vector<> stores unique_ptrs. Each component can be gathered via an unique_ptr. This second vector<> allows multiple components of the same std::type_index for one entity (id). + */ std::unordered_map>>> mComponents; }; diff --git a/mwe/ecs-homemade/inc/ComponentManager.hpp b/mwe/ecs-homemade/inc/ComponentManager.hpp index a7fc30f..03135a8 100644 --- a/mwe/ecs-homemade/inc/ComponentManager.hpp +++ b/mwe/ecs-homemade/inc/ComponentManager.hpp @@ -4,68 +4,63 @@ void ComponentManager::AddComponent(std::uint32_t id, Args&&... args) { std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) if (mComponents.find(type) == mComponents.end()) { //Check if this component type is already in the unordered_map<> - mComponents[type] = std::vector>>(); //If not, create a new (empty) vector<> of unique_ptr + mComponents[type] = std::vector>>(); //If not, create a new (empty) vector<> of vector> } if (id >= mComponents[type].size()) { //Resize the vector<> if the id is greater than the current size - mComponents[type].resize(id + 1); //Initialize new slots to nullptr (resize does this automatically) + mComponents[type].resize(id + 1); //Initialize new slots to nullptr (resize does automatically init to nullptr) } - mComponents[type][id].push_back(std::make_unique(std::forward(args)...)); //Create a new component of type T using perfect forwarding and store its unique_ptr in the correct vector + mComponents[type][id].push_back(std::make_unique(std::forward(args)...)); //Create a new component of type T using perfect forwarding and store its unique_ptr in the vector<> } template -std::vector> ComponentManager::GetComponentsOfID(std::uint32_t id) { - std::type_index type = typeid(T); +std::vector> ComponentManager::GetComponentsByID(std::uint32_t id) const { + std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) + + std::vector> componentVector; //Create an empty vector<> - std::vector> componentVector; + if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_list<>) - if (mComponents.find(type) != mComponents.end()) { + const std::vector>>& componentArray = mComponents.at(type); //Get the correct vector<> - const auto& componentArray = mComponents[type]; + if (id < componentArray.size()) { //Make sure that the id (that we are looking for) is within the boundaries of the vector<> + for (const std::unique_ptr& componentPtr : componentArray[id]) { //Loop trough the whole vector<> + T* castedComponent = static_cast(componentPtr.get()); //Cast the unique_ptr to a raw pointer - if (id < componentArray.size()) { - for (const auto& componentPtr : componentArray[id]) { - // Use static_cast instead of dynamic_cast - T* castedComponent = static_cast(componentPtr.get()); - if (castedComponent) { // Ensure cast was successful - componentVector.push_back(*castedComponent); // Add the raw pointer to the vector + if (castedComponent) { //Ensure that the cast was successful + componentVector.push_back(*castedComponent); //Add the dereferenced raw pointer to the vector<> } } } } - return componentVector; // Return empty vector if not found + return componentVector; //Return the vector<> } -/*// GetAllComponentIDs implementation template -std::vector ComponentManager::GetAllComponentIDs() { - std::type_index type = typeid(T); - std::vector ids; - if (mComponents.find(type) != mComponents.end()) { - const auto& componentArray = mComponents[type]; - for (std::uint32_t id = 0; id < componentArray.size(); ++id) { - if (componentArray[id] != nullptr) { - ids.push_back(id); // Collect IDs of non-null components - } - } - } - return ids; -} +std::vector, std::uint32_t>> ComponentManager::GetComponentsByType() const { + std::type_index type = typeid(T); //Determine the type of T (this is used as the key of the unordered_map<>) -// GetAllComponentPointer implementation -template -std::vector ComponentManager::GetAllComponentPointer() { - std::type_index type = typeid(T); - std::vector pointers; - if (mComponents.find(type) != mComponents.end()) { - const auto& componentArray = mComponents[type]; - for (const auto& component : componentArray) { - if (component != nullptr) { - pointers.push_back(static_cast(component)); // Cast to the correct type + std::vector, std::uint32_t>> componentVector; //Create an empty vector<> + std::uint32_t id = 0; //Set the id to 0 (the id will also be stored in the returned vector<>) + + if (mComponents.find(type) != mComponents.end()) { //Find the type (in the unordered_list<>) + + const std::vector>>& componentArray = mComponents.at(type); //Get the correct vector<> + + for (const std::vector>& component : componentArray) { //Loop through the whole vector<> + for (const std::unique_ptr& componentPtr : component) { //Loop trough the whole vector<> + T* castedComponent = static_cast(componentPtr.get()); //Cast the unique_ptr to a raw pointer + + if (castedComponent) { //Ensure that the cast was successful + componentVector.push_back(std::make_pair(std::ref(*castedComponent), id)); //Pair the dereferenced raw pointer and the id and add it to the vector<> + } } + + ++id; //Increase the id (the id will also be stored in the returned vector<>) } } - return pointers; -}*/ + + return componentVector; +} -- cgit v1.2.3