18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "entity_manager.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <algorithm> 198bf80f4bSopenharmony_ci#include <atomic> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <base/containers/generic_iterator.h> 228bf80f4bSopenharmony_ci#include <base/containers/iterator.h> 238bf80f4bSopenharmony_ci#include <base/containers/refcnt_ptr.h> 248bf80f4bSopenharmony_ci#include <base/containers/type_traits.h> 258bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h> 268bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 278bf80f4bSopenharmony_ci#include <base/containers/vector.h> 288bf80f4bSopenharmony_ci#include <base/namespace.h> 298bf80f4bSopenharmony_ci#include <core/ecs/entity.h> 308bf80f4bSopenharmony_ci#include <core/ecs/entity_reference.h> 318bf80f4bSopenharmony_ci#include <core/ecs/intf_entity_manager.h> 328bf80f4bSopenharmony_ci#include <core/log.h> 338bf80f4bSopenharmony_ci#include <core/namespace.h> 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 368bf80f4bSopenharmony_ciusing BASE_NS::pair; 378bf80f4bSopenharmony_ciusing BASE_NS::vector; 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_cinamespace { 408bf80f4bSopenharmony_ciuint32_t GetId(const Entity& e) 418bf80f4bSopenharmony_ci{ 428bf80f4bSopenharmony_ci return e.id & 0xFFFFFFFF; 438bf80f4bSopenharmony_ci} 448bf80f4bSopenharmony_ci 458bf80f4bSopenharmony_ciuint32_t GetGeneration(const Entity& e) 468bf80f4bSopenharmony_ci{ 478bf80f4bSopenharmony_ci return (e.id >> 32l) & 0xFFFFFFFF; 488bf80f4bSopenharmony_ci} 498bf80f4bSopenharmony_ci 508bf80f4bSopenharmony_ciEntity MakeEntityId(uint32_t g, uint32_t i) 518bf80f4bSopenharmony_ci{ 528bf80f4bSopenharmony_ci return { (static_cast<uint64_t>(g) << 32l) | i }; 538bf80f4bSopenharmony_ci} 548bf80f4bSopenharmony_ci 558bf80f4bSopenharmony_ciclass EntityReferenceCounter final : public IEntityReferenceCounter { 568bf80f4bSopenharmony_cipublic: 578bf80f4bSopenharmony_ci using Ptr = BASE_NS::refcnt_ptr<EntityReferenceCounter>; 588bf80f4bSopenharmony_ci EntityReferenceCounter() = default; 598bf80f4bSopenharmony_ci ~EntityReferenceCounter() override = default; 608bf80f4bSopenharmony_ci EntityReferenceCounter(const EntityReferenceCounter&) = delete; 618bf80f4bSopenharmony_ci EntityReferenceCounter& operator=(const EntityReferenceCounter&) = delete; 628bf80f4bSopenharmony_ci EntityReferenceCounter(EntityReferenceCounter&&) = delete; 638bf80f4bSopenharmony_ci EntityReferenceCounter& operator=(EntityReferenceCounter&&) = delete; 648bf80f4bSopenharmony_ci 658bf80f4bSopenharmony_ciprotected: 668bf80f4bSopenharmony_ci void Ref() noexcept override 678bf80f4bSopenharmony_ci { 688bf80f4bSopenharmony_ci refcnt_.fetch_add(1, std::memory_order_relaxed); 698bf80f4bSopenharmony_ci } 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_ci void Unref() noexcept override 728bf80f4bSopenharmony_ci { 738bf80f4bSopenharmony_ci if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 0) { 748bf80f4bSopenharmony_ci std::atomic_thread_fence(std::memory_order_acquire); 758bf80f4bSopenharmony_ci delete this; 768bf80f4bSopenharmony_ci } 778bf80f4bSopenharmony_ci } 788bf80f4bSopenharmony_ci 798bf80f4bSopenharmony_ci int32_t GetRefCount() const noexcept override 808bf80f4bSopenharmony_ci { 818bf80f4bSopenharmony_ci return refcnt_.load(); 828bf80f4bSopenharmony_ci } 838bf80f4bSopenharmony_ci 848bf80f4bSopenharmony_ciprivate: 858bf80f4bSopenharmony_ci std::atomic<int32_t> refcnt_ { -1 }; 868bf80f4bSopenharmony_ci}; 878bf80f4bSopenharmony_ci} // namespace 888bf80f4bSopenharmony_ci 898bf80f4bSopenharmony_ciEntityManager::EntityManager() : EntityManager(64u) {} 908bf80f4bSopenharmony_ci 918bf80f4bSopenharmony_ciEntityManager::EntityManager(const size_t entityCount) 928bf80f4bSopenharmony_ci{ 938bf80f4bSopenharmony_ci entities_.reserve(entityCount); 948bf80f4bSopenharmony_ci} 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ciEntityManager::~EntityManager() 978bf80f4bSopenharmony_ci{ 988bf80f4bSopenharmony_ci // count live entities, should be zero 998bf80f4bSopenharmony_ci [[maybe_unused]] int32_t liveEntities = 0; 1008bf80f4bSopenharmony_ci [[maybe_unused]] int32_t inactiveEntities = 0; 1018bf80f4bSopenharmony_ci for (const auto& e : entities_) { 1028bf80f4bSopenharmony_ci if (EntityState::State::ALIVE == e.state) { 1038bf80f4bSopenharmony_ci ++liveEntities; 1048bf80f4bSopenharmony_ci } 1058bf80f4bSopenharmony_ci if (EntityState::State::INACTIVE == e.state) { 1068bf80f4bSopenharmony_ci ++inactiveEntities; 1078bf80f4bSopenharmony_ci } 1088bf80f4bSopenharmony_ci } 1098bf80f4bSopenharmony_ci CORE_ASSERT(inactiveEntities == 0); 1108bf80f4bSopenharmony_ci CORE_ASSERT(liveEntities == 0); 1118bf80f4bSopenharmony_ci} 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ciEntity EntityManager::Create() 1148bf80f4bSopenharmony_ci{ 1158bf80f4bSopenharmony_ci Entity result; 1168bf80f4bSopenharmony_ci if (freeList_.empty()) { 1178bf80f4bSopenharmony_ci const auto generation = 1U; 1188bf80f4bSopenharmony_ci const auto id = static_cast<uint32_t>(entities_.size()); 1198bf80f4bSopenharmony_ci entities_.push_back({ EntityState::State::ALIVE, generation, nullptr }); 1208bf80f4bSopenharmony_ci result = MakeEntityId(generation, id); 1218bf80f4bSopenharmony_ci } else { 1228bf80f4bSopenharmony_ci const auto id = freeList_.back(); 1238bf80f4bSopenharmony_ci freeList_.pop_back(); 1248bf80f4bSopenharmony_ci auto& slot = entities_[id]; 1258bf80f4bSopenharmony_ci // if the slot isn't free report a dead entity 1268bf80f4bSopenharmony_ci if (slot.state != EntityState::State::FREE) { 1278bf80f4bSopenharmony_ci const auto deadEntity = MakeEntityId(slot.generation, id); 1288bf80f4bSopenharmony_ci removedList_.push_back(deadEntity); 1298bf80f4bSopenharmony_ci eventList_.push_back({ deadEntity, EventType::DESTROYED }); 1308bf80f4bSopenharmony_ci } 1318bf80f4bSopenharmony_ci slot.counter = nullptr; // NOTE: could push to a pool and recycle used often 1328bf80f4bSopenharmony_ci ++slot.generation; 1338bf80f4bSopenharmony_ci 1348bf80f4bSopenharmony_ci slot.state = EntityState::State::ALIVE; 1358bf80f4bSopenharmony_ci result = MakeEntityId(slot.generation, id); 1368bf80f4bSopenharmony_ci } 1378bf80f4bSopenharmony_ci eventList_.push_back({ result, EventType::CREATED }); 1388bf80f4bSopenharmony_ci ++generationCounter_; 1398bf80f4bSopenharmony_ci return result; 1408bf80f4bSopenharmony_ci} 1418bf80f4bSopenharmony_ci 1428bf80f4bSopenharmony_ciEntityReference EntityManager::CreateReferenceCounted() 1438bf80f4bSopenharmony_ci{ 1448bf80f4bSopenharmony_ci Entity result; 1458bf80f4bSopenharmony_ci if (freeList_.empty()) { 1468bf80f4bSopenharmony_ci const auto generation = 1U; 1478bf80f4bSopenharmony_ci const auto id = static_cast<uint32_t>(entities_.size()); 1488bf80f4bSopenharmony_ci entities_.push_back( 1498bf80f4bSopenharmony_ci { EntityState::State::ALIVE, generation, IEntityReferenceCounter::Ptr { new EntityReferenceCounter } }); 1508bf80f4bSopenharmony_ci result = MakeEntityId(generation, id); 1518bf80f4bSopenharmony_ci } else { 1528bf80f4bSopenharmony_ci const auto id = freeList_.back(); 1538bf80f4bSopenharmony_ci freeList_.pop_back(); 1548bf80f4bSopenharmony_ci auto& slot = entities_[id]; 1558bf80f4bSopenharmony_ci 1568bf80f4bSopenharmony_ci // if the slot isn't free report a dead entity 1578bf80f4bSopenharmony_ci if (slot.state != EntityState::State::FREE) { 1588bf80f4bSopenharmony_ci const auto deadEntity = MakeEntityId(slot.generation, id); 1598bf80f4bSopenharmony_ci removedList_.push_back(deadEntity); 1608bf80f4bSopenharmony_ci eventList_.push_back({ deadEntity, EventType::DESTROYED }); 1618bf80f4bSopenharmony_ci } 1628bf80f4bSopenharmony_ci if (!slot.counter) { 1638bf80f4bSopenharmony_ci slot.counter.reset(new EntityReferenceCounter); 1648bf80f4bSopenharmony_ci } 1658bf80f4bSopenharmony_ci ++slot.generation; 1668bf80f4bSopenharmony_ci slot.state = EntityState::State::ALIVE; 1678bf80f4bSopenharmony_ci result = MakeEntityId(slot.generation, id); 1688bf80f4bSopenharmony_ci } 1698bf80f4bSopenharmony_ci eventList_.push_back({ result, EventType::CREATED }); 1708bf80f4bSopenharmony_ci ++generationCounter_; 1718bf80f4bSopenharmony_ci return EntityReference(result, entities_[GetId(result)].counter); 1728bf80f4bSopenharmony_ci} 1738bf80f4bSopenharmony_ci 1748bf80f4bSopenharmony_ciEntityReference EntityManager::GetReferenceCounted(const Entity entity) 1758bf80f4bSopenharmony_ci{ 1768bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 1778bf80f4bSopenharmony_ci if (const uint32_t id = GetId(entity); id < entities_.size()) { 1788bf80f4bSopenharmony_ci auto& e = entities_[id]; 1798bf80f4bSopenharmony_ci // make sure the given entity id has the same generation and that the entity isn't dead or free. 1808bf80f4bSopenharmony_ci if ((e.generation == GetGeneration(entity)) && 1818bf80f4bSopenharmony_ci ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) { 1828bf80f4bSopenharmony_ci if (!e.counter) { 1838bf80f4bSopenharmony_ci // entity wasn't yet reference counted so add a counter 1848bf80f4bSopenharmony_ci e.counter.reset(new EntityReferenceCounter); 1858bf80f4bSopenharmony_ci return { entity, e.counter }; 1868bf80f4bSopenharmony_ci } 1878bf80f4bSopenharmony_ci if (e.counter->GetRefCount() > 0) { 1888bf80f4bSopenharmony_ci // reference count is still valid 1898bf80f4bSopenharmony_ci return { entity, e.counter }; 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci // reference count has expired, but we won't revive the entity. 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci } 1948bf80f4bSopenharmony_ci } 1958bf80f4bSopenharmony_ci return {}; 1968bf80f4bSopenharmony_ci} 1978bf80f4bSopenharmony_ci 1988bf80f4bSopenharmony_civoid EntityManager::Destroy(const Entity entity) 1998bf80f4bSopenharmony_ci{ 2008bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 2018bf80f4bSopenharmony_ci if (const uint32_t id = GetId(entity); id < entities_.size()) { 2028bf80f4bSopenharmony_ci auto& e = entities_[id]; 2038bf80f4bSopenharmony_ci if ((e.generation == GetGeneration(entity)) && 2048bf80f4bSopenharmony_ci ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) { 2058bf80f4bSopenharmony_ci e.state = EntityState::State::DEAD; 2068bf80f4bSopenharmony_ci e.counter = nullptr; 2078bf80f4bSopenharmony_ci removedList_.push_back(entity); 2088bf80f4bSopenharmony_ci eventList_.push_back({ entity, EventType::DESTROYED }); 2098bf80f4bSopenharmony_ci ++generationCounter_; 2108bf80f4bSopenharmony_ci } 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci } 2138bf80f4bSopenharmony_ci} 2148bf80f4bSopenharmony_ci 2158bf80f4bSopenharmony_civoid EntityManager::DestroyAllEntities() 2168bf80f4bSopenharmony_ci{ 2178bf80f4bSopenharmony_ci for (uint32_t i = 0, count = static_cast<uint32_t>(entities_.size()); i < count; ++i) { 2188bf80f4bSopenharmony_ci auto& e = entities_[i]; 2198bf80f4bSopenharmony_ci if ((EntityState::State::ALIVE == e.state) || (EntityState::State::INACTIVE == e.state)) { 2208bf80f4bSopenharmony_ci auto entity = MakeEntityId(e.generation, i); 2218bf80f4bSopenharmony_ci removedList_.push_back(entity); 2228bf80f4bSopenharmony_ci eventList_.push_back({ entity, EventType::DESTROYED }); 2238bf80f4bSopenharmony_ci e.counter = nullptr; 2248bf80f4bSopenharmony_ci e.state = EntityState::State::DEAD; 2258bf80f4bSopenharmony_ci } 2268bf80f4bSopenharmony_ci } 2278bf80f4bSopenharmony_ci ++generationCounter_; 2288bf80f4bSopenharmony_ci} 2298bf80f4bSopenharmony_ci 2308bf80f4bSopenharmony_cibool EntityManager::IsAlive(const Entity entity) const 2318bf80f4bSopenharmony_ci{ 2328bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 2338bf80f4bSopenharmony_ci const uint32_t id = GetId(entity); 2348bf80f4bSopenharmony_ci if (id < entities_.size()) { 2358bf80f4bSopenharmony_ci const auto& state = entities_[id]; 2368bf80f4bSopenharmony_ci if (state.generation == GetGeneration(entity)) { 2378bf80f4bSopenharmony_ci return (state.state == EntityState::State::ALIVE) && 2388bf80f4bSopenharmony_ci (!state.counter || (state.counter->GetRefCount() > 0)); 2398bf80f4bSopenharmony_ci } 2408bf80f4bSopenharmony_ci } 2418bf80f4bSopenharmony_ci } 2428bf80f4bSopenharmony_ci return false; 2438bf80f4bSopenharmony_ci} 2448bf80f4bSopenharmony_ci 2458bf80f4bSopenharmony_civector<Entity> EntityManager::GetRemovedEntities() 2468bf80f4bSopenharmony_ci{ 2478bf80f4bSopenharmony_ci const auto freeSize = freeList_.size(); 2488bf80f4bSopenharmony_ci for (const Entity& e : removedList_) { 2498bf80f4bSopenharmony_ci const uint32_t id = GetId(e); 2508bf80f4bSopenharmony_ci if (id < entities_.size()) { 2518bf80f4bSopenharmony_ci if (entities_[id].generation == GetGeneration(e)) { 2528bf80f4bSopenharmony_ci CORE_ASSERT(entities_[id].state == EntityState::State::DEAD); 2538bf80f4bSopenharmony_ci if (id < entities_.size() - 1) { 2548bf80f4bSopenharmony_ci entities_[id].state = EntityState::State::FREE; 2558bf80f4bSopenharmony_ci freeList_.push_back(id); 2568bf80f4bSopenharmony_ci } else { 2578bf80f4bSopenharmony_ci entities_.resize(entities_.size() - 1); 2588bf80f4bSopenharmony_ci } 2598bf80f4bSopenharmony_ci } 2608bf80f4bSopenharmony_ci } 2618bf80f4bSopenharmony_ci } 2628bf80f4bSopenharmony_ci if (const auto finalFreeSize = freeList_.size()) { 2638bf80f4bSopenharmony_ci // by sorting with greater and using pop_back in creation we keep entities_ filled from the beginning. 2648bf80f4bSopenharmony_ci // could be removed not useful. 2658bf80f4bSopenharmony_ci if (finalFreeSize != freeSize) { 2668bf80f4bSopenharmony_ci std::sort(freeList_.begin(), freeList_.end(), std::greater {}); 2678bf80f4bSopenharmony_ci } 2688bf80f4bSopenharmony_ci // check from the beginning that ids don't go out-of-bounds and remove problematic ones. 2698bf80f4bSopenharmony_ci // most likely they never are so linear is better than lower_bounds. 2708bf80f4bSopenharmony_ci auto count = 0U; 2718bf80f4bSopenharmony_ci while ((count < finalFreeSize) && (freeList_[count] >= entities_.size())) { 2728bf80f4bSopenharmony_ci ++count; 2738bf80f4bSopenharmony_ci } 2748bf80f4bSopenharmony_ci if (count) { 2758bf80f4bSopenharmony_ci freeList_.erase(freeList_.cbegin(), freeList_.cbegin() + count); 2768bf80f4bSopenharmony_ci } 2778bf80f4bSopenharmony_ci } 2788bf80f4bSopenharmony_ci return move(removedList_); 2798bf80f4bSopenharmony_ci} 2808bf80f4bSopenharmony_ci 2818bf80f4bSopenharmony_ciuint32_t EntityManager::GetGenerationCounter() const 2828bf80f4bSopenharmony_ci{ 2838bf80f4bSopenharmony_ci return generationCounter_; 2848bf80f4bSopenharmony_ci} 2858bf80f4bSopenharmony_ci 2868bf80f4bSopenharmony_civector<pair<Entity, IEntityManager::EventType>> EntityManager::GetEvents() 2878bf80f4bSopenharmony_ci{ 2888bf80f4bSopenharmony_ci return move(eventList_); 2898bf80f4bSopenharmony_ci} 2908bf80f4bSopenharmony_ci 2918bf80f4bSopenharmony_civoid EntityManager::SetActive(const Entity entity, bool state) 2928bf80f4bSopenharmony_ci{ 2938bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 2948bf80f4bSopenharmony_ci EntityState::State oldState; 2958bf80f4bSopenharmony_ci EntityState::State newState; 2968bf80f4bSopenharmony_ci EventType event; 2978bf80f4bSopenharmony_ci if (state) { 2988bf80f4bSopenharmony_ci oldState = EntityState::State::INACTIVE; 2998bf80f4bSopenharmony_ci newState = EntityState::State::ALIVE; 3008bf80f4bSopenharmony_ci event = EventType::ACTIVATED; 3018bf80f4bSopenharmony_ci } else { 3028bf80f4bSopenharmony_ci oldState = EntityState::State::ALIVE; 3038bf80f4bSopenharmony_ci newState = EntityState::State::INACTIVE; 3048bf80f4bSopenharmony_ci event = EventType::DEACTIVATED; 3058bf80f4bSopenharmony_ci } 3068bf80f4bSopenharmony_ci 3078bf80f4bSopenharmony_ci uint32_t id = GetId(entity); 3088bf80f4bSopenharmony_ci if (id < entities_.size()) { 3098bf80f4bSopenharmony_ci if (entities_[id].generation == GetGeneration(entity)) { 3108bf80f4bSopenharmony_ci if (entities_[id].state == oldState) { 3118bf80f4bSopenharmony_ci entities_[id].state = newState; 3128bf80f4bSopenharmony_ci eventList_.push_back({ entity, event }); 3138bf80f4bSopenharmony_ci ++generationCounter_; 3148bf80f4bSopenharmony_ci } 3158bf80f4bSopenharmony_ci } 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci } 3188bf80f4bSopenharmony_ci} 3198bf80f4bSopenharmony_ci 3208bf80f4bSopenharmony_civoid EntityManager::UpdateDeadEntities() 3218bf80f4bSopenharmony_ci{ 3228bf80f4bSopenharmony_ci const auto removedCount = removedList_.size(); 3238bf80f4bSopenharmony_ci for (uint32_t id = 0, count = static_cast<uint32_t>(entities_.size()); id < count; ++id) { 3248bf80f4bSopenharmony_ci auto& e = entities_[id]; 3258bf80f4bSopenharmony_ci if ((e.state != EntityState::State::FREE) && e.counter && (e.counter->GetRefCount() == 0)) { 3268bf80f4bSopenharmony_ci const Entity entity = MakeEntityId(e.generation, id); 3278bf80f4bSopenharmony_ci removedList_.push_back(entity); 3288bf80f4bSopenharmony_ci eventList_.push_back({ entity, EventType::DESTROYED }); 3298bf80f4bSopenharmony_ci e.state = EntityState::State::DEAD; 3308bf80f4bSopenharmony_ci } 3318bf80f4bSopenharmony_ci } 3328bf80f4bSopenharmony_ci if (removedCount != removedList_.size()) { 3338bf80f4bSopenharmony_ci ++generationCounter_; 3348bf80f4bSopenharmony_ci } 3358bf80f4bSopenharmony_ci} 3368bf80f4bSopenharmony_ci 3378bf80f4bSopenharmony_ciEntityManager::IteratorImpl::IteratorImpl(const EntityManager& owner, size_t index, IteratorType type) 3388bf80f4bSopenharmony_ci : owner_(&owner), index_(static_cast<uint32_t>(index)), type_(type) 3398bf80f4bSopenharmony_ci{ 3408bf80f4bSopenharmony_ci const auto valid = (type == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE; 3418bf80f4bSopenharmony_ci if (index < owner.entities_.size()) { 3428bf80f4bSopenharmony_ci const auto& e = owner.entities_[index]; 3438bf80f4bSopenharmony_ci if ((e.state != valid) || (e.counter && e.counter->GetRefCount() == 0)) { 3448bf80f4bSopenharmony_ci Next(); 3458bf80f4bSopenharmony_ci } 3468bf80f4bSopenharmony_ci } 3478bf80f4bSopenharmony_ci} 3488bf80f4bSopenharmony_ci 3498bf80f4bSopenharmony_ciconst class IEntityManager* EntityManager::IteratorImpl::GetOwner() const 3508bf80f4bSopenharmony_ci{ 3518bf80f4bSopenharmony_ci return owner_; 3528bf80f4bSopenharmony_ci} 3538bf80f4bSopenharmony_ci 3548bf80f4bSopenharmony_cibool EntityManager::IteratorImpl::Compare(const Iterator::Ptr& other) const 3558bf80f4bSopenharmony_ci{ 3568bf80f4bSopenharmony_ci if ((other == nullptr) || (other->GetOwner() != owner_)) { 3578bf80f4bSopenharmony_ci return false; 3588bf80f4bSopenharmony_ci } 3598bf80f4bSopenharmony_ci auto* otheri = static_cast<const EntityManager::IteratorImpl*>(other.get()); 3608bf80f4bSopenharmony_ci return (index_ == otheri->index_) && (type_ == otheri->type_); 3618bf80f4bSopenharmony_ci} 3628bf80f4bSopenharmony_ci 3638bf80f4bSopenharmony_cibool EntityManager::IteratorImpl::Next() 3648bf80f4bSopenharmony_ci{ 3658bf80f4bSopenharmony_ci const auto& entities = owner_->entities_; 3668bf80f4bSopenharmony_ci if (index_ < entities.size()) { 3678bf80f4bSopenharmony_ci const auto valid = 3688bf80f4bSopenharmony_ci (type_ == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE; 3698bf80f4bSopenharmony_ci 3708bf80f4bSopenharmony_ci ++index_; 3718bf80f4bSopenharmony_ci while (index_ < entities.size()) { 3728bf80f4bSopenharmony_ci auto& state = entities[index_]; 3738bf80f4bSopenharmony_ci if ((state.state == valid) && ((!state.counter) || (state.counter->GetRefCount() > 0))) { 3748bf80f4bSopenharmony_ci break; 3758bf80f4bSopenharmony_ci } 3768bf80f4bSopenharmony_ci ++index_; 3778bf80f4bSopenharmony_ci } 3788bf80f4bSopenharmony_ci } 3798bf80f4bSopenharmony_ci return (index_ < owner_->entities_.size()); 3808bf80f4bSopenharmony_ci} 3818bf80f4bSopenharmony_ci 3828bf80f4bSopenharmony_ciEntity EntityManager::IteratorImpl::Get() const 3838bf80f4bSopenharmony_ci{ 3848bf80f4bSopenharmony_ci if (index_ >= owner_->entities_.size()) { 3858bf80f4bSopenharmony_ci return {}; 3868bf80f4bSopenharmony_ci } 3878bf80f4bSopenharmony_ci return MakeEntityId(owner_->entities_[index_].generation, index_); 3888bf80f4bSopenharmony_ci} 3898bf80f4bSopenharmony_ci 3908bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::MakeIterator(uint32_t index, IteratorType type) const 3918bf80f4bSopenharmony_ci{ 3928bf80f4bSopenharmony_ci auto del = [](Iterator* it) { delete static_cast<EntityManager::IteratorImpl*>(it); }; 3938bf80f4bSopenharmony_ci auto p = new EntityManager::IteratorImpl(*this, index, type); 3948bf80f4bSopenharmony_ci return { p, del }; 3958bf80f4bSopenharmony_ci} 3968bf80f4bSopenharmony_ci 3978bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::IteratorImpl::Clone() const 3988bf80f4bSopenharmony_ci{ 3998bf80f4bSopenharmony_ci return owner_->MakeIterator(index_, type_); 4008bf80f4bSopenharmony_ci} 4018bf80f4bSopenharmony_ci 4028bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::Begin(IteratorType type) const 4038bf80f4bSopenharmony_ci{ 4048bf80f4bSopenharmony_ci return MakeIterator(0U, type); 4058bf80f4bSopenharmony_ci} 4068bf80f4bSopenharmony_ci 4078bf80f4bSopenharmony_ciIEntityManager::Iterator::Ptr EntityManager::End(IteratorType type) const 4088bf80f4bSopenharmony_ci{ 4098bf80f4bSopenharmony_ci return MakeIterator(static_cast<uint32_t>(entities_.size()), type); 4108bf80f4bSopenharmony_ci} 4118bf80f4bSopenharmony_ci 4128bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 413