diff --git a/libs/ecs/include/psemek/ecs/container.hpp b/libs/ecs/include/psemek/ecs/container.hpp index f33ab6f1..a09f73a8 100644 --- a/libs/ecs/include/psemek/ecs/container.hpp +++ b/libs/ecs/include/psemek/ecs/container.hpp @@ -479,6 +479,9 @@ namespace psemek::ecs for (auto const & uuid : attached_uuid_set) uuids.push_back(uuid); + if (archetype_changed) + data->table->trigger_destructors(*this, data->row, attached_uuid_set, {}); + auto table = table_container_.get(uuids); if (!table) @@ -508,7 +511,7 @@ namespace psemek::ecs ((accessor.get>() = std::forward(components)), ...); if (archetype_changed) - table->trigger_constructors(*this, data->row, attached_uuid_set); + table->trigger_constructors(*this, data->row, attached_uuid_set, {}); attached_uuid_set.clear(); uuids.clear(); @@ -530,10 +533,9 @@ namespace psemek::ecs auto * data = entity_list_.get_entities().begin() + entity.id; for (auto const & column : data->table->columns()) { - if (detached_uuid_set.contains(column->uuid())) - detached_uuid_set.insert(column->uuid()); - else - uuids.push_back(column->uuid()); + auto const column_uuid = column->uuid(); + if (!detached_uuid_set.contains(column_uuid)) + uuids.push_back(column_uuid); } bool const archetype_changed = sizeof...(Components) > 0; @@ -541,7 +543,7 @@ namespace psemek::ecs auto table = table_container_.get(uuids); if (archetype_changed) - data->table->trigger_destructors(*this, data->row, detached_uuid_set); + data->table->trigger_destructors(*this, data->row, {}, detached_uuid_set); // Destructors could lead to reallocation of entity list data = entity_list_.get_entities().begin() + entity.id; @@ -568,6 +570,9 @@ namespace psemek::ecs data->row = new_row; } + if (archetype_changed) + table->trigger_constructors(*this, data->row, {}, detached_uuid_set); + detached_uuid_set.clear(); uuids.clear(); detached_uuid_set.clear(); @@ -664,9 +669,12 @@ namespace psemek::ecs auto id = next_constructor_id_++; auto constructor_factory = [function = std::move(function)](std::vector const & column_indices) -> detail::table_callback { - return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & attached_components, bool force){ + return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components, bool force){ - bool const invoke = force || (detail::contains_helper::contains(attached_components) || ...); + bool const invoke = force + || (detail::contains_helper::contains(attached_components) || ...) + || (detail::contains_helper::contains_without(detached_components) || ...) + ; if (!invoke) return; @@ -699,9 +707,11 @@ namespace psemek::ecs auto id = next_destructor_id_++; auto destructor_factory = [function = std::move(function)](std::vector const & column_indices) -> detail::table_callback { - return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & detached_components, bool force){ - - bool const invoke = force || (detail::contains_helper::contains(detached_components) || ...); + return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components, bool force){ + bool const invoke = force + || (detail::contains_helper::contains_without(attached_components) || ...) + || (detail::contains_helper::contains(detached_components) || ...) + ; if (!invoke) return; diff --git a/libs/ecs/include/psemek/ecs/detail/callback.hpp b/libs/ecs/include/psemek/ecs/detail/callback.hpp index 02fa9e61..cb154e11 100644 --- a/libs/ecs/include/psemek/ecs/detail/callback.hpp +++ b/libs/ecs/include/psemek/ecs/detail/callback.hpp @@ -16,7 +16,7 @@ namespace psemek::ecs struct table; - using table_callback = util::function const &, bool)>; + using table_callback = util::function const &, util::hash_set const &, bool)>; struct ordered_table_callback { diff --git a/libs/ecs/include/psemek/ecs/detail/table.hpp b/libs/ecs/include/psemek/ecs/detail/table.hpp index ad2edf8a..5dea109a 100644 --- a/libs/ecs/include/psemek/ecs/detail/table.hpp +++ b/libs/ecs/include/psemek/ecs/detail/table.hpp @@ -74,10 +74,10 @@ namespace psemek::ecs::detail void add_destructor(ordered_table_callback callback); void trigger_constructors(container & container, std::uint32_t row); - void trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components); + void trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components); void trigger_destructors(container & container, std::uint32_t row); - void trigger_destructors(container & container, std::uint32_t row, util::hash_set const & detached_components); + void trigger_destructors(container & container, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components); std::size_t memory_usage() const; diff --git a/libs/ecs/include/psemek/ecs/detail/without.hpp b/libs/ecs/include/psemek/ecs/detail/without.hpp index 9841c3fd..ed4f895e 100644 --- a/libs/ecs/include/psemek/ecs/detail/without.hpp +++ b/libs/ecs/include/psemek/ecs/detail/without.hpp @@ -87,6 +87,12 @@ namespace psemek::ecs::detail { return container.contains(Component::uuid()); } + + template + static bool contains_without(Container const &) + { + return false; + } }; template @@ -97,6 +103,12 @@ namespace psemek::ecs::detail { return false; } + + template + static bool contains_without(Container const & container) + { + return container.contains(Component::uuid()); + } }; } diff --git a/libs/ecs/source/detail/table.cpp b/libs/ecs/source/detail/table.cpp index 9fdd4d38..27f8011f 100644 --- a/libs/ecs/source/detail/table.cpp +++ b/libs/ecs/source/detail/table.cpp @@ -161,25 +161,25 @@ namespace psemek::ecs::detail void table::trigger_constructors(container & container, std::uint32_t row) { for (auto const & callback : *constructors_) - callback.callback(container, *this, row, column_uuid_set_, true); + callback.callback(container, *this, row, column_uuid_set_, {}, true); } - void table::trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components) + void table::trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components) { for (auto const & callback : *constructors_) - callback.callback(container, *this, row, attached_components, false); + callback.callback(container, *this, row, attached_components, detached_components, false); } void table::trigger_destructors(container & container, std::uint32_t row) { for (auto const & callback : *destructors_) - callback.callback(container, *this, row, column_uuid_set_, true); + callback.callback(container, *this, row, {}, column_uuid_set_, true); } - void table::trigger_destructors(container & container, std::uint32_t row, util::hash_set const & detached_components) + void table::trigger_destructors(container & container, std::uint32_t row, util::hash_set const & attached_components, util::hash_set const & detached_components) { for (auto const & callback : *destructors_) - callback.callback(container, *this, row, detached_components, false); + callback.callback(container, *this, row, attached_components, detached_components, false); } std::size_t table::memory_usage() const