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 <algorithm> 178bf80f4bSopenharmony_ci#include <atomic> 188bf80f4bSopenharmony_ci#include <cstdint> 198bf80f4bSopenharmony_ci 208bf80f4bSopenharmony_ci#include <base/containers/array_view.h> 218bf80f4bSopenharmony_ci#include <base/containers/iterator.h> 228bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 238bf80f4bSopenharmony_ci#include <base/containers/type_traits.h> 248bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h> 258bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 268bf80f4bSopenharmony_ci#include <base/containers/vector.h> 278bf80f4bSopenharmony_ci#include <base/namespace.h> 288bf80f4bSopenharmony_ci#include <base/util/uid.h> 298bf80f4bSopenharmony_ci#include <core/ecs/entity.h> 308bf80f4bSopenharmony_ci#include <core/ecs/intf_component_manager.h> 318bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h> 328bf80f4bSopenharmony_ci#include <core/ecs/intf_system.h> 338bf80f4bSopenharmony_ci#include <core/log.h> 348bf80f4bSopenharmony_ci#include <core/namespace.h> 358bf80f4bSopenharmony_ci#include <core/perf/cpu_perf_scope.h> 368bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin.h> 378bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin_register.h> 388bf80f4bSopenharmony_ci#include <core/threading/intf_thread_pool.h> 398bf80f4bSopenharmony_ci 408bf80f4bSopenharmony_ci#include "ecs/entity_manager.h" 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 438bf80f4bSopenharmony_cinamespace { 448bf80f4bSopenharmony_ciusing BASE_NS::array_view; 458bf80f4bSopenharmony_ciusing BASE_NS::pair; 468bf80f4bSopenharmony_ciusing BASE_NS::Uid; 478bf80f4bSopenharmony_ciusing BASE_NS::unique_ptr; 488bf80f4bSopenharmony_ciusing BASE_NS::unordered_map; 498bf80f4bSopenharmony_ciusing BASE_NS::vector; 508bf80f4bSopenharmony_ci 518bf80f4bSopenharmony_ciclass Ecs final : public IEcs, IPluginRegister::ITypeInfoListener { 528bf80f4bSopenharmony_cipublic: 538bf80f4bSopenharmony_ci Ecs(IClassFactory&, const IThreadPool::Ptr& threadPool); 548bf80f4bSopenharmony_ci ~Ecs() override; 558bf80f4bSopenharmony_ci 568bf80f4bSopenharmony_ci Ecs(const Ecs&) = delete; 578bf80f4bSopenharmony_ci Ecs(const Ecs&&) = delete; 588bf80f4bSopenharmony_ci Ecs& operator=(const Ecs&) = delete; 598bf80f4bSopenharmony_ci Ecs& operator=(const Ecs&&) = delete; 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_ci IEntityManager& GetEntityManager() override; 628bf80f4bSopenharmony_ci void GetComponents(Entity entity, vector<IComponentManager*>& result) override; 638bf80f4bSopenharmony_ci vector<ISystem*> GetSystems() const override; 648bf80f4bSopenharmony_ci ISystem* GetSystem(const Uid& uid) const override; 658bf80f4bSopenharmony_ci vector<IComponentManager*> GetComponentManagers() const override; 668bf80f4bSopenharmony_ci IComponentManager* GetComponentManager(const Uid& uid) const override; 678bf80f4bSopenharmony_ci Entity CloneEntity(const Entity entity) override; 688bf80f4bSopenharmony_ci void ProcessEvents() override; 698bf80f4bSopenharmony_ci 708bf80f4bSopenharmony_ci void Initialize() override; 718bf80f4bSopenharmony_ci bool Update(uint64_t time, uint64_t delta) override; 728bf80f4bSopenharmony_ci void Uninitialize() override; 738bf80f4bSopenharmony_ci 748bf80f4bSopenharmony_ci IComponentManager* CreateComponentManager(const ComponentManagerTypeInfo& componentManagerTypeInfo) override; 758bf80f4bSopenharmony_ci ISystem* CreateSystem(const SystemTypeInfo& systemInfo) override; 768bf80f4bSopenharmony_ci 778bf80f4bSopenharmony_ci void AddListener(EntityListener& listener) override; 788bf80f4bSopenharmony_ci void RemoveListener(EntityListener& listener) override; 798bf80f4bSopenharmony_ci void AddListener(ComponentListener& listener) override; 808bf80f4bSopenharmony_ci void RemoveListener(ComponentListener& listener) override; 818bf80f4bSopenharmony_ci void AddListener(IComponentManager& manager, ComponentListener& listener) override; 828bf80f4bSopenharmony_ci void RemoveListener(IComponentManager& manager, ComponentListener& listener) override; 838bf80f4bSopenharmony_ci 848bf80f4bSopenharmony_ci void RequestRender() override; 858bf80f4bSopenharmony_ci void SetRenderMode(RenderMode renderMode) override; 868bf80f4bSopenharmony_ci RenderMode GetRenderMode() override; 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ci bool NeedRender() const override; 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_ci IClassFactory& GetClassFactory() const override; 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_ci const IThreadPool::Ptr& GetThreadPool() const override; 938bf80f4bSopenharmony_ci 948bf80f4bSopenharmony_ci float GetTimeScale() const override; 958bf80f4bSopenharmony_ci void SetTimeScale(float scale) override; 968bf80f4bSopenharmony_ci 978bf80f4bSopenharmony_ci void Ref() noexcept override; 988bf80f4bSopenharmony_ci void Unref() noexcept override; 998bf80f4bSopenharmony_ci 1008bf80f4bSopenharmony_ciprotected: 1018bf80f4bSopenharmony_ci using SystemPtr = unique_ptr<ISystem, SystemTypeInfo::DestroySystemFn>; 1028bf80f4bSopenharmony_ci using ManagerPtr = unique_ptr<IComponentManager, ComponentManagerTypeInfo::DestroyComponentManagerFn>; 1038bf80f4bSopenharmony_ci 1048bf80f4bSopenharmony_ci // IPluginRegister::ITypeInfoListener 1058bf80f4bSopenharmony_ci void OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos) override; 1068bf80f4bSopenharmony_ci 1078bf80f4bSopenharmony_ci void ProcessComponentEvents( 1088bf80f4bSopenharmony_ci IEcs::ComponentListener::EventType eventType, array_view<const Entity> removedEntities) const; 1098bf80f4bSopenharmony_ci 1108bf80f4bSopenharmony_ci IThreadPool::Ptr threadPool_; 1118bf80f4bSopenharmony_ci 1128bf80f4bSopenharmony_ci // for storing systems and component managers in creation order 1138bf80f4bSopenharmony_ci vector<SystemPtr> systemOrder_; 1148bf80f4bSopenharmony_ci vector<ManagerPtr> managerOrder_; 1158bf80f4bSopenharmony_ci // for finding systems and component managers with UID 1168bf80f4bSopenharmony_ci unordered_map<Uid, ISystem*> systems_; 1178bf80f4bSopenharmony_ci unordered_map<Uid, IComponentManager*> managers_; 1188bf80f4bSopenharmony_ci 1198bf80f4bSopenharmony_ci vector<EntityListener*> entityListeners_; 1208bf80f4bSopenharmony_ci vector<ComponentListener*> componentListeners_; 1218bf80f4bSopenharmony_ci unordered_map<IComponentManager*, vector<ComponentListener*>> componentManagerListeners_; 1228bf80f4bSopenharmony_ci 1238bf80f4bSopenharmony_ci bool needRender_ { false }; 1248bf80f4bSopenharmony_ci bool renderRequested_ { false }; 1258bf80f4bSopenharmony_ci RenderMode renderMode_ { RENDER_ALWAYS }; 1268bf80f4bSopenharmony_ci 1278bf80f4bSopenharmony_ci IClassFactory& pluginRegistry_; 1288bf80f4bSopenharmony_ci EntityManager entityManager_; 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_ci vector<pair<PluginToken, const IEcsPlugin*>> plugins_; 1318bf80f4bSopenharmony_ci float timeScale_ { 1.f }; 1328bf80f4bSopenharmony_ci std::atomic<int32_t> refcnt_ { 0 }; 1338bf80f4bSopenharmony_ci 1348bf80f4bSopenharmony_ci bool processingEvents_ { false }; 1358bf80f4bSopenharmony_ci}; 1368bf80f4bSopenharmony_ci 1378bf80f4bSopenharmony_citemplate<typename ListType, typename ValueType> 1388bf80f4bSopenharmony_ciauto Find(ListType& list, const ValueType& value) 1398bf80f4bSopenharmony_ci{ 1408bf80f4bSopenharmony_ci return std::find(list.begin(), list.end(), value); 1418bf80f4bSopenharmony_ci} 1428bf80f4bSopenharmony_ci 1438bf80f4bSopenharmony_civoid ProcessEntityListeners(const array_view<const pair<Entity, IEntityManager::EventType>> states, 1448bf80f4bSopenharmony_ci const array_view<IEcs::EntityListener*> entityListeners) 1458bf80f4bSopenharmony_ci{ 1468bf80f4bSopenharmony_ci // handle state changes (collect to groups of same kind of events) 1478bf80f4bSopenharmony_ci vector<Entity> res; 1488bf80f4bSopenharmony_ci res.reserve(states.size()); 1498bf80f4bSopenharmony_ci auto type = states[0U].second; 1508bf80f4bSopenharmony_ci for (const auto& s : states) { 1518bf80f4bSopenharmony_ci if (s.second != type) { 1528bf80f4bSopenharmony_ci if (!res.empty()) { 1538bf80f4bSopenharmony_ci // Let listeners know that entity state has changed. 1548bf80f4bSopenharmony_ci for (auto* listener : entityListeners) { 1558bf80f4bSopenharmony_ci if (listener) { 1568bf80f4bSopenharmony_ci listener->OnEntityEvent(type, res); 1578bf80f4bSopenharmony_ci } 1588bf80f4bSopenharmony_ci } 1598bf80f4bSopenharmony_ci // start collecting new events. 1608bf80f4bSopenharmony_ci res.clear(); 1618bf80f4bSopenharmony_ci } 1628bf80f4bSopenharmony_ci type = s.second; 1638bf80f4bSopenharmony_ci } 1648bf80f4bSopenharmony_ci // add to event list. 1658bf80f4bSopenharmony_ci res.push_back(s.first); 1668bf80f4bSopenharmony_ci } 1678bf80f4bSopenharmony_ci if (!res.empty()) { 1688bf80f4bSopenharmony_ci // Send the final events. 1698bf80f4bSopenharmony_ci for (auto* listener : entityListeners) { 1708bf80f4bSopenharmony_ci if (listener) { 1718bf80f4bSopenharmony_ci listener->OnEntityEvent(type, res); 1728bf80f4bSopenharmony_ci } 1738bf80f4bSopenharmony_ci } 1748bf80f4bSopenharmony_ci } 1758bf80f4bSopenharmony_ci} 1768bf80f4bSopenharmony_ci 1778bf80f4bSopenharmony_civoid Ecs::AddListener(EntityListener& listener) 1788bf80f4bSopenharmony_ci{ 1798bf80f4bSopenharmony_ci if (Find(entityListeners_, &listener) != entityListeners_.end()) { 1808bf80f4bSopenharmony_ci // already added. 1818bf80f4bSopenharmony_ci return; 1828bf80f4bSopenharmony_ci } 1838bf80f4bSopenharmony_ci entityListeners_.push_back(&listener); 1848bf80f4bSopenharmony_ci} 1858bf80f4bSopenharmony_ci 1868bf80f4bSopenharmony_civoid Ecs::RemoveListener(EntityListener& listener) 1878bf80f4bSopenharmony_ci{ 1888bf80f4bSopenharmony_ci if (auto it = Find(entityListeners_, &listener); it != entityListeners_.end()) { 1898bf80f4bSopenharmony_ci // Setting the listener to null instead of removing. This allows removing listeners from a listener callback. 1908bf80f4bSopenharmony_ci *it = nullptr; 1918bf80f4bSopenharmony_ci return; 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci} 1948bf80f4bSopenharmony_ci 1958bf80f4bSopenharmony_civoid Ecs::AddListener(ComponentListener& listener) 1968bf80f4bSopenharmony_ci{ 1978bf80f4bSopenharmony_ci if (Find(componentListeners_, &listener) != componentListeners_.end()) { 1988bf80f4bSopenharmony_ci // already added. 1998bf80f4bSopenharmony_ci return; 2008bf80f4bSopenharmony_ci } 2018bf80f4bSopenharmony_ci componentListeners_.push_back(&listener); 2028bf80f4bSopenharmony_ci} 2038bf80f4bSopenharmony_ci 2048bf80f4bSopenharmony_civoid Ecs::RemoveListener(ComponentListener& listener) 2058bf80f4bSopenharmony_ci{ 2068bf80f4bSopenharmony_ci if (auto it = Find(componentListeners_, &listener); it != componentListeners_.end()) { 2078bf80f4bSopenharmony_ci *it = nullptr; 2088bf80f4bSopenharmony_ci return; 2098bf80f4bSopenharmony_ci } 2108bf80f4bSopenharmony_ci} 2118bf80f4bSopenharmony_ci 2128bf80f4bSopenharmony_civoid Ecs::AddListener(IComponentManager& manager, ComponentListener& listener) 2138bf80f4bSopenharmony_ci{ 2148bf80f4bSopenharmony_ci auto list = componentManagerListeners_.find(&manager); 2158bf80f4bSopenharmony_ci if (list != componentManagerListeners_.end()) { 2168bf80f4bSopenharmony_ci if (auto it = Find(list->second, &listener); it != list->second.end()) { 2178bf80f4bSopenharmony_ci return; 2188bf80f4bSopenharmony_ci } 2198bf80f4bSopenharmony_ci list->second.push_back(&listener); 2208bf80f4bSopenharmony_ci return; 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci componentManagerListeners_[&manager].push_back(&listener); 2238bf80f4bSopenharmony_ci} 2248bf80f4bSopenharmony_ci 2258bf80f4bSopenharmony_civoid Ecs::RemoveListener(IComponentManager& manager, ComponentListener& listener) 2268bf80f4bSopenharmony_ci{ 2278bf80f4bSopenharmony_ci auto list = componentManagerListeners_.find(&manager); 2288bf80f4bSopenharmony_ci if (list == componentManagerListeners_.end()) { 2298bf80f4bSopenharmony_ci return; 2308bf80f4bSopenharmony_ci } 2318bf80f4bSopenharmony_ci if (auto it = Find(list->second, &listener); it != list->second.end()) { 2328bf80f4bSopenharmony_ci *it = nullptr; 2338bf80f4bSopenharmony_ci return; 2348bf80f4bSopenharmony_ci } 2358bf80f4bSopenharmony_ci} 2368bf80f4bSopenharmony_ci 2378bf80f4bSopenharmony_ciIComponentManager* Ecs::CreateComponentManager(const ComponentManagerTypeInfo& componentManagerTypeInfo) 2388bf80f4bSopenharmony_ci{ 2398bf80f4bSopenharmony_ci IComponentManager* manager = nullptr; 2408bf80f4bSopenharmony_ci if (componentManagerTypeInfo.createManager) { 2418bf80f4bSopenharmony_ci manager = GetComponentManager(componentManagerTypeInfo.UID); 2428bf80f4bSopenharmony_ci if (manager) { 2438bf80f4bSopenharmony_ci CORE_LOG_W("Duplicate component manager creation, returning existing instance"); 2448bf80f4bSopenharmony_ci } else { 2458bf80f4bSopenharmony_ci manager = componentManagerTypeInfo.createManager(*this); 2468bf80f4bSopenharmony_ci if (manager) { 2478bf80f4bSopenharmony_ci managers_.insert({ componentManagerTypeInfo.uid, manager }); 2488bf80f4bSopenharmony_ci managerOrder_.emplace_back(manager, componentManagerTypeInfo.destroyManager); 2498bf80f4bSopenharmony_ci } 2508bf80f4bSopenharmony_ci } 2518bf80f4bSopenharmony_ci } 2528bf80f4bSopenharmony_ci return manager; 2538bf80f4bSopenharmony_ci} 2548bf80f4bSopenharmony_ci 2558bf80f4bSopenharmony_ciISystem* Ecs::CreateSystem(const SystemTypeInfo& systemInfo) 2568bf80f4bSopenharmony_ci{ 2578bf80f4bSopenharmony_ci ISystem* system = nullptr; 2588bf80f4bSopenharmony_ci if (systemInfo.createSystem) { 2598bf80f4bSopenharmony_ci system = GetSystem(systemInfo.UID); 2608bf80f4bSopenharmony_ci if (system) { 2618bf80f4bSopenharmony_ci CORE_LOG_W("Duplicate system creation, returning existing instance"); 2628bf80f4bSopenharmony_ci } else { 2638bf80f4bSopenharmony_ci system = systemInfo.createSystem(*this); 2648bf80f4bSopenharmony_ci if (system) { 2658bf80f4bSopenharmony_ci systems_.insert({ systemInfo.uid, system }); 2668bf80f4bSopenharmony_ci systemOrder_.emplace_back(system, systemInfo.destroySystem); 2678bf80f4bSopenharmony_ci } 2688bf80f4bSopenharmony_ci } 2698bf80f4bSopenharmony_ci } 2708bf80f4bSopenharmony_ci return system; 2718bf80f4bSopenharmony_ci} 2728bf80f4bSopenharmony_ci 2738bf80f4bSopenharmony_ciEcs::Ecs(IClassFactory& registry, const IThreadPool::Ptr& threadPool) 2748bf80f4bSopenharmony_ci : threadPool_(threadPool), pluginRegistry_(registry) 2758bf80f4bSopenharmony_ci{ 2768bf80f4bSopenharmony_ci for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(IEcsPlugin::UID)) { 2778bf80f4bSopenharmony_ci if (auto ecsPlugin = static_cast<const IEcsPlugin*>(info); ecsPlugin && ecsPlugin->createPlugin) { 2788bf80f4bSopenharmony_ci auto token = ecsPlugin->createPlugin(*this); 2798bf80f4bSopenharmony_ci plugins_.push_back({ token, ecsPlugin }); 2808bf80f4bSopenharmony_ci } 2818bf80f4bSopenharmony_ci } 2828bf80f4bSopenharmony_ci GetPluginRegister().AddListener(*this); 2838bf80f4bSopenharmony_ci} 2848bf80f4bSopenharmony_ci 2858bf80f4bSopenharmony_ciEcs::~Ecs() 2868bf80f4bSopenharmony_ci{ 2878bf80f4bSopenharmony_ci GetPluginRegister().RemoveListener(*this); 2888bf80f4bSopenharmony_ci 2898bf80f4bSopenharmony_ci Uninitialize(); 2908bf80f4bSopenharmony_ci managerOrder_.clear(); 2918bf80f4bSopenharmony_ci systemOrder_.clear(); 2928bf80f4bSopenharmony_ci 2938bf80f4bSopenharmony_ci for (auto& plugin : plugins_) { 2948bf80f4bSopenharmony_ci if (plugin.second->destroyPlugin) { 2958bf80f4bSopenharmony_ci plugin.second->destroyPlugin(plugin.first); 2968bf80f4bSopenharmony_ci } 2978bf80f4bSopenharmony_ci } 2988bf80f4bSopenharmony_ci} 2998bf80f4bSopenharmony_ci 3008bf80f4bSopenharmony_ciIClassFactory& Ecs::GetClassFactory() const 3018bf80f4bSopenharmony_ci{ 3028bf80f4bSopenharmony_ci return pluginRegistry_; 3038bf80f4bSopenharmony_ci} 3048bf80f4bSopenharmony_ci 3058bf80f4bSopenharmony_ciIEntityManager& Ecs::GetEntityManager() 3068bf80f4bSopenharmony_ci{ 3078bf80f4bSopenharmony_ci return entityManager_; 3088bf80f4bSopenharmony_ci} 3098bf80f4bSopenharmony_ci 3108bf80f4bSopenharmony_civoid Ecs::GetComponents(Entity entity, vector<IComponentManager*>& result) 3118bf80f4bSopenharmony_ci{ 3128bf80f4bSopenharmony_ci result.clear(); 3138bf80f4bSopenharmony_ci result.reserve(managers_.size()); 3148bf80f4bSopenharmony_ci for (auto& m : managerOrder_) { 3158bf80f4bSopenharmony_ci if (m->HasComponent(entity)) { 3168bf80f4bSopenharmony_ci result.push_back(m.get()); 3178bf80f4bSopenharmony_ci } 3188bf80f4bSopenharmony_ci } 3198bf80f4bSopenharmony_ci} 3208bf80f4bSopenharmony_ci 3218bf80f4bSopenharmony_civector<ISystem*> Ecs::GetSystems() const 3228bf80f4bSopenharmony_ci{ 3238bf80f4bSopenharmony_ci vector<ISystem*> result; 3248bf80f4bSopenharmony_ci result.reserve(systemOrder_.size()); 3258bf80f4bSopenharmony_ci for (auto& t : systemOrder_) { 3268bf80f4bSopenharmony_ci result.push_back(t.get()); 3278bf80f4bSopenharmony_ci } 3288bf80f4bSopenharmony_ci return result; 3298bf80f4bSopenharmony_ci} 3308bf80f4bSopenharmony_ci 3318bf80f4bSopenharmony_ciISystem* Ecs::GetSystem(const Uid& uid) const 3328bf80f4bSopenharmony_ci{ 3338bf80f4bSopenharmony_ci if (auto pos = systems_.find(uid); pos != systems_.end()) { 3348bf80f4bSopenharmony_ci return pos->second; 3358bf80f4bSopenharmony_ci } 3368bf80f4bSopenharmony_ci return nullptr; 3378bf80f4bSopenharmony_ci} 3388bf80f4bSopenharmony_ci 3398bf80f4bSopenharmony_civector<IComponentManager*> Ecs::GetComponentManagers() const 3408bf80f4bSopenharmony_ci{ 3418bf80f4bSopenharmony_ci vector<IComponentManager*> result; 3428bf80f4bSopenharmony_ci result.reserve(managerOrder_.size()); 3438bf80f4bSopenharmony_ci for (auto& t : managerOrder_) { 3448bf80f4bSopenharmony_ci result.push_back(t.get()); 3458bf80f4bSopenharmony_ci } 3468bf80f4bSopenharmony_ci return result; 3478bf80f4bSopenharmony_ci} 3488bf80f4bSopenharmony_ci 3498bf80f4bSopenharmony_ciIComponentManager* Ecs::GetComponentManager(const Uid& uid) const 3508bf80f4bSopenharmony_ci{ 3518bf80f4bSopenharmony_ci if (auto pos = managers_.find(uid); pos != managers_.end()) { 3528bf80f4bSopenharmony_ci return pos->second; 3538bf80f4bSopenharmony_ci } 3548bf80f4bSopenharmony_ci return nullptr; 3558bf80f4bSopenharmony_ci} 3568bf80f4bSopenharmony_ci 3578bf80f4bSopenharmony_ciEntity Ecs::CloneEntity(const Entity entity) 3588bf80f4bSopenharmony_ci{ 3598bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(entity)) { 3608bf80f4bSopenharmony_ci return Entity(); 3618bf80f4bSopenharmony_ci } 3628bf80f4bSopenharmony_ci 3638bf80f4bSopenharmony_ci const Entity clonedEntity = entityManager_.Create(); 3648bf80f4bSopenharmony_ci if (entityManager_.IsAlive(entity)) { 3658bf80f4bSopenharmony_ci for (auto& cm : managerOrder_) { 3668bf80f4bSopenharmony_ci const auto id = cm->GetComponentId(entity); 3678bf80f4bSopenharmony_ci if (id != IComponentManager::INVALID_COMPONENT_ID) { 3688bf80f4bSopenharmony_ci cm->Create(clonedEntity); 3698bf80f4bSopenharmony_ci cm->SetData(clonedEntity, *cm->GetData(id)); 3708bf80f4bSopenharmony_ci } 3718bf80f4bSopenharmony_ci } 3728bf80f4bSopenharmony_ci } 3738bf80f4bSopenharmony_ci return clonedEntity; 3748bf80f4bSopenharmony_ci} 3758bf80f4bSopenharmony_ci 3768bf80f4bSopenharmony_civoid Ecs::ProcessComponentEvents( 3778bf80f4bSopenharmony_ci ComponentListener::EventType eventType, const array_view<const Entity> removedEntities) const 3788bf80f4bSopenharmony_ci{ 3798bf80f4bSopenharmony_ci vector<Entity> (IComponentManager::*getter)(); 3808bf80f4bSopenharmony_ci switch (eventType) { 3818bf80f4bSopenharmony_ci case ComponentListener::EventType::CREATED: 3828bf80f4bSopenharmony_ci getter = &IComponentManager::GetAddedComponents; 3838bf80f4bSopenharmony_ci break; 3848bf80f4bSopenharmony_ci case ComponentListener::EventType::MODIFIED: 3858bf80f4bSopenharmony_ci getter = &IComponentManager::GetUpdatedComponents; 3868bf80f4bSopenharmony_ci break; 3878bf80f4bSopenharmony_ci case ComponentListener::EventType::DESTROYED: 3888bf80f4bSopenharmony_ci getter = &IComponentManager::GetRemovedComponents; 3898bf80f4bSopenharmony_ci break; 3908bf80f4bSopenharmony_ci default: 3918bf80f4bSopenharmony_ci return; 3928bf80f4bSopenharmony_ci } 3938bf80f4bSopenharmony_ci for (const auto& m : managerOrder_) { 3948bf80f4bSopenharmony_ci vector<Entity> affectedEntities = (*m.*getter)(); 3958bf80f4bSopenharmony_ci if (!removedEntities.empty()) { 3968bf80f4bSopenharmony_ci affectedEntities.erase( 3978bf80f4bSopenharmony_ci std::remove_if(affectedEntities.begin(), affectedEntities.end(), 3988bf80f4bSopenharmony_ci [removedEntities](const Entity& entity) { 3998bf80f4bSopenharmony_ci const auto pos = std::lower_bound(removedEntities.cbegin(), removedEntities.cend(), entity, 4008bf80f4bSopenharmony_ci [](const Entity& entity, const Entity& removed) { return entity.id < removed.id; }); 4018bf80f4bSopenharmony_ci return ((pos != removedEntities.cend()) && !(entity.id < pos->id)); 4028bf80f4bSopenharmony_ci }), 4038bf80f4bSopenharmony_ci affectedEntities.cend()); 4048bf80f4bSopenharmony_ci } 4058bf80f4bSopenharmony_ci if (!affectedEntities.empty()) { 4068bf80f4bSopenharmony_ci // global listeners 4078bf80f4bSopenharmony_ci for (auto* listener : componentListeners_) { 4088bf80f4bSopenharmony_ci if (listener) { 4098bf80f4bSopenharmony_ci listener->OnComponentEvent(eventType, *m, affectedEntities); 4108bf80f4bSopenharmony_ci } 4118bf80f4bSopenharmony_ci } 4128bf80f4bSopenharmony_ci // per manager listeners 4138bf80f4bSopenharmony_ci if (auto it = componentManagerListeners_.find(m.get()); it != componentManagerListeners_.cend()) { 4148bf80f4bSopenharmony_ci for (auto* listener : it->second) { 4158bf80f4bSopenharmony_ci if (listener) { 4168bf80f4bSopenharmony_ci listener->OnComponentEvent(eventType, *m, affectedEntities); 4178bf80f4bSopenharmony_ci } 4188bf80f4bSopenharmony_ci } 4198bf80f4bSopenharmony_ci } 4208bf80f4bSopenharmony_ci } 4218bf80f4bSopenharmony_ci } 4228bf80f4bSopenharmony_ci} 4238bf80f4bSopenharmony_ci 4248bf80f4bSopenharmony_civoid Ecs::ProcessEvents() 4258bf80f4bSopenharmony_ci{ 4268bf80f4bSopenharmony_ci if (processingEvents_) { 4278bf80f4bSopenharmony_ci CORE_ASSERT_MSG(false, "Calling ProcessEvents() from an event callback is not allowed"); 4288bf80f4bSopenharmony_ci return; 4298bf80f4bSopenharmony_ci } 4308bf80f4bSopenharmony_ci processingEvents_ = true; 4318bf80f4bSopenharmony_ci 4328bf80f4bSopenharmony_ci vector<Entity> allRemovedEntities; 4338bf80f4bSopenharmony_ci bool deadEntities = false; 4348bf80f4bSopenharmony_ci do { 4358bf80f4bSopenharmony_ci // Let entity manager check entity reference counts 4368bf80f4bSopenharmony_ci entityManager_.UpdateDeadEntities(); 4378bf80f4bSopenharmony_ci 4388bf80f4bSopenharmony_ci // Send entity related events 4398bf80f4bSopenharmony_ci if (const auto events = entityManager_.GetEvents(); !events.empty()) { 4408bf80f4bSopenharmony_ci ProcessEntityListeners(events, entityListeners_); 4418bf80f4bSopenharmony_ci } 4428bf80f4bSopenharmony_ci 4438bf80f4bSopenharmony_ci // Remove components for removed entities. 4448bf80f4bSopenharmony_ci const vector<Entity> removed = entityManager_.GetRemovedEntities(); 4458bf80f4bSopenharmony_ci deadEntities = !removed.empty(); 4468bf80f4bSopenharmony_ci if (deadEntities) { 4478bf80f4bSopenharmony_ci allRemovedEntities.append(removed.cbegin(), removed.cend()); 4488bf80f4bSopenharmony_ci } 4498bf80f4bSopenharmony_ci for (auto& m : managerOrder_) { 4508bf80f4bSopenharmony_ci // Destroy all components related to these entities. 4518bf80f4bSopenharmony_ci if (deadEntities) { 4528bf80f4bSopenharmony_ci m->Destroy(removed); 4538bf80f4bSopenharmony_ci } 4548bf80f4bSopenharmony_ci m->Gc(); 4558bf80f4bSopenharmony_ci } 4568bf80f4bSopenharmony_ci // Destroying components may release the last reference for some entity so we loop until there are no new 4578bf80f4bSopenharmony_ci // deaths reported. 4588bf80f4bSopenharmony_ci } while (deadEntities); 4598bf80f4bSopenharmony_ci 4608bf80f4bSopenharmony_ci if (!allRemovedEntities.empty()) { 4618bf80f4bSopenharmony_ci std::sort(allRemovedEntities.begin(), allRemovedEntities.end(), 4628bf80f4bSopenharmony_ci [](const Entity& lhs, const Entity& rhs) { return lhs.id < rhs.id; }); 4638bf80f4bSopenharmony_ci } 4648bf80f4bSopenharmony_ci 4658bf80f4bSopenharmony_ci // Send component related events 4668bf80f4bSopenharmony_ci ProcessComponentEvents(ComponentListener::EventType::CREATED, allRemovedEntities); 4678bf80f4bSopenharmony_ci ProcessComponentEvents(ComponentListener::EventType::MODIFIED, allRemovedEntities); 4688bf80f4bSopenharmony_ci ProcessComponentEvents(ComponentListener::EventType::DESTROYED, {}); 4698bf80f4bSopenharmony_ci 4708bf80f4bSopenharmony_ci // Clean-up removed listeners. 4718bf80f4bSopenharmony_ci entityListeners_.erase( 4728bf80f4bSopenharmony_ci std::remove(entityListeners_.begin(), entityListeners_.end(), nullptr), entityListeners_.cend()); 4738bf80f4bSopenharmony_ci componentListeners_.erase( 4748bf80f4bSopenharmony_ci std::remove(componentListeners_.begin(), componentListeners_.end(), nullptr), componentListeners_.cend()); 4758bf80f4bSopenharmony_ci 4768bf80f4bSopenharmony_ci for (auto it = componentManagerListeners_.begin(); it != componentManagerListeners_.cend();) { 4778bf80f4bSopenharmony_ci auto& listeners = it->second; 4788bf80f4bSopenharmony_ci listeners.erase(std::remove(listeners.begin(), listeners.end(), nullptr), listeners.cend()); 4798bf80f4bSopenharmony_ci if (listeners.empty()) { 4808bf80f4bSopenharmony_ci it = componentManagerListeners_.erase(it); 4818bf80f4bSopenharmony_ci } else { 4828bf80f4bSopenharmony_ci ++it; 4838bf80f4bSopenharmony_ci } 4848bf80f4bSopenharmony_ci } 4858bf80f4bSopenharmony_ci 4868bf80f4bSopenharmony_ci processingEvents_ = false; 4878bf80f4bSopenharmony_ci} 4888bf80f4bSopenharmony_ci 4898bf80f4bSopenharmony_civoid Ecs::Initialize() 4908bf80f4bSopenharmony_ci{ 4918bf80f4bSopenharmony_ci for (auto& s : systemOrder_) { 4928bf80f4bSopenharmony_ci s->Initialize(); 4938bf80f4bSopenharmony_ci } 4948bf80f4bSopenharmony_ci} 4958bf80f4bSopenharmony_ci 4968bf80f4bSopenharmony_cibool Ecs::Update(uint64_t time, uint64_t delta) 4978bf80f4bSopenharmony_ci{ 4988bf80f4bSopenharmony_ci CORE_CPU_PERF_SCOPE("ECS", "Update", "Total_Cpu"); 4998bf80f4bSopenharmony_ci 5008bf80f4bSopenharmony_ci bool frameRenderingQueued = false; 5018bf80f4bSopenharmony_ci if (GetRenderMode() == RENDER_ALWAYS || renderRequested_) { 5028bf80f4bSopenharmony_ci frameRenderingQueued = true; 5038bf80f4bSopenharmony_ci } 5048bf80f4bSopenharmony_ci 5058bf80f4bSopenharmony_ci // Update all systems. 5068bf80f4bSopenharmony_ci delta = static_cast<uint64_t>(static_cast<float>(delta) * timeScale_); 5078bf80f4bSopenharmony_ci for (auto& s : systemOrder_) { 5088bf80f4bSopenharmony_ci CORE_CPU_PERF_SCOPE("ECS", "SystemUpdate_Cpu", s->GetName()); 5098bf80f4bSopenharmony_ci if (s->Update(frameRenderingQueued, time, delta)) { 5108bf80f4bSopenharmony_ci frameRenderingQueued = true; 5118bf80f4bSopenharmony_ci } 5128bf80f4bSopenharmony_ci } 5138bf80f4bSopenharmony_ci 5148bf80f4bSopenharmony_ci // Clear modification flags from component managers. 5158bf80f4bSopenharmony_ci for (auto& componentManager : managerOrder_) { 5168bf80f4bSopenharmony_ci componentManager->ClearModifiedFlags(); 5178bf80f4bSopenharmony_ci } 5188bf80f4bSopenharmony_ci 5198bf80f4bSopenharmony_ci renderRequested_ = false; 5208bf80f4bSopenharmony_ci needRender_ = frameRenderingQueued; 5218bf80f4bSopenharmony_ci 5228bf80f4bSopenharmony_ci return frameRenderingQueued; 5238bf80f4bSopenharmony_ci} 5248bf80f4bSopenharmony_ci 5258bf80f4bSopenharmony_civoid Ecs::Uninitialize() 5268bf80f4bSopenharmony_ci{ 5278bf80f4bSopenharmony_ci // Destroy all entities from scene. 5288bf80f4bSopenharmony_ci entityManager_.DestroyAllEntities(); 5298bf80f4bSopenharmony_ci 5308bf80f4bSopenharmony_ci // Garbage-collect. 5318bf80f4bSopenharmony_ci ProcessEvents(); 5328bf80f4bSopenharmony_ci 5338bf80f4bSopenharmony_ci // Uninitialize systems. 5348bf80f4bSopenharmony_ci for (auto it = systemOrder_.rbegin(); it != systemOrder_.rend(); ++it) { 5358bf80f4bSopenharmony_ci (*it)->Uninitialize(); 5368bf80f4bSopenharmony_ci } 5378bf80f4bSopenharmony_ci} 5388bf80f4bSopenharmony_ci 5398bf80f4bSopenharmony_civoid Ecs::RequestRender() 5408bf80f4bSopenharmony_ci{ 5418bf80f4bSopenharmony_ci renderRequested_ = true; 5428bf80f4bSopenharmony_ci} 5438bf80f4bSopenharmony_ci 5448bf80f4bSopenharmony_civoid Ecs::SetRenderMode(RenderMode renderMode) 5458bf80f4bSopenharmony_ci{ 5468bf80f4bSopenharmony_ci renderMode_ = renderMode; 5478bf80f4bSopenharmony_ci} 5488bf80f4bSopenharmony_ci 5498bf80f4bSopenharmony_ciIEcs::RenderMode Ecs::GetRenderMode() 5508bf80f4bSopenharmony_ci{ 5518bf80f4bSopenharmony_ci return renderMode_; 5528bf80f4bSopenharmony_ci} 5538bf80f4bSopenharmony_ci 5548bf80f4bSopenharmony_cibool Ecs::NeedRender() const 5558bf80f4bSopenharmony_ci{ 5568bf80f4bSopenharmony_ci return needRender_; 5578bf80f4bSopenharmony_ci} 5588bf80f4bSopenharmony_ci 5598bf80f4bSopenharmony_ciconst IThreadPool::Ptr& Ecs::GetThreadPool() const 5608bf80f4bSopenharmony_ci{ 5618bf80f4bSopenharmony_ci return threadPool_; 5628bf80f4bSopenharmony_ci} 5638bf80f4bSopenharmony_ci 5648bf80f4bSopenharmony_cifloat Ecs::GetTimeScale() const 5658bf80f4bSopenharmony_ci{ 5668bf80f4bSopenharmony_ci return timeScale_; 5678bf80f4bSopenharmony_ci} 5688bf80f4bSopenharmony_ci 5698bf80f4bSopenharmony_civoid Ecs::SetTimeScale(float scale) 5708bf80f4bSopenharmony_ci{ 5718bf80f4bSopenharmony_ci timeScale_ = scale; 5728bf80f4bSopenharmony_ci} 5738bf80f4bSopenharmony_ci 5748bf80f4bSopenharmony_civoid Ecs::Ref() noexcept 5758bf80f4bSopenharmony_ci{ 5768bf80f4bSopenharmony_ci refcnt_.fetch_add(1, std::memory_order_relaxed); 5778bf80f4bSopenharmony_ci} 5788bf80f4bSopenharmony_ci 5798bf80f4bSopenharmony_civoid Ecs::Unref() noexcept 5808bf80f4bSopenharmony_ci{ 5818bf80f4bSopenharmony_ci if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 1) { 5828bf80f4bSopenharmony_ci std::atomic_thread_fence(std::memory_order_acquire); 5838bf80f4bSopenharmony_ci delete this; 5848bf80f4bSopenharmony_ci } 5858bf80f4bSopenharmony_ci} 5868bf80f4bSopenharmony_ci 5878bf80f4bSopenharmony_citemplate<typename Container> 5888bf80f4bSopenharmony_ciinline auto RemoveUid(Container& container, const Uid& uid) 5898bf80f4bSopenharmony_ci{ 5908bf80f4bSopenharmony_ci container.erase(std::remove_if(container.begin(), container.end(), 5918bf80f4bSopenharmony_ci [&uid](const auto& thing) { return thing->GetUid() == uid; }), 5928bf80f4bSopenharmony_ci container.cend()); 5938bf80f4bSopenharmony_ci} 5948bf80f4bSopenharmony_ci 5958bf80f4bSopenharmony_civoid Ecs::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos) 5968bf80f4bSopenharmony_ci{ 5978bf80f4bSopenharmony_ci if (type == EventType::ADDED) { 5988bf80f4bSopenharmony_ci // not really interesed in these events. systems and component managers are added when SystemGraphLoader parses 5998bf80f4bSopenharmony_ci // a configuration. we could store them in systems_ and managers_ and only define the order based on the graph. 6008bf80f4bSopenharmony_ci } else if (type == EventType::REMOVED) { 6018bf80f4bSopenharmony_ci for (const auto* info : typeInfos) { 6028bf80f4bSopenharmony_ci if (info && info->typeUid == SystemTypeInfo::UID) { 6038bf80f4bSopenharmony_ci const auto systemInfo = static_cast<const SystemTypeInfo*>(info); 6048bf80f4bSopenharmony_ci // for systems Untinitialize should be called before destroying the instance 6058bf80f4bSopenharmony_ci if (const auto pos = systems_.find(systemInfo->uid); pos != systems_.cend()) { 6068bf80f4bSopenharmony_ci pos->second->Uninitialize(); 6078bf80f4bSopenharmony_ci systems_.erase(pos); 6088bf80f4bSopenharmony_ci } 6098bf80f4bSopenharmony_ci RemoveUid(systemOrder_, systemInfo->uid); 6108bf80f4bSopenharmony_ci } else if (info && info->typeUid == ComponentManagerTypeInfo::UID) { 6118bf80f4bSopenharmony_ci const auto managerInfo = static_cast<const ComponentManagerTypeInfo*>(info); 6128bf80f4bSopenharmony_ci // BaseManager expects that the component list is empty when it's destroyed. might be also 6138bf80f4bSopenharmony_ci // nice to notify all the listeners that the components are being destroyed. 6148bf80f4bSopenharmony_ci if (const auto pos = managers_.find(managerInfo->uid); pos != managers_.end()) { 6158bf80f4bSopenharmony_ci auto* manager = pos->second; 6168bf80f4bSopenharmony_ci 6178bf80f4bSopenharmony_ci // remove all the components. 6188bf80f4bSopenharmony_ci const auto components = static_cast<IComponentManager::ComponentId>(manager->GetComponentCount()); 6198bf80f4bSopenharmony_ci for (IComponentManager::ComponentId i = 0; i < components; ++i) { 6208bf80f4bSopenharmony_ci manager->Destroy(manager->GetEntity(i)); 6218bf80f4bSopenharmony_ci } 6228bf80f4bSopenharmony_ci 6238bf80f4bSopenharmony_ci // check are there generic or specific component listeners to inform. 6248bf80f4bSopenharmony_ci if (const auto listenerIt = componentManagerListeners_.find(manager); 6258bf80f4bSopenharmony_ci !componentListeners_.empty() || 6268bf80f4bSopenharmony_ci ((listenerIt != componentManagerListeners_.end()) && !listenerIt->second.empty())) { 6278bf80f4bSopenharmony_ci if (const vector<Entity> removed = manager->GetRemovedComponents(); !removed.empty()) { 6288bf80f4bSopenharmony_ci const auto removedView = array_view<const Entity>(removed); 6298bf80f4bSopenharmony_ci for (auto* lister : componentListeners_) { 6308bf80f4bSopenharmony_ci if (lister) { 6318bf80f4bSopenharmony_ci lister->OnComponentEvent( 6328bf80f4bSopenharmony_ci ComponentListener::EventType::DESTROYED, *manager, removedView); 6338bf80f4bSopenharmony_ci } 6348bf80f4bSopenharmony_ci } 6358bf80f4bSopenharmony_ci if (listenerIt != componentManagerListeners_.end()) { 6368bf80f4bSopenharmony_ci for (auto* lister : listenerIt->second) { 6378bf80f4bSopenharmony_ci if (lister) { 6388bf80f4bSopenharmony_ci lister->OnComponentEvent( 6398bf80f4bSopenharmony_ci ComponentListener::EventType::DESTROYED, *manager, removedView); 6408bf80f4bSopenharmony_ci } 6418bf80f4bSopenharmony_ci } 6428bf80f4bSopenharmony_ci // remove all the listeners for this manager. RemoveListener won't do anything. this 6438bf80f4bSopenharmony_ci // isn't neccessary, but rather not leave invalid manager pointer even if it's just used 6448bf80f4bSopenharmony_ci // as the key. 6458bf80f4bSopenharmony_ci componentManagerListeners_.erase(listenerIt); 6468bf80f4bSopenharmony_ci } 6478bf80f4bSopenharmony_ci } 6488bf80f4bSopenharmony_ci } 6498bf80f4bSopenharmony_ci // garbage collection will remove dead entries from the list and BaseManager is happy. 6508bf80f4bSopenharmony_ci manager->Gc(); 6518bf80f4bSopenharmony_ci managers_.erase(pos); 6528bf80f4bSopenharmony_ci } 6538bf80f4bSopenharmony_ci RemoveUid(managerOrder_, managerInfo->uid); 6548bf80f4bSopenharmony_ci } 6558bf80f4bSopenharmony_ci } 6568bf80f4bSopenharmony_ci } 6578bf80f4bSopenharmony_ci} 6588bf80f4bSopenharmony_ci} // namespace 6598bf80f4bSopenharmony_ci 6608bf80f4bSopenharmony_ciIEcs* IEcsInstance(IClassFactory& registry, const IThreadPool::Ptr& threadPool) 6618bf80f4bSopenharmony_ci{ 6628bf80f4bSopenharmony_ci return new Ecs(registry, threadPool); 6638bf80f4bSopenharmony_ci} 6648bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 665