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