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 "engine.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <chrono>
208bf80f4bSopenharmony_ci#include <cstring>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include <base/containers/array_view.h>
238bf80f4bSopenharmony_ci#include <base/containers/iterator.h>
248bf80f4bSopenharmony_ci#include <base/containers/refcnt_ptr.h>
258bf80f4bSopenharmony_ci#include <base/containers/string.h>
268bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
278bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
288bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h>
298bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
308bf80f4bSopenharmony_ci#include <base/containers/vector.h>
318bf80f4bSopenharmony_ci#include <base/namespace.h>
328bf80f4bSopenharmony_ci#include <base/util/uid.h>
338bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h>
348bf80f4bSopenharmony_ci#include <core/engine_info.h>
358bf80f4bSopenharmony_ci#include <core/implementation_uids.h>
368bf80f4bSopenharmony_ci#include <core/intf_engine.h>
378bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
388bf80f4bSopenharmony_ci#include <core/io/intf_filesystem_api.h>
398bf80f4bSopenharmony_ci#include <core/log.h>
408bf80f4bSopenharmony_ci#include <core/namespace.h>
418bf80f4bSopenharmony_ci#include <core/os/intf_platform.h>
428bf80f4bSopenharmony_ci#include <core/plugin/intf_class_factory.h>
438bf80f4bSopenharmony_ci#include <core/plugin/intf_class_register.h>
448bf80f4bSopenharmony_ci#include <core/plugin/intf_interface.h>
458bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin.h>
468bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin_register.h>
478bf80f4bSopenharmony_ci#include <core/threading/intf_thread_pool.h>
488bf80f4bSopenharmony_ci
498bf80f4bSopenharmony_ci#include "image/image_loader_manager.h"
508bf80f4bSopenharmony_ci#include "image/loaders/image_loader_ktx.h"
518bf80f4bSopenharmony_ci#include "image/loaders/image_loader_stb_image.h"
528bf80f4bSopenharmony_ci#include "os/platform.h"
538bf80f4bSopenharmony_ci
548bf80f4bSopenharmony_ci#if (CORE_PERF_ENABLED == 1)
558bf80f4bSopenharmony_ci#include "perf/performance_data_manager.h"
568bf80f4bSopenharmony_ci#endif
578bf80f4bSopenharmony_ci
588bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE()
598bf80f4bSopenharmony_cinamespace {
608bf80f4bSopenharmony_ci#if (CORE_EMBEDDED_ASSETS_ENABLED == 1)
618bf80f4bSopenharmony_ci// Core Rofs Data.
628bf80f4bSopenharmony_ciextern "C" const uint64_t SIZEOFDATAFORCORE;
638bf80f4bSopenharmony_ciextern "C" const void* const BINARYDATAFORCORE[];
648bf80f4bSopenharmony_ci#endif
658bf80f4bSopenharmony_ci
668bf80f4bSopenharmony_ciusing BASE_NS::array_view;
678bf80f4bSopenharmony_ciusing BASE_NS::make_unique;
688bf80f4bSopenharmony_ciusing BASE_NS::pair;
698bf80f4bSopenharmony_ciusing BASE_NS::string;
708bf80f4bSopenharmony_ciusing BASE_NS::string_view;
718bf80f4bSopenharmony_ciusing BASE_NS::Uid;
728bf80f4bSopenharmony_ci
738bf80f4bSopenharmony_ci// This is defined in the CMake generated version.cpp
748bf80f4bSopenharmony_civoid LogEngineBuildInfo()
758bf80f4bSopenharmony_ci{
768bf80f4bSopenharmony_ci#define CORE_TO_STRING_INTERNAL(x) #x
778bf80f4bSopenharmony_ci#define CORE_TO_STRING(x) CORE_TO_STRING_INTERNAL(x)
788bf80f4bSopenharmony_ci
798bf80f4bSopenharmony_ci#ifdef NDEBUG
808bf80f4bSopenharmony_ci    CORE_LOG_I("Core engine version: %s", GetVersion().data());
818bf80f4bSopenharmony_ci#else
828bf80f4bSopenharmony_ci    CORE_LOG_I("Version: %s (DEBUG)", GetVersion().data());
838bf80f4bSopenharmony_ci#endif
848bf80f4bSopenharmony_ci
858bf80f4bSopenharmony_ci    CORE_LOG_I("CORE_VALIDATION_ENABLED=" CORE_TO_STRING(CORE_VALIDATION_ENABLED));
868bf80f4bSopenharmony_ci    CORE_LOG_I("CORE_DEV_ENABLED=" CORE_TO_STRING(CORE_DEV_ENABLED));
878bf80f4bSopenharmony_ci}
888bf80f4bSopenharmony_ci} // namespace
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_ciEngine::Engine(EngineCreateInfo const& createInfo)
918bf80f4bSopenharmony_ci    : platform_(Platform::Create(createInfo.platformCreateInfo)), applicationContext_(createInfo.applicationContext)
928bf80f4bSopenharmony_ci{
938bf80f4bSopenharmony_ci    LogEngineBuildInfo();
948bf80f4bSopenharmony_ci    auto factory = CORE_NS::GetInstance<IFileSystemApi>(UID_FILESYSTEM_API_FACTORY);
958bf80f4bSopenharmony_ci    fileManager_ = factory->CreateFilemanager();
968bf80f4bSopenharmony_ci    fileManager_->RegisterFilesystem("file", factory->CreateStdFileSystem());
978bf80f4bSopenharmony_ci    fileManager_->RegisterFilesystem("memory", factory->CreateMemFileSystem());
988bf80f4bSopenharmony_ci#if (CORE_EMBEDDED_ASSETS_ENABLED == 1)
998bf80f4bSopenharmony_ci    fileManager_->RegisterFilesystem(
1008bf80f4bSopenharmony_ci        "corerofs", factory->CreateROFilesystem(BINARYDATAFORCORE, static_cast<size_t>(SIZEOFDATAFORCORE)));
1018bf80f4bSopenharmony_ci#endif
1028bf80f4bSopenharmony_ci
1038bf80f4bSopenharmony_ci    RegisterDefaultPaths();
1048bf80f4bSopenharmony_ci}
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_ciEngine::~Engine()
1078bf80f4bSopenharmony_ci{
1088bf80f4bSopenharmony_ci    GetPluginRegister().RemoveListener(*this);
1098bf80f4bSopenharmony_ci
1108bf80f4bSopenharmony_ci#if (CORE_PERF_ENABLED == 1)
1118bf80f4bSopenharmony_ci    if (auto perfFactory = CORE_NS::GetInstance<IPerformanceDataManagerFactory>(UID_PERFORMANCE_FACTORY); perfFactory) {
1128bf80f4bSopenharmony_ci        for (const auto& perfMan : perfFactory->GetAllCategories()) {
1138bf80f4bSopenharmony_ci            CORE_LOG_I("%s PerformanceData for this run:", perfMan->GetCategory().data());
1148bf80f4bSopenharmony_ci            static_cast<const PerformanceDataManager&>(*perfMan).DumpToLog();
1158bf80f4bSopenharmony_ci        }
1168bf80f4bSopenharmony_ci    }
1178bf80f4bSopenharmony_ci#endif
1188bf80f4bSopenharmony_ci
1198bf80f4bSopenharmony_ci    UnloadPlugins();
1208bf80f4bSopenharmony_ci
1218bf80f4bSopenharmony_ci    fileManager_.reset();
1228bf80f4bSopenharmony_ci}
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_ciCORE_NS::IEcs* IEcsInstance(IClassFactory&, const IThreadPool::Ptr&);
1258bf80f4bSopenharmony_ci
1268bf80f4bSopenharmony_ciIEcs::Ptr Engine::CreateEcs()
1278bf80f4bSopenharmony_ci{
1288bf80f4bSopenharmony_ci    // construct a secondary ecs instance.
1298bf80f4bSopenharmony_ci    if (auto threadFactory = CORE_NS::GetInstance<ITaskQueueFactory>(UID_TASK_QUEUE_FACTORY); threadFactory) {
1308bf80f4bSopenharmony_ci        auto threadPool = threadFactory->CreateThreadPool(threadFactory->GetNumberOfCores());
1318bf80f4bSopenharmony_ci        return IEcs::Ptr { IEcsInstance(*this, threadPool) };
1328bf80f4bSopenharmony_ci    }
1338bf80f4bSopenharmony_ci
1348bf80f4bSopenharmony_ci    return IEcs::Ptr {};
1358bf80f4bSopenharmony_ci}
1368bf80f4bSopenharmony_ci
1378bf80f4bSopenharmony_ciIEcs::Ptr Engine::CreateEcs(IThreadPool& threadPool)
1388bf80f4bSopenharmony_ci{
1398bf80f4bSopenharmony_ci    return IEcs::Ptr { IEcsInstance(*this, IThreadPool::Ptr { &threadPool }) };
1408bf80f4bSopenharmony_ci}
1418bf80f4bSopenharmony_ci
1428bf80f4bSopenharmony_civoid Engine::Init()
1438bf80f4bSopenharmony_ci{
1448bf80f4bSopenharmony_ci    CORE_LOG_D("Engine init.");
1458bf80f4bSopenharmony_ci
1468bf80f4bSopenharmony_ci    imageManager_ = make_unique<ImageLoaderManager>(*fileManager_);
1478bf80f4bSopenharmony_ci
1488bf80f4bSopenharmony_ci    // Pre-register some basic image formats.
1498bf80f4bSopenharmony_ci
1508bf80f4bSopenharmony_ci    LoadPlugins();
1518bf80f4bSopenharmony_ci
1528bf80f4bSopenharmony_ci    GetPluginRegister().AddListener(*this);
1538bf80f4bSopenharmony_ci}
1548bf80f4bSopenharmony_ci
1558bf80f4bSopenharmony_civoid Engine::RegisterDefaultPaths()
1568bf80f4bSopenharmony_ci{
1578bf80f4bSopenharmony_ci    platform_->RegisterDefaultPaths(*fileManager_);
1588bf80f4bSopenharmony_ci#if (CORE_EMBEDDED_ASSETS_ENABLED == 1)
1598bf80f4bSopenharmony_ci    // Create engine:// protocol that points to embedded engine asset files.
1608bf80f4bSopenharmony_ci    CORE_LOG_D("Registered core asset path: 'corerofs://core/'");
1618bf80f4bSopenharmony_ci    fileManager_->RegisterPath("engine", "corerofs://core/", false);
1628bf80f4bSopenharmony_ci#endif
1638bf80f4bSopenharmony_ci
1648bf80f4bSopenharmony_ci    // Create shaders:// protocol that points to shader files.
1658bf80f4bSopenharmony_ci    fileManager_->RegisterPath("shaders", "engine://shaders/", false);
1668bf80f4bSopenharmony_ci    // Create shaderstates:// protocol that points to (graphics) shader state files.
1678bf80f4bSopenharmony_ci    fileManager_->RegisterPath("shaderstates", "engine://shaderstates/", false);
1688bf80f4bSopenharmony_ci    // Create vertexinputdeclarations:// protocol that points to vid files.
1698bf80f4bSopenharmony_ci    fileManager_->RegisterPath("vertexinputdeclarations", "engine://vertexinputdeclarations/", false);
1708bf80f4bSopenharmony_ci    // Create pipelinelayouts:// protocol that points to vid files.
1718bf80f4bSopenharmony_ci    fileManager_->RegisterPath("pipelinelayouts", "engine://pipelinelayouts/", false);
1728bf80f4bSopenharmony_ci    // Create renderdataconfigurations:// protocol that points to render byteData configurations.
1738bf80f4bSopenharmony_ci    fileManager_->RegisterPath("renderdataconfigurations", "engine://renderdataconfigurations/", false);
1748bf80f4bSopenharmony_ci}
1758bf80f4bSopenharmony_ci
1768bf80f4bSopenharmony_civoid Engine::UnloadPlugins()
1778bf80f4bSopenharmony_ci{
1788bf80f4bSopenharmony_ci    for (auto& plugin : plugins_) {
1798bf80f4bSopenharmony_ci        if (plugin.second->destroyPlugin) {
1808bf80f4bSopenharmony_ci            plugin.second->destroyPlugin(plugin.first);
1818bf80f4bSopenharmony_ci        }
1828bf80f4bSopenharmony_ci    }
1838bf80f4bSopenharmony_ci}
1848bf80f4bSopenharmony_ci
1858bf80f4bSopenharmony_civoid Engine::LoadPlugins()
1868bf80f4bSopenharmony_ci{
1878bf80f4bSopenharmony_ci    for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(IEnginePlugin::UID)) {
1888bf80f4bSopenharmony_ci        if (auto enginePlugin = static_cast<const IEnginePlugin*>(info); enginePlugin && enginePlugin->createPlugin) {
1898bf80f4bSopenharmony_ci            auto token = enginePlugin->createPlugin(*this);
1908bf80f4bSopenharmony_ci            plugins_.push_back({ token, enginePlugin });
1918bf80f4bSopenharmony_ci        }
1928bf80f4bSopenharmony_ci    }
1938bf80f4bSopenharmony_ci}
1948bf80f4bSopenharmony_ci
1958bf80f4bSopenharmony_cibool Engine::TickFrame()
1968bf80f4bSopenharmony_ci{
1978bf80f4bSopenharmony_ci    return TickFrame({ nullptr, size_t(0) });
1988bf80f4bSopenharmony_ci}
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_cibool Engine::TickFrame(const array_view<IEcs*>& ecsInputs)
2018bf80f4bSopenharmony_ci{
2028bf80f4bSopenharmony_ci    using namespace std::chrono;
2038bf80f4bSopenharmony_ci    const auto currentTime =
2048bf80f4bSopenharmony_ci        static_cast<uint64_t>(duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count());
2058bf80f4bSopenharmony_ci
2068bf80f4bSopenharmony_ci    if (firstTime_ == ~0u) {
2078bf80f4bSopenharmony_ci        previousFrameTime_ = firstTime_ = currentTime;
2088bf80f4bSopenharmony_ci    }
2098bf80f4bSopenharmony_ci    deltaTime_ = currentTime - previousFrameTime_;
2108bf80f4bSopenharmony_ci    constexpr auto limitHz = duration_cast<microseconds>(duration<float, std::ratio<1, 15u>>(1)).count();
2118bf80f4bSopenharmony_ci    if (deltaTime_ > limitHz) {
2128bf80f4bSopenharmony_ci        deltaTime_ = limitHz; // clamp the time step to no longer than 15hz.
2138bf80f4bSopenharmony_ci    }
2148bf80f4bSopenharmony_ci    previousFrameTime_ = currentTime;
2158bf80f4bSopenharmony_ci
2168bf80f4bSopenharmony_ci    const uint64_t totalTime = currentTime - firstTime_;
2178bf80f4bSopenharmony_ci
2188bf80f4bSopenharmony_ci    bool needRender = false;
2198bf80f4bSopenharmony_ci    for (auto& ecs : ecsInputs) {
2208bf80f4bSopenharmony_ci        if (TickFrame(*ecs, totalTime, deltaTime_)) {
2218bf80f4bSopenharmony_ci            needRender = true;
2228bf80f4bSopenharmony_ci        }
2238bf80f4bSopenharmony_ci    }
2248bf80f4bSopenharmony_ci
2258bf80f4bSopenharmony_ci    return needRender;
2268bf80f4bSopenharmony_ci}
2278bf80f4bSopenharmony_ci
2288bf80f4bSopenharmony_cibool Engine::TickFrame(IEcs& ecs, uint64_t totalTime, uint64_t deltaTime)
2298bf80f4bSopenharmony_ci{
2308bf80f4bSopenharmony_ci    // run garbage collection before updating the systems to ensure only valid entities/ components are available.
2318bf80f4bSopenharmony_ci    ecs.ProcessEvents();
2328bf80f4bSopenharmony_ci
2338bf80f4bSopenharmony_ci    const bool needRender = ecs.Update(totalTime, deltaTime);
2348bf80f4bSopenharmony_ci
2358bf80f4bSopenharmony_ci    // do gc also after the systems have been updated to ensure any deletes done by systems are effective
2368bf80f4bSopenharmony_ci    // and client doesn't see stale entities.
2378bf80f4bSopenharmony_ci    ecs.ProcessEvents();
2388bf80f4bSopenharmony_ci
2398bf80f4bSopenharmony_ci    return needRender;
2408bf80f4bSopenharmony_ci}
2418bf80f4bSopenharmony_ci
2428bf80f4bSopenharmony_ciIImageLoaderManager& Engine::GetImageLoaderManager()
2438bf80f4bSopenharmony_ci{
2448bf80f4bSopenharmony_ci    CORE_ASSERT_MSG(imageManager_, "Engine not initialized");
2458bf80f4bSopenharmony_ci    return *imageManager_;
2468bf80f4bSopenharmony_ci}
2478bf80f4bSopenharmony_ci
2488bf80f4bSopenharmony_ciIFileManager& Engine::GetFileManager()
2498bf80f4bSopenharmony_ci{
2508bf80f4bSopenharmony_ci    CORE_ASSERT_MSG(fileManager_, "Engine not initialized");
2518bf80f4bSopenharmony_ci    return *fileManager_;
2528bf80f4bSopenharmony_ci}
2538bf80f4bSopenharmony_ci
2548bf80f4bSopenharmony_ciEngineTime Engine::GetEngineTime() const
2558bf80f4bSopenharmony_ci{
2568bf80f4bSopenharmony_ci    return { previousFrameTime_ - firstTime_, deltaTime_ };
2578bf80f4bSopenharmony_ci}
2588bf80f4bSopenharmony_ci
2598bf80f4bSopenharmony_ciconst IInterface* Engine::GetInterface(const Uid& uid) const
2608bf80f4bSopenharmony_ci{
2618bf80f4bSopenharmony_ci    if ((uid == IEngine::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
2628bf80f4bSopenharmony_ci        return static_cast<const IEngine*>(this);
2638bf80f4bSopenharmony_ci    }
2648bf80f4bSopenharmony_ci    if (uid == IClassRegister::UID) {
2658bf80f4bSopenharmony_ci        return static_cast<const IClassRegister*>(this);
2668bf80f4bSopenharmony_ci    }
2678bf80f4bSopenharmony_ci
2688bf80f4bSopenharmony_ci    return nullptr;
2698bf80f4bSopenharmony_ci}
2708bf80f4bSopenharmony_ci
2718bf80f4bSopenharmony_ciIInterface* Engine::GetInterface(const Uid& uid)
2728bf80f4bSopenharmony_ci{
2738bf80f4bSopenharmony_ci    if ((uid == IEngine::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
2748bf80f4bSopenharmony_ci        return static_cast<IEngine*>(this);
2758bf80f4bSopenharmony_ci    }
2768bf80f4bSopenharmony_ci    if (uid == IClassRegister::UID) {
2778bf80f4bSopenharmony_ci        return static_cast<IClassRegister*>(this);
2788bf80f4bSopenharmony_ci    }
2798bf80f4bSopenharmony_ci
2808bf80f4bSopenharmony_ci    return nullptr;
2818bf80f4bSopenharmony_ci}
2828bf80f4bSopenharmony_ci
2838bf80f4bSopenharmony_civoid Engine::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
2848bf80f4bSopenharmony_ci{
2858bf80f4bSopenharmony_ci    // keep interfaceTypeInfos_ sorted according to UIDs
2868bf80f4bSopenharmony_ci    const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
2878bf80f4bSopenharmony_ci        [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
2888bf80f4bSopenharmony_ci    interfaceTypeInfos_.insert(pos, &interfaceInfo);
2898bf80f4bSopenharmony_ci}
2908bf80f4bSopenharmony_ci
2918bf80f4bSopenharmony_civoid Engine::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
2928bf80f4bSopenharmony_ci{
2938bf80f4bSopenharmony_ci    if (!interfaceTypeInfos_.empty()) {
2948bf80f4bSopenharmony_ci        const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
2958bf80f4bSopenharmony_ci            [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
2968bf80f4bSopenharmony_ci        if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == interfaceInfo.uid) {
2978bf80f4bSopenharmony_ci            interfaceTypeInfos_.erase(pos);
2988bf80f4bSopenharmony_ci        }
2998bf80f4bSopenharmony_ci    }
3008bf80f4bSopenharmony_ci}
3018bf80f4bSopenharmony_ci
3028bf80f4bSopenharmony_ciarray_view<const InterfaceTypeInfo* const> Engine::GetInterfaceMetadata() const
3038bf80f4bSopenharmony_ci{
3048bf80f4bSopenharmony_ci    return interfaceTypeInfos_;
3058bf80f4bSopenharmony_ci}
3068bf80f4bSopenharmony_ci
3078bf80f4bSopenharmony_ciconst InterfaceTypeInfo& Engine::GetInterfaceMetadata(const Uid& uid) const
3088bf80f4bSopenharmony_ci{
3098bf80f4bSopenharmony_ci    static constexpr InterfaceTypeInfo invalidType {};
3108bf80f4bSopenharmony_ci
3118bf80f4bSopenharmony_ci    if (!interfaceTypeInfos_.empty()) {
3128bf80f4bSopenharmony_ci        const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
3138bf80f4bSopenharmony_ci            [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
3148bf80f4bSopenharmony_ci        if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == uid) {
3158bf80f4bSopenharmony_ci            return *(*pos);
3168bf80f4bSopenharmony_ci        }
3178bf80f4bSopenharmony_ci    }
3188bf80f4bSopenharmony_ci    return invalidType;
3198bf80f4bSopenharmony_ci}
3208bf80f4bSopenharmony_ci
3218bf80f4bSopenharmony_ciIInterface* Engine::GetInstance(const Uid& uid) const
3228bf80f4bSopenharmony_ci{
3238bf80f4bSopenharmony_ci    const auto& data = GetInterfaceMetadata(uid);
3248bf80f4bSopenharmony_ci    if (data.getInterface) {
3258bf80f4bSopenharmony_ci        return data.getInterface(const_cast<Engine&>(*this), data.token);
3268bf80f4bSopenharmony_ci    }
3278bf80f4bSopenharmony_ci    return nullptr;
3288bf80f4bSopenharmony_ci}
3298bf80f4bSopenharmony_ci
3308bf80f4bSopenharmony_ciIInterface::Ptr Engine::CreateInstance(const Uid& uid)
3318bf80f4bSopenharmony_ci{
3328bf80f4bSopenharmony_ci    const auto& data = GetInterfaceMetadata(uid);
3338bf80f4bSopenharmony_ci    if (data.createInterface) {
3348bf80f4bSopenharmony_ci        return IInterface::Ptr { data.createInterface(*this, data.token) };
3358bf80f4bSopenharmony_ci    }
3368bf80f4bSopenharmony_ci    return {};
3378bf80f4bSopenharmony_ci}
3388bf80f4bSopenharmony_ci
3398bf80f4bSopenharmony_civoid Engine::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
3408bf80f4bSopenharmony_ci{
3418bf80f4bSopenharmony_ci    if (type == EventType::ADDED) {
3428bf80f4bSopenharmony_ci        for (const auto* info : typeInfos) {
3438bf80f4bSopenharmony_ci            if (info && info->typeUid == IEnginePlugin::UID && static_cast<const IEnginePlugin*>(info)->createPlugin) {
3448bf80f4bSopenharmony_ci                auto enginePlugin = static_cast<const IEnginePlugin*>(info);
3458bf80f4bSopenharmony_ci                if (std::none_of(plugins_.begin(), plugins_.end(),
3468bf80f4bSopenharmony_ci                        [enginePlugin](const pair<PluginToken, const IEnginePlugin*>& pluginData) {
3478bf80f4bSopenharmony_ci                            return pluginData.second == enginePlugin;
3488bf80f4bSopenharmony_ci                        })) {
3498bf80f4bSopenharmony_ci                    auto token = enginePlugin->createPlugin(*this);
3508bf80f4bSopenharmony_ci                    plugins_.push_back({ token, enginePlugin });
3518bf80f4bSopenharmony_ci                }
3528bf80f4bSopenharmony_ci            }
3538bf80f4bSopenharmony_ci        }
3548bf80f4bSopenharmony_ci    } else if (type == EventType::REMOVED) {
3558bf80f4bSopenharmony_ci        for (const auto* info : typeInfos) {
3568bf80f4bSopenharmony_ci            if (info && info->typeUid == IEnginePlugin::UID) {
3578bf80f4bSopenharmony_ci                auto enginePlugin = static_cast<const IEnginePlugin*>(info);
3588bf80f4bSopenharmony_ci                if (auto pos = std::find_if(plugins_.cbegin(), plugins_.cend(),
3598bf80f4bSopenharmony_ci                        [enginePlugin](const pair<PluginToken, const IEnginePlugin*>& pluginData) {
3608bf80f4bSopenharmony_ci                            return pluginData.second == enginePlugin;
3618bf80f4bSopenharmony_ci                        });
3628bf80f4bSopenharmony_ci                    pos != plugins_.cend()) {
3638bf80f4bSopenharmony_ci                    if (enginePlugin->destroyPlugin) {
3648bf80f4bSopenharmony_ci                        enginePlugin->destroyPlugin(pos->first);
3658bf80f4bSopenharmony_ci                    }
3668bf80f4bSopenharmony_ci                    plugins_.erase(pos);
3678bf80f4bSopenharmony_ci                }
3688bf80f4bSopenharmony_ci            }
3698bf80f4bSopenharmony_ci        }
3708bf80f4bSopenharmony_ci    }
3718bf80f4bSopenharmony_ci}
3728bf80f4bSopenharmony_ci
3738bf80f4bSopenharmony_cistring_view Engine::GetVersion()
3748bf80f4bSopenharmony_ci{
3758bf80f4bSopenharmony_ci    return CORE_NS::GetVersion();
3768bf80f4bSopenharmony_ci}
3778bf80f4bSopenharmony_ci
3788bf80f4bSopenharmony_cibool Engine::IsDebugBuild()
3798bf80f4bSopenharmony_ci{
3808bf80f4bSopenharmony_ci    return CORE_NS::IsDebugBuild();
3818bf80f4bSopenharmony_ci}
3828bf80f4bSopenharmony_ci
3838bf80f4bSopenharmony_ciIEngine::Ptr CreateEngine(EngineCreateInfo const& createInfo)
3848bf80f4bSopenharmony_ci{
3858bf80f4bSopenharmony_ci    auto engine = new Engine(createInfo);
3868bf80f4bSopenharmony_ci    return IEngine::Ptr { engine };
3878bf80f4bSopenharmony_ci}
3888bf80f4bSopenharmony_ci
3898bf80f4bSopenharmony_ciconst IPlatform& Engine::GetPlatform() const
3908bf80f4bSopenharmony_ci{
3918bf80f4bSopenharmony_ci    return *platform_;
3928bf80f4bSopenharmony_ci}
3938bf80f4bSopenharmony_ci
3948bf80f4bSopenharmony_civoid Engine::Ref()
3958bf80f4bSopenharmony_ci{
3968bf80f4bSopenharmony_ci    refCount_++;
3978bf80f4bSopenharmony_ci}
3988bf80f4bSopenharmony_ci
3998bf80f4bSopenharmony_civoid Engine::Unref()
4008bf80f4bSopenharmony_ci{
4018bf80f4bSopenharmony_ci    if (--refCount_ == 0) {
4028bf80f4bSopenharmony_ci        delete this;
4038bf80f4bSopenharmony_ci    }
4048bf80f4bSopenharmony_ci}
4058bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
406