From 50423f7ec97bbafe49dd3f7e075a52253a854938 Mon Sep 17 00:00:00 2001 From: Julian Date: Mon, 24 Jun 2019 11:45:40 +0200 Subject: [PATCH] Fixed a bug in deleteAllEntities beeing stuck with shouldBeKeeped entities and added a safeDelete function --- README.md | 7 +++++++ sources/Entity.cpp | 1 + sources/EntityManager.cpp | 28 +++++++++++++++++++++++----- sources/EntityManager.hpp | 12 ++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 280d6b8..4e07093 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,13 @@ bool deleteEntity(const internal::ID &entityID); ``` > **INFO**: For this and the following functions please see the [documentation](#documentation) or the [examples](#examples) for details on how to use them. +If you are in an applyToEach loop or if you are iterating on entities better use safeDeleteEntity: +```cpp +void safeDeleteEntity(const internal::ID &entityID); +``` +> **INFO**: For this and the following functions please see the [documentation](#documentation) or the [examples](#examples) for details on how to use them. +> **INFO**: You will need to call in a safe spot (like your main loop the function `applySafeDelete` to take effects of safeDelete) + The function used to retrieve an entity by its identifiers are as follow: ```cpp EntityHandler getEntityByID(const internal::ID &entityID); diff --git a/sources/Entity.cpp b/sources/Entity.cpp index 94c6769..78b8767 100644 --- a/sources/Entity.cpp +++ b/sources/Entity.cpp @@ -22,6 +22,7 @@ jf::entities::Entity::~Entity() { for (auto &i : _components) { delete i.second; + i.second = nullptr; } events::EventManager::getInstance().emit({this}); } diff --git a/sources/EntityManager.cpp b/sources/EntityManager.cpp index b261232..0208804 100644 --- a/sources/EntityManager.cpp +++ b/sources/EntityManager.cpp @@ -17,7 +17,7 @@ jf::entities::EntityManager &jf::entities::EntityManager::getInstance() } jf::entities::EntityManager::EntityManager() - : _maxId(0), _entities(), _freeIDs() + : _maxId(0), _entities(), _freeIDs(), _toDestroyIDs() { } @@ -111,8 +111,26 @@ std::vector jf::entities::EntityManager::getEntitie void jf::entities::EntityManager::deleteAllEntities() { - while (!_entities.empty()) { - if (!_entities.begin()->second->shouldBeKeeped()) - deleteEntity(_entities.begin()->first); + auto entity = std::find_if(_entities.begin(), _entities.end(), [](const std::pair &pair) { + return !pair.second->shouldBeKeeped(); + }); + while (entity != _entities.end()) { + deleteEntity(entity->first); + entity = std::find_if(_entities.begin(), _entities.end(), [](const std::pair &pair) { + return !pair.second->shouldBeKeeped(); + }); } -} \ No newline at end of file +} + +void jf::entities::EntityManager::safeDeleteEntity(const jf::internal::ID &entityID) +{ + _toDestroyIDs.push_back(entityID); +} + +void jf::entities::EntityManager::applySafeDelete() +{ + for (auto &id : _toDestroyIDs) { + unregisterEntity(id); + } + _toDestroyIDs.clear(); +} diff --git a/sources/EntityManager.hpp b/sources/EntityManager.hpp index 1a32cb7..d7bf2d9 100644 --- a/sources/EntityManager.hpp +++ b/sources/EntityManager.hpp @@ -79,12 +79,23 @@ namespace jf { * @return true if the entity existed and was deleted false otherwise */ bool deleteEntity(const internal::ID &entityID); + /*! + * @brief Delete an entity given it's id + * @param entityID The id of the entity to delete + * @return true if the entity existed and was deleted false otherwise + */ + void safeDeleteEntity(const internal::ID &entityID); /*! * @brief Delete all the existing entities except the ones marked as shouldBeKeeped */ void deleteAllEntities(); + /*! + * @brief Delete entities that have been marked for safe delete. + */ + void applySafeDelete(); + /*! * @brief Get an entity given an ID * @param entityID The id of the entity to get @@ -150,6 +161,7 @@ namespace jf { uint64_t _maxId; /*!< The last biggest existing entity */ std::unordered_map _entities; /*!< A map containing all the existing entities */ std::queue _freeIDs; /*!< Ids destroyed and not used */ + std::vector _toDestroyIDs; /*!< Ids of entities to destroy */ }; template