From 2b3021b5074d312fa70ddd1a07aab24ced0e91f5 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Mon, 9 Oct 2023 00:27:41 +0100 Subject: [PATCH] refactor(ecs): replace type idx by Type if needed --- core/include/cubos/core/ecs/blueprint.hpp | 9 +++-- .../cubos/core/ecs/component/manager.hpp | 21 ++++++------ .../cubos/core/ecs/component/registry.hpp | 21 ++++++------ core/include/cubos/core/memory/type_map.hpp | 2 +- core/src/cubos/core/ecs/blueprint.cpp | 9 +++-- core/src/cubos/core/ecs/component/manager.cpp | 34 +++++++------------ .../src/cubos/core/ecs/component/registry.cpp | 16 ++++----- core/src/cubos/core/ecs/world.cpp | 6 ++-- core/tests/ecs/registry.cpp | 16 +++++---- core/tests/ecs/system.cpp | 1 + 10 files changed, 63 insertions(+), 72 deletions(-) diff --git a/core/include/cubos/core/ecs/blueprint.hpp b/core/include/cubos/core/ecs/blueprint.hpp index e2a44f220..161dbc1af 100644 --- a/core/include/cubos/core/ecs/blueprint.hpp +++ b/core/include/cubos/core/ecs/blueprint.hpp @@ -191,16 +191,15 @@ namespace cubos::core::ecs ( [&]() { - auto ptr = mBuffers.at(); IBuffer* buf; - if (ptr == nullptr) + if (mBuffers.contains()) { - buf = new Buffer(); - mBuffers.set(buf); + buf = mBuffers.at(); } else { - buf = *ptr; + buf = new Buffer(); + mBuffers.insert(buf); } auto ser = data::old::BinarySerializer(buf->stream); diff --git a/core/include/cubos/core/ecs/component/manager.hpp b/core/include/cubos/core/ecs/component/manager.hpp index c2a4e35c1..d67fefb6a 100644 --- a/core/include/cubos/core/ecs/component/manager.hpp +++ b/core/include/cubos/core/ecs/component/manager.hpp @@ -13,6 +13,7 @@ #include #include +#include namespace cubos::core::ecs { @@ -33,7 +34,7 @@ namespace cubos::core::ecs /// @param type Component type. /// @return Registered name of the component type. /// @ingroup core-ecs-component - std::optional getComponentName(std::type_index type); + std::optional getComponentName(const reflection::Type& type); /// @brief Utility struct used to reference a storage of component type @p T for reading. /// @tparam T Component type. @@ -110,12 +111,12 @@ namespace cubos::core::ecs /// Must be called before any component of this type is used in any way. /// /// @param type Type of the component. - void registerComponent(std::type_index type); + void registerComponent(const reflection::Type& type); /// @brief Gets the identifier of a registered component type. /// @param type Component type. /// @return Component identifier. - std::size_t getIDFromIndex(std::type_index type) const; + std::size_t getID(const reflection::Type& type) const; /// @brief Gets the identifier of a registered component type. /// @tparam T Component type. @@ -126,7 +127,7 @@ namespace cubos::core::ecs /// @brief Gets the type of a component from its identifier. /// @param id Component identifier. /// @return Component type index. - std::type_index getType(std::size_t id) const; + const reflection::Type& getType(std::size_t id) const; //// @brief Locks a storage for reading and returns it. /// @tparam T Component type. @@ -187,10 +188,8 @@ namespace cubos::core::ecs std::unique_ptr mutex; ///< Read/write lock for the storage. }; - /// @brief Maps component types to component IDs. - std::unordered_map mTypeToIds; - - std::vector mEntries; ///< Registered component storages. + memory::TypeMap mTypeToIds; ///< Maps component types to component IDs. + std::vector mEntries; ///< Registered component storages. }; // Implementation. @@ -198,7 +197,7 @@ namespace cubos::core::ecs template std::optional getComponentName() { - return getComponentName(typeid(T)); + return getComponentName(reflection::reflect()); } template @@ -248,13 +247,13 @@ namespace cubos::core::ecs template void ComponentManager::registerComponent() { - this->registerComponent(typeid(T)); + this->registerComponent(reflection::reflect()); } template std::size_t ComponentManager::getID() const { - return this->getIDFromIndex(typeid(T)); + return this->getID(reflection::reflect()); } template diff --git a/core/include/cubos/core/ecs/component/registry.hpp b/core/include/cubos/core/ecs/component/registry.hpp index d485d963c..d29cb1d15 100644 --- a/core/include/cubos/core/ecs/component/registry.hpp +++ b/core/include/cubos/core/ecs/component/registry.hpp @@ -33,9 +33,9 @@ namespace cubos::core::ecs static bool create(std::string_view name, data::old::Deserializer& des, Blueprint& blueprint, Entity id); /// @brief Instantiates a component storage for the given component type. - /// @param type Type index of the component. + /// @param type Type of the component. /// @return Smart pointer to the storage, or nullptr if the component type was not found. - static std::unique_ptr createStorage(std::type_index type); + static std::unique_ptr createStorage(const reflection::Type& type); /// @brief Registers a new component type. /// @tparam T Component type to register. @@ -45,22 +45,21 @@ namespace cubos::core::ecs static void add(std::string_view name); /// @brief Gets the name of a component type. - /// @param type Type index of the component. + /// @param type Type of the component. /// @return Name of the component, or std::nullopt if the component type was not found. - static std::optional name(std::type_index type); + static std::optional name(const reflection::Type& type); /// @brief Gets the type index of a component type. /// @param name Name of the component. - /// @return Type index of the component, or std::nullopt if the component type was not - /// found. - static std::optional type(std::string_view name); + /// @return Type of the component, or nullptr if the component type was not found. + static const reflection::Type* type(std::string_view name); private: /// @brief Entry in the component registry. struct Entry { - std::type_index type; ///< Type index of the component. - std::string name; ///< Name of the component. + const reflection::Type* type; ///< Type of the component. + std::string name; ///< Name of the component. /// Function for creating the component from a deserializer. bool (*componentCreator)(data::old::Deserializer&, Blueprint&, Entity); @@ -88,7 +87,7 @@ namespace cubos::core::ecs assert(byNames.find(std::string(name)) == byNames.end()); auto entry = std::make_shared(Entry{ - .type = typeid(T), + .type = &reflection::reflect(), .name = std::string(name), .componentCreator = [](data::old::Deserializer& des, Blueprint& blueprint, Entity id) { @@ -109,7 +108,7 @@ namespace cubos::core::ecs }, }); - byType.set(entry); + byType.insert(entry); byNames[std::string(name)] = entry; } } // namespace cubos::core::ecs diff --git a/core/include/cubos/core/memory/type_map.hpp b/core/include/cubos/core/memory/type_map.hpp index 14275b8c2..a893a9dd8 100644 --- a/core/include/cubos/core/memory/type_map.hpp +++ b/core/include/cubos/core/memory/type_map.hpp @@ -23,7 +23,7 @@ namespace cubos::core::memory /// @param value Value. void insert(const reflection::Type& type, V value) { - mMap.emplace(&type, std::move(value)); + mMap.insert_or_assign(&type, std::move(value)); } /// @brief Sets the value associated to the given type. diff --git a/core/src/cubos/core/ecs/blueprint.cpp b/core/src/cubos/core/ecs/blueprint.cpp index be0df4f7e..9abf9b4cb 100644 --- a/core/src/cubos/core/ecs/blueprint.cpp +++ b/core/src/cubos/core/ecs/blueprint.cpp @@ -52,16 +52,15 @@ void Blueprint::merge(const std::string& prefix, const Blueprint& other) /// Then, merge the buffers. for (const auto& buffer : other.mBuffers) { - auto* ptr = mBuffers.at(buffer.first); IBuffer* buf; - if (ptr == nullptr) + if (mBuffers.contains(*buffer.first)) { - buf = buffer.second->create(); - mBuffers.set(buffer.first, buf); + buf = mBuffers.at(*buffer.first); } else { - buf = *ptr; + buf = buffer.second->create(); + mBuffers.insert(*buffer.first, buf); } buf->merge(buffer.second, prefix, src, dst); diff --git a/core/src/cubos/core/ecs/component/manager.cpp b/core/src/cubos/core/ecs/component/manager.cpp index 565ca3206..f98c7a2ce 100644 --- a/core/src/cubos/core/ecs/component/manager.cpp +++ b/core/src/cubos/core/ecs/component/manager.cpp @@ -1,53 +1,45 @@ #include #include +#include using namespace cubos::core; using namespace cubos::core::ecs; -std::optional cubos::core::ecs::getComponentName(std::type_index type) +std::optional cubos::core::ecs::getComponentName(const reflection::Type& type) { return Registry::name(type); } -void ComponentManager::registerComponent(std::type_index type) +void ComponentManager::registerComponent(const reflection::Type& type) { - if (mTypeToIds.find(type) == mTypeToIds.end()) + if (!mTypeToIds.contains(type)) { auto storage = Registry::createStorage(type); - if (storage == nullptr) - { - CUBOS_CRITICAL("Component type '{}' is not registered in the global registry", type.name()); - abort(); - } + CUBOS_ASSERT(storage != nullptr, "Component type '{}' is not registered in the global registry", type.name()); - mTypeToIds[type] = mEntries.size() + 1; // Component ids start at 1. + mTypeToIds.insert(type, mEntries.size() + 1); // Component ids start at 1. mEntries.emplace_back(std::move(storage)); } } -std::size_t ComponentManager::getIDFromIndex(std::type_index type) const +std::size_t ComponentManager::getID(const reflection::Type& type) const { - if (auto it = mTypeToIds.find(type); it != mTypeToIds.end()) - { - return it->second; - } - - CUBOS_CRITICAL("Component type '{}' is not registered in the component manager", type.name()); - abort(); + CUBOS_ASSERT(mTypeToIds.contains(type), "Component type '{}' is not registered in the component manager", + type.name()); + return mTypeToIds.at(type); } -std::type_index ComponentManager::getType(std::size_t id) const +const reflection::Type& ComponentManager::getType(std::size_t id) const { for (const auto& pair : mTypeToIds) { if (pair.second == id) { - return pair.first; + return *pair.first; } } - CUBOS_CRITICAL("No component found with ID {}", id); - abort(); + CUBOS_FAIL("No component found with ID {}", id); } void ComponentManager::remove(uint32_t id, std::size_t componentId) diff --git a/core/src/cubos/core/ecs/component/registry.cpp b/core/src/cubos/core/ecs/component/registry.cpp index 002a2209f..5eade747d 100644 --- a/core/src/cubos/core/ecs/component/registry.cpp +++ b/core/src/cubos/core/ecs/component/registry.cpp @@ -14,29 +14,29 @@ bool Registry::create(std::string_view name, data::old::Deserializer& des, Bluep return false; } -std::unique_ptr Registry::createStorage(std::type_index type) +std::unique_ptr Registry::createStorage(const reflection::Type& type) { auto& creators = Registry::entriesByType(); - if (auto* it = creators.at(type)) + if (creators.contains(type)) { - return (*it)->storageCreator(); + return creators.at(type)->storageCreator(); } return nullptr; } -std::optional Registry::name(std::type_index type) +std::optional Registry::name(const reflection::Type& type) { auto& entries = Registry::entriesByType(); - if (auto* it = entries.at(type)) + if (entries.contains(type)) { - return (*it)->name; + return entries.at(type)->name; } return std::nullopt; } -std::optional Registry::type(std::string_view name) +const reflection::Type* Registry::type(std::string_view name) { auto& entries = Registry::entriesByName(); if (auto it = entries.find(std::string(name)); it != entries.end()) @@ -44,7 +44,7 @@ std::optional Registry::type(std::string_view name) return it->second->type; } - return std::nullopt; + return nullptr; } memory::TypeMap>& Registry::entriesByType() diff --git a/core/src/cubos/core/ecs/world.cpp b/core/src/cubos/core/ecs/world.cpp index 4abc2a03f..3580f9315 100644 --- a/core/src/cubos/core/ecs/world.cpp +++ b/core/src/cubos/core/ecs/world.cpp @@ -58,15 +58,15 @@ bool World::unpack(Entity entity, const data::old::Package& package, data::old:: for (const auto& field : package.fields()) { - auto type = Registry::type(field.first); - if (!type.has_value()) + const auto* type = Registry::type(field.first); + if (type == nullptr) { CUBOS_ERROR("Unknown component type '{}'", field.first); success = false; continue; } - auto id = mComponentManager.getIDFromIndex(*type); + auto id = mComponentManager.getID(*type); if (mComponentManager.unpack(entity.index, id, field.second, context)) { mask.set(id); diff --git a/core/tests/ecs/registry.cpp b/core/tests/ecs/registry.cpp index 483968d01..382f3d43c 100644 --- a/core/tests/ecs/registry.cpp +++ b/core/tests/ecs/registry.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "utils.hpp" @@ -13,6 +14,7 @@ using cubos::core::ecs::Commands; using cubos::core::ecs::Registry; using cubos::core::ecs::VecStorage; using cubos::core::ecs::World; +using cubos::core::reflection::reflect; TEST_CASE("ecs::Registry") { @@ -23,18 +25,18 @@ TEST_CASE("ecs::Registry") auto entity = blueprint.create("entity"); // Initially "foo" of type int isn't registered. - CHECK_FALSE(Registry::type("foo").has_value()); - CHECK_FALSE(Registry::name(typeid(int)).has_value()); + CHECK(Registry::type("foo") == nullptr); + CHECK_FALSE(Registry::name(reflect()).has_value()); // After registering, it can now be found. Registry::add>("foo"); - REQUIRE(Registry::type("foo").has_value()); - CHECK(*Registry::type("foo") == typeid(int)); - REQUIRE(Registry::name(typeid(int)).has_value()); - CHECK(*Registry::name(typeid(int)) == "foo"); + REQUIRE(Registry::type("foo") != nullptr); + CHECK(Registry::type("foo") == &reflect()); + REQUIRE(Registry::name(reflect()).has_value()); + CHECK(*Registry::name(reflect()) == "foo"); // Create a storage for it and check if its of the correct type. - auto storage = Registry::createStorage(typeid(int)); + auto storage = Registry::createStorage(reflect()); CHECK(dynamic_cast*>(storage.get()) != nullptr); // Instantiate the component into a blueprint, from a package. diff --git a/core/tests/ecs/system.cpp b/core/tests/ecs/system.cpp index 154ad68cc..4777a3d16 100644 --- a/core/tests/ecs/system.cpp +++ b/core/tests/ecs/system.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "utils.hpp"