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 "asset_loader.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <algorithm> 198bf80f4bSopenharmony_ci 208bf80f4bSopenharmony_ci#include <3d/ecs/components/animation_component.h> 218bf80f4bSopenharmony_ci#include <3d/ecs/components/animation_track_component.h> 228bf80f4bSopenharmony_ci#include <3d/ecs/components/name_component.h> 238bf80f4bSopenharmony_ci#include <3d/ecs/components/node_component.h> 248bf80f4bSopenharmony_ci#include <3d/ecs/components/render_handle_component.h> 258bf80f4bSopenharmony_ci#include <3d/ecs/components/uri_component.h> 268bf80f4bSopenharmony_ci#include <3d/ecs/systems/intf_animation_system.h> 278bf80f4bSopenharmony_ci#include <3d/ecs/systems/intf_node_system.h> 288bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h> 298bf80f4bSopenharmony_ci#include <base/containers/vector.h> 308bf80f4bSopenharmony_ci#include <core/image/intf_image_loader_manager.h> 318bf80f4bSopenharmony_ci#include <core/intf_engine.h> 328bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h> 338bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h> 348bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 358bf80f4bSopenharmony_ci 368bf80f4bSopenharmony_ci#include "asset_manager.h" 378bf80f4bSopenharmony_ci#include "asset_migration.h" 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ciusing namespace BASE_NS; 408bf80f4bSopenharmony_ciusing namespace CORE_NS; 418bf80f4bSopenharmony_ciusing namespace RENDER_NS; 428bf80f4bSopenharmony_ciusing namespace CORE3D_NS; 438bf80f4bSopenharmony_ci 448bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_cinamespace { 478bf80f4bSopenharmony_ci 488bf80f4bSopenharmony_cistruct IoUtil { 498bf80f4bSopenharmony_ci static bool LoadTextFile(string_view fileUri, string& fileContentsOut, IFileManager& fileManager) 508bf80f4bSopenharmony_ci { 518bf80f4bSopenharmony_ci auto file = fileManager.OpenFile(fileUri); 528bf80f4bSopenharmony_ci if (file) { 538bf80f4bSopenharmony_ci const size_t length = file->GetLength(); 548bf80f4bSopenharmony_ci fileContentsOut.resize(length); 558bf80f4bSopenharmony_ci return file->Read(fileContentsOut.data(), length) == length; 568bf80f4bSopenharmony_ci } 578bf80f4bSopenharmony_ci return false; 588bf80f4bSopenharmony_ci } 598bf80f4bSopenharmony_ci}; 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_ci// Add a node and all of its children recursively to a collection 628bf80f4bSopenharmony_civoid AddNodeToCollectionRecursive(IEntityCollection& ec, ISceneNode& node, string_view path) 638bf80f4bSopenharmony_ci{ 648bf80f4bSopenharmony_ci const auto entity = node.GetEntity(); 658bf80f4bSopenharmony_ci const auto currentPath = path + node.GetName(); 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ci EntityReference ref = ec.GetEcs().GetEntityManager().GetReferenceCounted(entity); 688bf80f4bSopenharmony_ci ec.AddEntity(ref); 698bf80f4bSopenharmony_ci ec.SetId(currentPath, ref); 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_ci const auto childBasePath = currentPath + "/"; 728bf80f4bSopenharmony_ci for (auto* child : node.GetChildren()) { 738bf80f4bSopenharmony_ci AddNodeToCollectionRecursive(ec, *child, childBasePath); 748bf80f4bSopenharmony_ci } 758bf80f4bSopenharmony_ci} 768bf80f4bSopenharmony_ci} // namespace 778bf80f4bSopenharmony_ci 788bf80f4bSopenharmony_ci// A class that executes asset load operation over multiple frames. 798bf80f4bSopenharmony_ciclass AssetLoader final : public IAssetLoader, private IAssetLoader::IListener, private IGLTF2Importer::Listener { 808bf80f4bSopenharmony_cipublic: 818bf80f4bSopenharmony_ci AssetLoader(AssetManager& assetManager, IRenderContext& renderContext, IGraphicsContext& graphicsContext, 828bf80f4bSopenharmony_ci IEntityCollection& ec, string_view src, string_view contextUri) 838bf80f4bSopenharmony_ci : assetManager_(assetManager), renderContext_(renderContext), graphicsContext_(graphicsContext), 848bf80f4bSopenharmony_ci ecs_(ec.GetEcs()), ec_(ec), src_(src), contextUri_(contextUri), 858bf80f4bSopenharmony_ci fileManager_(renderContext_.GetEngine().GetFileManager()) 868bf80f4bSopenharmony_ci {} 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ci ~AssetLoader() override 898bf80f4bSopenharmony_ci { 908bf80f4bSopenharmony_ci Cancel(); 918bf80f4bSopenharmony_ci } 928bf80f4bSopenharmony_ci 938bf80f4bSopenharmony_ci IEntityCollection& GetEntityCollection() const override 948bf80f4bSopenharmony_ci { 958bf80f4bSopenharmony_ci return ec_; 968bf80f4bSopenharmony_ci } 978bf80f4bSopenharmony_ci 988bf80f4bSopenharmony_ci string GetSrc() const override 998bf80f4bSopenharmony_ci { 1008bf80f4bSopenharmony_ci return src_; 1018bf80f4bSopenharmony_ci } 1028bf80f4bSopenharmony_ci 1038bf80f4bSopenharmony_ci string GetContextUri() const override 1048bf80f4bSopenharmony_ci { 1058bf80f4bSopenharmony_ci return contextUri_; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci 1088bf80f4bSopenharmony_ci string GetUri() const override 1098bf80f4bSopenharmony_ci { 1108bf80f4bSopenharmony_ci return PathUtil::ResolveUri(contextUri_, src_, true); 1118bf80f4bSopenharmony_ci } 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ci void AddListener(IAssetLoader::IListener& listener) override 1148bf80f4bSopenharmony_ci { 1158bf80f4bSopenharmony_ci CORE_ASSERT(&listener); 1168bf80f4bSopenharmony_ci listeners_.emplace_back(&listener); 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci 1198bf80f4bSopenharmony_ci void RemoveListener(IAssetLoader::IListener& listener) override 1208bf80f4bSopenharmony_ci { 1218bf80f4bSopenharmony_ci CORE_ASSERT(&listener); 1228bf80f4bSopenharmony_ci for (size_t i = 0; i < listeners_.size(); ++i) { 1238bf80f4bSopenharmony_ci if (&listener == listeners_[i]) { 1248bf80f4bSopenharmony_ci listeners_.erase(listeners_.begin() + i); 1258bf80f4bSopenharmony_ci return; 1268bf80f4bSopenharmony_ci } 1278bf80f4bSopenharmony_ci } 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci // trying to remove a non-existent listener. 1308bf80f4bSopenharmony_ci CORE_ASSERT(true); 1318bf80f4bSopenharmony_ci } 1328bf80f4bSopenharmony_ci 1338bf80f4bSopenharmony_ci void LoadAsset() override 1348bf80f4bSopenharmony_ci { 1358bf80f4bSopenharmony_ci async_ = false; 1368bf80f4bSopenharmony_ci StartLoading(); 1378bf80f4bSopenharmony_ci } 1388bf80f4bSopenharmony_ci 1398bf80f4bSopenharmony_ci void LoadAssetAsync() override 1408bf80f4bSopenharmony_ci { 1418bf80f4bSopenharmony_ci async_ = true; 1428bf80f4bSopenharmony_ci StartLoading(); 1438bf80f4bSopenharmony_ci } 1448bf80f4bSopenharmony_ci 1458bf80f4bSopenharmony_ci IAssetLoader* GetNextDependency() const 1468bf80f4bSopenharmony_ci { 1478bf80f4bSopenharmony_ci if (dependencies_.empty()) { 1488bf80f4bSopenharmony_ci return nullptr; 1498bf80f4bSopenharmony_ci } 1508bf80f4bSopenharmony_ci for (const auto& dep : dependencies_) { 1518bf80f4bSopenharmony_ci if (dep && !dep->IsCompleted()) { 1528bf80f4bSopenharmony_ci return dep.get(); 1538bf80f4bSopenharmony_ci } 1548bf80f4bSopenharmony_ci } 1558bf80f4bSopenharmony_ci return nullptr; 1568bf80f4bSopenharmony_ci } 1578bf80f4bSopenharmony_ci 1588bf80f4bSopenharmony_ci // 1598bf80f4bSopenharmony_ci // From IAssetLoader::Listener 1608bf80f4bSopenharmony_ci // 1618bf80f4bSopenharmony_ci void OnLoadFinished(const IAssetLoader& loader) override 1628bf80f4bSopenharmony_ci { 1638bf80f4bSopenharmony_ci // This will be called when a dependency has finished loading. 1648bf80f4bSopenharmony_ci 1658bf80f4bSopenharmony_ci // Hide cached data. 1668bf80f4bSopenharmony_ci loader.GetEntityCollection().SetActive(false); 1678bf80f4bSopenharmony_ci 1688bf80f4bSopenharmony_ci auto* dep = GetNextDependency(); 1698bf80f4bSopenharmony_ci if (dep) { 1708bf80f4bSopenharmony_ci // Load next dependency. 1718bf80f4bSopenharmony_ci ContinueLoading(); 1728bf80f4bSopenharmony_ci } else { 1738bf80f4bSopenharmony_ci // There are no more dependencies. Try loading the main asset again but now with the dependencies loaded. 1748bf80f4bSopenharmony_ci StartLoading(); 1758bf80f4bSopenharmony_ci } 1768bf80f4bSopenharmony_ci } 1778bf80f4bSopenharmony_ci 1788bf80f4bSopenharmony_ci // 1798bf80f4bSopenharmony_ci // From CORE_NS::IGLTF2Importer::Listener 1808bf80f4bSopenharmony_ci // 1818bf80f4bSopenharmony_ci void OnImportStarted() override {} 1828bf80f4bSopenharmony_ci void OnImportFinished() override 1838bf80f4bSopenharmony_ci { 1848bf80f4bSopenharmony_ci GltfImportFinished(); 1858bf80f4bSopenharmony_ci if (async_) { 1868bf80f4bSopenharmony_ci ContinueLoading(); 1878bf80f4bSopenharmony_ci } 1888bf80f4bSopenharmony_ci } 1898bf80f4bSopenharmony_ci void OnImportProgressed(size_t taskIndex, size_t taskCount) override {} 1908bf80f4bSopenharmony_ci 1918bf80f4bSopenharmony_ci bool Execute(uint32_t timeBudget) override 1928bf80f4bSopenharmony_ci { 1938bf80f4bSopenharmony_ci // NOTE: Currently actually only one import will be active at a time so we don't need to worry about the time 1948bf80f4bSopenharmony_ci // budget. 1958bf80f4bSopenharmony_ci bool done = true; 1968bf80f4bSopenharmony_ci 1978bf80f4bSopenharmony_ci for (auto& dep : dependencies_) { 1988bf80f4bSopenharmony_ci if (dep) { 1998bf80f4bSopenharmony_ci done &= dep->Execute(timeBudget); 2008bf80f4bSopenharmony_ci } 2018bf80f4bSopenharmony_ci } 2028bf80f4bSopenharmony_ci if (importer_) { 2038bf80f4bSopenharmony_ci done &= importer_->Execute(timeBudget); 2048bf80f4bSopenharmony_ci } 2058bf80f4bSopenharmony_ci return done; 2068bf80f4bSopenharmony_ci } 2078bf80f4bSopenharmony_ci 2088bf80f4bSopenharmony_ci void Cancel() override 2098bf80f4bSopenharmony_ci { 2108bf80f4bSopenharmony_ci cancelled_ = true; 2118bf80f4bSopenharmony_ci for (auto& dep : dependencies_) { 2128bf80f4bSopenharmony_ci if (dep) { 2138bf80f4bSopenharmony_ci dep->Cancel(); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci } 2168bf80f4bSopenharmony_ci 2178bf80f4bSopenharmony_ci if (importer_) { 2188bf80f4bSopenharmony_ci importer_->Cancel(); 2198bf80f4bSopenharmony_ci importer_.reset(); 2208bf80f4bSopenharmony_ci } 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci 2238bf80f4bSopenharmony_ci bool IsCompleted() const override 2248bf80f4bSopenharmony_ci { 2258bf80f4bSopenharmony_ci return done_; 2268bf80f4bSopenharmony_ci } 2278bf80f4bSopenharmony_ci 2288bf80f4bSopenharmony_ci Result GetResult() const override 2298bf80f4bSopenharmony_ci { 2308bf80f4bSopenharmony_ci return result_; 2318bf80f4bSopenharmony_ci } 2328bf80f4bSopenharmony_ci 2338bf80f4bSopenharmony_ci void Destroy() override 2348bf80f4bSopenharmony_ci { 2358bf80f4bSopenharmony_ci delete this; 2368bf80f4bSopenharmony_ci } 2378bf80f4bSopenharmony_ci 2388bf80f4bSopenharmony_ciprivate: 2398bf80f4bSopenharmony_ci void StartLoading() 2408bf80f4bSopenharmony_ci { 2418bf80f4bSopenharmony_ci if (src_.empty()) { 2428bf80f4bSopenharmony_ci result_ = { false, "Ivalid uri" }; 2438bf80f4bSopenharmony_ci done_ = true; 2448bf80f4bSopenharmony_ci return; 2458bf80f4bSopenharmony_ci } 2468bf80f4bSopenharmony_ci 2478bf80f4bSopenharmony_ci const auto resolvedUri = GetUri(); 2488bf80f4bSopenharmony_ci 2498bf80f4bSopenharmony_ci const auto resolvedFile = PathUtil::ResolveUri(contextUri_, src_, false); 2508bf80f4bSopenharmony_ci const auto ext = PathUtil::GetExtension(resolvedFile); 2518bf80f4bSopenharmony_ci const auto type = assetManager_.GetExtensionType(ext); 2528bf80f4bSopenharmony_ci // TODO: Separate different loaders and make it possible to register more. 2538bf80f4bSopenharmony_ci switch (type) { 2548bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::COLLECTION: { 2558bf80f4bSopenharmony_ci ec_.SetType("entitycollection"); 2568bf80f4bSopenharmony_ci if (LoadJsonEntityCollection()) { 2578bf80f4bSopenharmony_ci MigrateAnimation(ec_); 2588bf80f4bSopenharmony_ci } 2598bf80f4bSopenharmony_ci break; 2608bf80f4bSopenharmony_ci } 2618bf80f4bSopenharmony_ci 2628bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::SCENE: { 2638bf80f4bSopenharmony_ci ec_.SetType("scene"); 2648bf80f4bSopenharmony_ci if (LoadJsonEntityCollection()) { 2658bf80f4bSopenharmony_ci MigrateAnimation(ec_); 2668bf80f4bSopenharmony_ci } 2678bf80f4bSopenharmony_ci break; 2688bf80f4bSopenharmony_ci } 2698bf80f4bSopenharmony_ci 2708bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::ANIMATION: { 2718bf80f4bSopenharmony_ci ec_.SetType("animation"); 2728bf80f4bSopenharmony_ci if (LoadJsonEntityCollection()) { 2738bf80f4bSopenharmony_ci MigrateAnimation(ec_); 2748bf80f4bSopenharmony_ci } 2758bf80f4bSopenharmony_ci break; 2768bf80f4bSopenharmony_ci } 2778bf80f4bSopenharmony_ci 2788bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::MATERIAL: { 2798bf80f4bSopenharmony_ci ec_.SetType("material"); 2808bf80f4bSopenharmony_ci LoadJsonEntityCollection(); 2818bf80f4bSopenharmony_ci break; 2828bf80f4bSopenharmony_ci } 2838bf80f4bSopenharmony_ci 2848bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::GLTF: 2858bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::GLB: { 2868bf80f4bSopenharmony_ci ec_.SetType("gltf"); 2878bf80f4bSopenharmony_ci LoadGltfEntityCollection(); 2888bf80f4bSopenharmony_ci break; 2898bf80f4bSopenharmony_ci } 2908bf80f4bSopenharmony_ci 2918bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::JPG: 2928bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::PNG: 2938bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::KTX: { 2948bf80f4bSopenharmony_ci ec_.SetType("image"); 2958bf80f4bSopenharmony_ci LoadImageEntityCollection(); 2968bf80f4bSopenharmony_ci break; 2978bf80f4bSopenharmony_ci } 2988bf80f4bSopenharmony_ci 2998bf80f4bSopenharmony_ci case IAssetManager::ExtensionType::NOT_SUPPORTED: 3008bf80f4bSopenharmony_ci default: { 3018bf80f4bSopenharmony_ci CORE_LOG_E("Unsupported asset format: '%s'", src_.c_str()); 3028bf80f4bSopenharmony_ci result_ = { false, "Unsupported asset format" }; 3038bf80f4bSopenharmony_ci done_ = true; 3048bf80f4bSopenharmony_ci break; 3058bf80f4bSopenharmony_ci } 3068bf80f4bSopenharmony_ci } 3078bf80f4bSopenharmony_ci 3088bf80f4bSopenharmony_ci ContinueLoading(); 3098bf80f4bSopenharmony_ci } 3108bf80f4bSopenharmony_ci 3118bf80f4bSopenharmony_ci void ContinueLoading() 3128bf80f4bSopenharmony_ci { 3138bf80f4bSopenharmony_ci if (done_) { 3148bf80f4bSopenharmony_ci ec_.MarkModified(false, true); 3158bf80f4bSopenharmony_ci 3168bf80f4bSopenharmony_ci for (auto* listener : listeners_) { 3178bf80f4bSopenharmony_ci listener->OnLoadFinished(*this); 3188bf80f4bSopenharmony_ci } 3198bf80f4bSopenharmony_ci return; 3208bf80f4bSopenharmony_ci } 3218bf80f4bSopenharmony_ci 3228bf80f4bSopenharmony_ci auto* dep = GetNextDependency(); 3238bf80f4bSopenharmony_ci if (dep) { 3248bf80f4bSopenharmony_ci if (async_) { 3258bf80f4bSopenharmony_ci dep->LoadAssetAsync(); 3268bf80f4bSopenharmony_ci } else { 3278bf80f4bSopenharmony_ci dep->LoadAsset(); 3288bf80f4bSopenharmony_ci } 3298bf80f4bSopenharmony_ci return; 3308bf80f4bSopenharmony_ci } 3318bf80f4bSopenharmony_ci } 3328bf80f4bSopenharmony_ci 3338bf80f4bSopenharmony_ci void CreateDummyEntity() 3348bf80f4bSopenharmony_ci { 3358bf80f4bSopenharmony_ci // Create a dummy root entity as a placeholder for a missing asset. 3368bf80f4bSopenharmony_ci auto dummyEntity = ecs_.GetEntityManager().CreateReferenceCounted(); 3378bf80f4bSopenharmony_ci // Note: adding a node component for now so it will be displayed in the hierarchy pane. 3388bf80f4bSopenharmony_ci // This is wrong as the failed asset might not be a 3D node in reality. this could be removed after combining 3398bf80f4bSopenharmony_ci // the Entity pane functionlity to the hierarchy pane and when there is better handling for missing references. 3408bf80f4bSopenharmony_ci auto* nodeComponentManager = GetManager<INodeComponentManager>(ecs_); 3418bf80f4bSopenharmony_ci CORE_ASSERT(nodeComponentManager); 3428bf80f4bSopenharmony_ci if (nodeComponentManager) { 3438bf80f4bSopenharmony_ci nodeComponentManager->Create(dummyEntity); 3448bf80f4bSopenharmony_ci } 3458bf80f4bSopenharmony_ci if (!GetUri().empty()) { 3468bf80f4bSopenharmony_ci auto* nameComponentManager = GetManager<INameComponentManager>(ecs_); 3478bf80f4bSopenharmony_ci CORE_ASSERT(nameComponentManager); 3488bf80f4bSopenharmony_ci if (nameComponentManager) { 3498bf80f4bSopenharmony_ci nameComponentManager->Create(dummyEntity); 3508bf80f4bSopenharmony_ci nameComponentManager->Write(dummyEntity)->name = GetUri(); 3518bf80f4bSopenharmony_ci } 3528bf80f4bSopenharmony_ci } 3538bf80f4bSopenharmony_ci ec_.AddEntity(dummyEntity); 3548bf80f4bSopenharmony_ci ec_.SetId("/", dummyEntity); 3558bf80f4bSopenharmony_ci } 3568bf80f4bSopenharmony_ci 3578bf80f4bSopenharmony_ci bool LoadJsonEntityCollection() 3588bf80f4bSopenharmony_ci { 3598bf80f4bSopenharmony_ci const auto resolvedUri = GetUri(); 3608bf80f4bSopenharmony_ci const auto resolvedFile = PathUtil::ResolveUri(contextUri_, src_, false); 3618bf80f4bSopenharmony_ci 3628bf80f4bSopenharmony_ci const auto params = PathUtil::GetUriParameters(src_); 3638bf80f4bSopenharmony_ci const auto targetParam = params.find("target"); 3648bf80f4bSopenharmony_ci string entityTarget = (targetParam != params.cend()) ? targetParam->second : ""; 3658bf80f4bSopenharmony_ci auto targetEntity = ec_.GetEntity(entityTarget); 3668bf80f4bSopenharmony_ci size_t subcollectionCount = ec_.GetSubCollectionCount(); 3678bf80f4bSopenharmony_ci while (!targetEntity && subcollectionCount) { 3688bf80f4bSopenharmony_ci targetEntity = ec_.GetSubCollection(--subcollectionCount)->GetEntity(entityTarget); 3698bf80f4bSopenharmony_ci } 3708bf80f4bSopenharmony_ci 3718bf80f4bSopenharmony_ci string textIn; 3728bf80f4bSopenharmony_ci if (IoUtil::LoadTextFile(resolvedFile, textIn, fileManager_)) { 3738bf80f4bSopenharmony_ci // TODO: Check file version here. 3748bf80f4bSopenharmony_ci 3758bf80f4bSopenharmony_ci auto json = json::parse(textIn.data()); 3768bf80f4bSopenharmony_ci if (!json) { 3778bf80f4bSopenharmony_ci CORE_LOG_E("Parsing json failed: '%s':\n%s", resolvedUri.c_str(), textIn.c_str()); 3788bf80f4bSopenharmony_ci } else { 3798bf80f4bSopenharmony_ci if (!dependencies_.empty()) { 3808bf80f4bSopenharmony_ci // There were dependencies loaded earlier and now we want to load the actual asset. 3818bf80f4bSopenharmony_ci // No dependencies to load. Just load the entity collection itself and this loading is done. 3828bf80f4bSopenharmony_ci auto result = assetManager_.GetEcsSerializer().ReadEntityCollection(ec_, json, resolvedUri); 3838bf80f4bSopenharmony_ci done_ = true; 3848bf80f4bSopenharmony_ci return result; 3858bf80f4bSopenharmony_ci } 3868bf80f4bSopenharmony_ci 3878bf80f4bSopenharmony_ci vector<IEcsSerializer::ExternalCollection> dependencies; 3888bf80f4bSopenharmony_ci assetManager_.GetEcsSerializer().GatherExternalCollections(json, resolvedUri, dependencies); 3898bf80f4bSopenharmony_ci 3908bf80f4bSopenharmony_ci for (const auto& dep : dependencies) { 3918bf80f4bSopenharmony_ci BASE_NS::string patchedDepUri = dep.src; 3928bf80f4bSopenharmony_ci if (!entityTarget.empty()) 3938bf80f4bSopenharmony_ci patchedDepUri.append("?target=").append(entityTarget); 3948bf80f4bSopenharmony_ci if (!assetManager_.IsCachedCollection(patchedDepUri, dep.contextUri)) { 3958bf80f4bSopenharmony_ci auto* cacheEc = 3968bf80f4bSopenharmony_ci assetManager_.CreateCachedCollection(ec_.GetEcs(), patchedDepUri, dep.contextUri); 3978bf80f4bSopenharmony_ci dependencies_.emplace_back( 3988bf80f4bSopenharmony_ci assetManager_.CreateAssetLoader(*cacheEc, patchedDepUri, dep.contextUri)); 3998bf80f4bSopenharmony_ci auto& dep = *dependencies_.back(); 4008bf80f4bSopenharmony_ci dep.AddListener(*this); 4018bf80f4bSopenharmony_ci } 4028bf80f4bSopenharmony_ci } 4038bf80f4bSopenharmony_ci 4048bf80f4bSopenharmony_ci if (GetNextDependency() == nullptr) { 4058bf80f4bSopenharmony_ci // No dependencies to load. Just load the entity collection itself and this loading is done. 4068bf80f4bSopenharmony_ci auto result = assetManager_.GetEcsSerializer().ReadEntityCollection(ec_, json, resolvedUri); 4078bf80f4bSopenharmony_ci done_ = true; 4088bf80f4bSopenharmony_ci return result; 4098bf80f4bSopenharmony_ci } 4108bf80f4bSopenharmony_ci 4118bf80f4bSopenharmony_ci // There are dependencies that need to be parsed in a next step. 4128bf80f4bSopenharmony_ci return true; 4138bf80f4bSopenharmony_ci } 4148bf80f4bSopenharmony_ci } 4158bf80f4bSopenharmony_ci 4168bf80f4bSopenharmony_ci CreateDummyEntity(); 4178bf80f4bSopenharmony_ci result_ = { false, "collection loading failed." }; 4188bf80f4bSopenharmony_ci done_ = true; 4198bf80f4bSopenharmony_ci return false; 4208bf80f4bSopenharmony_ci } 4218bf80f4bSopenharmony_ci 4228bf80f4bSopenharmony_ci void LoadGltfEntityCollection() 4238bf80f4bSopenharmony_ci { 4248bf80f4bSopenharmony_ci const auto resolvedFile = PathUtil::ResolveUri(contextUri_, src_, false); 4258bf80f4bSopenharmony_ci 4268bf80f4bSopenharmony_ci auto& gltf = graphicsContext_.GetGltf(); 4278bf80f4bSopenharmony_ci 4288bf80f4bSopenharmony_ci loadResult_ = gltf.LoadGLTF(resolvedFile); 4298bf80f4bSopenharmony_ci if (!loadResult_.success) { 4308bf80f4bSopenharmony_ci CORE_LOG_E("Loaded '%s' with errors:\n%s", resolvedFile.c_str(), loadResult_.error.c_str()); 4318bf80f4bSopenharmony_ci } 4328bf80f4bSopenharmony_ci if (!loadResult_.data) { 4338bf80f4bSopenharmony_ci CreateDummyEntity(); 4348bf80f4bSopenharmony_ci result_ = { false, "glTF load failed." }; 4358bf80f4bSopenharmony_ci done_ = true; 4368bf80f4bSopenharmony_ci return; 4378bf80f4bSopenharmony_ci } 4388bf80f4bSopenharmony_ci 4398bf80f4bSopenharmony_ci importer_ = gltf.CreateGLTF2Importer(ec_.GetEcs()); 4408bf80f4bSopenharmony_ci 4418bf80f4bSopenharmony_ci if (async_) { 4428bf80f4bSopenharmony_ci importer_->ImportGLTFAsync(*loadResult_.data, CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL, this); 4438bf80f4bSopenharmony_ci } else { 4448bf80f4bSopenharmony_ci importer_->ImportGLTF(*loadResult_.data, CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL); 4458bf80f4bSopenharmony_ci OnImportFinished(); 4468bf80f4bSopenharmony_ci } 4478bf80f4bSopenharmony_ci } 4488bf80f4bSopenharmony_ci 4498bf80f4bSopenharmony_ci Entity ImportSceneFromGltf(EntityReference root) 4508bf80f4bSopenharmony_ci { 4518bf80f4bSopenharmony_ci auto& gltf = graphicsContext_.GetGltf(); 4528bf80f4bSopenharmony_ci 4538bf80f4bSopenharmony_ci // Import the default scene, or first scene if there is no default scene set. 4548bf80f4bSopenharmony_ci size_t sceneIndex = loadResult_.data->GetDefaultSceneIndex(); 4558bf80f4bSopenharmony_ci if (sceneIndex == CORE_GLTF_INVALID_INDEX && loadResult_.data->GetSceneCount() > 0) { 4568bf80f4bSopenharmony_ci // Use first scene. 4578bf80f4bSopenharmony_ci sceneIndex = 0; 4588bf80f4bSopenharmony_ci } 4598bf80f4bSopenharmony_ci 4608bf80f4bSopenharmony_ci const CORE3D_NS::GLTFResourceData& resourceData = importer_->GetResult().data; 4618bf80f4bSopenharmony_ci Entity importedSceneEntity {}; 4628bf80f4bSopenharmony_ci if (sceneIndex != CORE_GLTF_INVALID_INDEX) { 4638bf80f4bSopenharmony_ci GltfSceneImportFlags importFlags = CORE_GLTF_IMPORT_COMPONENT_FLAG_BITS_ALL; 4648bf80f4bSopenharmony_ci importedSceneEntity = 4658bf80f4bSopenharmony_ci gltf.ImportGltfScene(sceneIndex, *loadResult_.data, resourceData, ecs_, root, importFlags); 4668bf80f4bSopenharmony_ci } 4678bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(importedSceneEntity)) { 4688bf80f4bSopenharmony_ci return {}; 4698bf80f4bSopenharmony_ci } 4708bf80f4bSopenharmony_ci 4718bf80f4bSopenharmony_ci // make sure everyone has a name (rest of the system fails if there are unnamed nodes) 4728bf80f4bSopenharmony_ci auto* nodeComponentManager = GetManager<INodeComponentManager>(ecs_); 4738bf80f4bSopenharmony_ci for (auto i = 0; i < nodeComponentManager->GetComponentCount(); i++) { 4748bf80f4bSopenharmony_ci auto ent = nodeComponentManager->GetEntity(i); 4758bf80f4bSopenharmony_ci auto* ncm = GetManager<INameComponentManager>(ecs_); 4768bf80f4bSopenharmony_ci bool setName = true; 4778bf80f4bSopenharmony_ci if (ncm->HasComponent(ent)) { 4788bf80f4bSopenharmony_ci // check if empty 4798bf80f4bSopenharmony_ci auto name = ncm->Get(ent).name; 4808bf80f4bSopenharmony_ci if (!name.empty()) { 4818bf80f4bSopenharmony_ci // it has a non empty name.. 4828bf80f4bSopenharmony_ci setName = false; 4838bf80f4bSopenharmony_ci } 4848bf80f4bSopenharmony_ci } 4858bf80f4bSopenharmony_ci if (setName) { 4868bf80f4bSopenharmony_ci // no name component, so create one create one. 4878bf80f4bSopenharmony_ci char buf[256]; 4888bf80f4bSopenharmony_ci // possibly not unique enough. user created names could conflict. 4898bf80f4bSopenharmony_ci sprintf(buf, "Unnamed Node %d", i); 4908bf80f4bSopenharmony_ci ncm->Set(ent, { buf }); 4918bf80f4bSopenharmony_ci } 4928bf80f4bSopenharmony_ci } 4938bf80f4bSopenharmony_ci 4948bf80f4bSopenharmony_ci // Link animation tracks to targets 4958bf80f4bSopenharmony_ci if (!resourceData.animations.empty()) { 4968bf80f4bSopenharmony_ci INodeSystem* nodeSystem = GetSystem<INodeSystem>(ecs_); 4978bf80f4bSopenharmony_ci if (auto animationRootNode = nodeSystem->GetNode(importedSceneEntity); animationRootNode) { 4988bf80f4bSopenharmony_ci for (const auto& animationEntity : resourceData.animations) { 4998bf80f4bSopenharmony_ci UpdateTrackTargets(animationEntity, animationRootNode); 5008bf80f4bSopenharmony_ci } 5018bf80f4bSopenharmony_ci } 5028bf80f4bSopenharmony_ci } 5038bf80f4bSopenharmony_ci 5048bf80f4bSopenharmony_ci return importedSceneEntity; 5058bf80f4bSopenharmony_ci } 5068bf80f4bSopenharmony_ci 5078bf80f4bSopenharmony_ci void UpdateTrackTargets(Entity animationEntity, ISceneNode* node) 5088bf80f4bSopenharmony_ci { 5098bf80f4bSopenharmony_ci auto& nameManager_ = *GetManager<INameComponentManager>(ecs_); 5108bf80f4bSopenharmony_ci auto animationManager = GetManager<IAnimationComponentManager>(ecs_); 5118bf80f4bSopenharmony_ci auto animationTrackManager = GetManager<IAnimationTrackComponentManager>(ecs_); 5128bf80f4bSopenharmony_ci auto& entityManager = ecs_.GetEntityManager(); 5138bf80f4bSopenharmony_ci 5148bf80f4bSopenharmony_ci if (const ScopedHandle<const AnimationComponent> animationData = animationManager->Read(animationEntity); 5158bf80f4bSopenharmony_ci animationData) { 5168bf80f4bSopenharmony_ci vector<Entity> targetEntities; 5178bf80f4bSopenharmony_ci targetEntities.reserve(animationData->tracks.size()); 5188bf80f4bSopenharmony_ci std::transform(animationData->tracks.begin(), animationData->tracks.end(), 5198bf80f4bSopenharmony_ci std::back_inserter(targetEntities), [&nameManager = nameManager_, &node](const Entity& trackEntity) { 5208bf80f4bSopenharmony_ci if (auto nameHandle = nameManager.Read(trackEntity); nameHandle) { 5218bf80f4bSopenharmony_ci if (auto targetNode = node->LookupNodeByPath(nameHandle->name); targetNode) { 5228bf80f4bSopenharmony_ci return targetNode->GetEntity(); 5238bf80f4bSopenharmony_ci } 5248bf80f4bSopenharmony_ci } 5258bf80f4bSopenharmony_ci return Entity {}; 5268bf80f4bSopenharmony_ci }); 5278bf80f4bSopenharmony_ci if (animationData->tracks.size() == targetEntities.size()) { 5288bf80f4bSopenharmony_ci auto targetIt = targetEntities.begin(); 5298bf80f4bSopenharmony_ci for (const auto& trackEntity : animationData->tracks) { 5308bf80f4bSopenharmony_ci if (auto track = animationTrackManager->Write(trackEntity); track) { 5318bf80f4bSopenharmony_ci if (track->target) { 5328bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("AnimationTrack %s already targetted", 5338bf80f4bSopenharmony_ci to_hex(static_cast<const Entity&>(track->target).id).data()); 5348bf80f4bSopenharmony_ci } 5358bf80f4bSopenharmony_ci track->target = entityManager.GetReferenceCounted(*targetIt); 5368bf80f4bSopenharmony_ci } 5378bf80f4bSopenharmony_ci ++targetIt; 5388bf80f4bSopenharmony_ci } 5398bf80f4bSopenharmony_ci } 5408bf80f4bSopenharmony_ci } 5418bf80f4bSopenharmony_ci } 5428bf80f4bSopenharmony_ci 5438bf80f4bSopenharmony_ci void GltfImportFinished() 5448bf80f4bSopenharmony_ci { 5458bf80f4bSopenharmony_ci auto* nodeSystem = GetSystem<INodeSystem>(ecs_); 5468bf80f4bSopenharmony_ci CORE_ASSERT(nodeSystem); 5478bf80f4bSopenharmony_ci auto* nodeComponentManager = GetManager<INodeComponentManager>(ecs_); 5488bf80f4bSopenharmony_ci CORE_ASSERT(nodeComponentManager); 5498bf80f4bSopenharmony_ci if (!nodeSystem || !nodeComponentManager) { 5508bf80f4bSopenharmony_ci result_ = { false, {} }; 5518bf80f4bSopenharmony_ci done_ = true; 5528bf80f4bSopenharmony_ci return; 5538bf80f4bSopenharmony_ci } 5548bf80f4bSopenharmony_ci 5558bf80f4bSopenharmony_ci const auto params = PathUtil::GetUriParameters(src_); 5568bf80f4bSopenharmony_ci const auto rootParam = params.find("root"); 5578bf80f4bSopenharmony_ci string entityPath = (rootParam != params.cend()) ? rootParam->second : ""; 5588bf80f4bSopenharmony_ci 5598bf80f4bSopenharmony_ci const auto targetParam = params.find("target"); 5608bf80f4bSopenharmony_ci string entityTarget = (targetParam != params.cend()) ? targetParam->second : ""; 5618bf80f4bSopenharmony_ci auto targetEntity = ec_.GetEntity(entityTarget); 5628bf80f4bSopenharmony_ci size_t subcollectionCount = ec_.GetSubCollectionCount(); 5638bf80f4bSopenharmony_ci while (!targetEntity && subcollectionCount) { 5648bf80f4bSopenharmony_ci targetEntity = ec_.GetSubCollection(--subcollectionCount)->GetEntity(entityTarget); 5658bf80f4bSopenharmony_ci } 5668bf80f4bSopenharmony_ci 5678bf80f4bSopenharmony_ci if (importer_) { 5688bf80f4bSopenharmony_ci auto const gltfImportResult = importer_->GetResult(); 5698bf80f4bSopenharmony_ci if (!gltfImportResult.success) { 5708bf80f4bSopenharmony_ci CORE_LOG_E("Importing of '%s' failed: %s", GetUri().c_str(), gltfImportResult.error.c_str()); 5718bf80f4bSopenharmony_ci CreateDummyEntity(); 5728bf80f4bSopenharmony_ci result_ = { false, "glTF import failed." }; 5738bf80f4bSopenharmony_ci done_ = true; 5748bf80f4bSopenharmony_ci return; 5758bf80f4bSopenharmony_ci 5768bf80f4bSopenharmony_ci } else if (cancelled_) { 5778bf80f4bSopenharmony_ci CORE_LOG_V("Importing of '%s' cancelled", GetUri().c_str()); 5788bf80f4bSopenharmony_ci CreateDummyEntity(); 5798bf80f4bSopenharmony_ci result_ = { false, "glTF import cancelled." }; 5808bf80f4bSopenharmony_ci done_ = true; 5818bf80f4bSopenharmony_ci return; 5828bf80f4bSopenharmony_ci } 5838bf80f4bSopenharmony_ci 5848bf80f4bSopenharmony_ci // Loading and importing of glTF was done successfully. Fill the collection with all the gltf entities. 5858bf80f4bSopenharmony_ci const auto originalRootEntity = ImportSceneFromGltf(targetEntity); 5868bf80f4bSopenharmony_ci auto* originalRootNode = nodeSystem->GetNode(originalRootEntity); 5878bf80f4bSopenharmony_ci 5888bf80f4bSopenharmony_ci // It's possible to only add some specific node from the gltf. 5898bf80f4bSopenharmony_ci auto* loadNode = originalRootNode; 5908bf80f4bSopenharmony_ci if (!entityPath.empty()) { 5918bf80f4bSopenharmony_ci loadNode = originalRootNode->LookupNodeByPath(entityPath); 5928bf80f4bSopenharmony_ci if (!loadNode || loadNode->GetEntity() == Entity {}) { 5938bf80f4bSopenharmony_ci CORE_LOG_E("Entity '%s' not found from '%s'", entityPath.c_str(), GetUri().c_str()); 5948bf80f4bSopenharmony_ci } 5958bf80f4bSopenharmony_ci } 5968bf80f4bSopenharmony_ci 5978bf80f4bSopenharmony_ci if (!loadNode || loadNode->GetEntity() == Entity {}) { 5988bf80f4bSopenharmony_ci CreateDummyEntity(); 5998bf80f4bSopenharmony_ci result_ = { false, "Ivalid uri" }; 6008bf80f4bSopenharmony_ci done_ = true; 6018bf80f4bSopenharmony_ci return; 6028bf80f4bSopenharmony_ci } 6038bf80f4bSopenharmony_ci 6048bf80f4bSopenharmony_ci Entity entity = loadNode->GetEntity(); 6058bf80f4bSopenharmony_ci if (entity != Entity {}) { 6068bf80f4bSopenharmony_ci EntityReference ref = ecs_.GetEntityManager().GetReferenceCounted(entity); 6078bf80f4bSopenharmony_ci ec_.AddEntity(ref); 6088bf80f4bSopenharmony_ci ec_.SetId("/", ref); 6098bf80f4bSopenharmony_ci 6108bf80f4bSopenharmony_ci if (!targetEntity) { 6118bf80f4bSopenharmony_ci loadNode->SetParent(nodeSystem->GetRootNode()); 6128bf80f4bSopenharmony_ci } 6138bf80f4bSopenharmony_ci for (auto* child : loadNode->GetChildren()) { 6148bf80f4bSopenharmony_ci AddNodeToCollectionRecursive(ec_, *child, "/"); 6158bf80f4bSopenharmony_ci } 6168bf80f4bSopenharmony_ci } 6178bf80f4bSopenharmony_ci 6188bf80f4bSopenharmony_ci // TODO: a little backwards to first create everything and then delete the extra. 6198bf80f4bSopenharmony_ci if (entity != originalRootEntity) { 6208bf80f4bSopenharmony_ci auto* oldRoot = nodeSystem->GetNode(originalRootEntity); 6218bf80f4bSopenharmony_ci CORE_ASSERT(oldRoot); 6228bf80f4bSopenharmony_ci if (oldRoot) { 6238bf80f4bSopenharmony_ci nodeSystem->DestroyNode(*oldRoot); 6248bf80f4bSopenharmony_ci } 6258bf80f4bSopenharmony_ci } 6268bf80f4bSopenharmony_ci 6278bf80f4bSopenharmony_ci // Add all resources in separate sub-collections. Not just 3D nodes. 6288bf80f4bSopenharmony_ci { 6298bf80f4bSopenharmony_ci const auto& importResult = importer_->GetResult(); 6308bf80f4bSopenharmony_ci ec_.AddSubCollection("images", {}).AddEntities(importResult.data.images); 6318bf80f4bSopenharmony_ci ec_.AddSubCollection("materials", {}).AddEntities(importResult.data.materials); 6328bf80f4bSopenharmony_ci ec_.AddSubCollection("meshes", {}).AddEntities(importResult.data.meshes); 6338bf80f4bSopenharmony_ci ec_.AddSubCollection("skins", {}).AddEntities(importResult.data.skins); 6348bf80f4bSopenharmony_ci ec_.AddSubCollection("animations", {}).AddEntities(importResult.data.animations); 6358bf80f4bSopenharmony_ci 6368bf80f4bSopenharmony_ci // TODO: don't list duplicates 6378bf80f4bSopenharmony_ci vector<EntityReference> animationTracks; 6388bf80f4bSopenharmony_ci auto* acm = GetManager<IAnimationComponentManager>(ecs_); 6398bf80f4bSopenharmony_ci if (acm) { 6408bf80f4bSopenharmony_ci for (auto& entity : importResult.data.animations) { 6418bf80f4bSopenharmony_ci if (auto handle = acm->Read(entity); handle) { 6428bf80f4bSopenharmony_ci const auto& tracks = handle->tracks; 6438bf80f4bSopenharmony_ci for (auto& entityRef : tracks) { 6448bf80f4bSopenharmony_ci animationTracks.emplace_back(entityRef); 6458bf80f4bSopenharmony_ci } 6468bf80f4bSopenharmony_ci } 6478bf80f4bSopenharmony_ci } 6488bf80f4bSopenharmony_ci } 6498bf80f4bSopenharmony_ci ec_.AddSubCollection("animationTracks", {}).AddEntities(animationTracks); 6508bf80f4bSopenharmony_ci } 6518bf80f4bSopenharmony_ci 6528bf80f4bSopenharmony_ci // Load finished successfully. 6538bf80f4bSopenharmony_ci done_ = true; 6548bf80f4bSopenharmony_ci } 6558bf80f4bSopenharmony_ci } 6568bf80f4bSopenharmony_ci 6578bf80f4bSopenharmony_ci bool LoadImageEntityCollection() 6588bf80f4bSopenharmony_ci { 6598bf80f4bSopenharmony_ci auto uri = GetUri(); 6608bf80f4bSopenharmony_ci auto imageHandle = assetManager_.GetEcsSerializer().LoadImageResource(uri); 6618bf80f4bSopenharmony_ci 6628bf80f4bSopenharmony_ci // NOTE: Creating the entity even when the image load failed to load so we can detect a missing resource. 6638bf80f4bSopenharmony_ci EntityReference entity = ecs_.GetEntityManager().CreateReferenceCounted(); 6648bf80f4bSopenharmony_ci ec_.AddEntity(entity); 6658bf80f4bSopenharmony_ci 6668bf80f4bSopenharmony_ci auto* ncm = GetManager<INameComponentManager>(ecs_); 6678bf80f4bSopenharmony_ci auto* ucm = GetManager<IUriComponentManager>(ecs_); 6688bf80f4bSopenharmony_ci auto* gcm = GetManager<IRenderHandleComponentManager>(ecs_); 6698bf80f4bSopenharmony_ci if (ncm && ucm && gcm) { 6708bf80f4bSopenharmony_ci { 6718bf80f4bSopenharmony_ci ncm->Create(entity); 6728bf80f4bSopenharmony_ci auto nc = ncm->Get(entity); 6738bf80f4bSopenharmony_ci nc.name = PathUtil::GetFilename(uri); 6748bf80f4bSopenharmony_ci ec_.SetUniqueIdentifier(nc.name, entity); 6758bf80f4bSopenharmony_ci ncm->Set(entity, nc); 6768bf80f4bSopenharmony_ci } 6778bf80f4bSopenharmony_ci 6788bf80f4bSopenharmony_ci { 6798bf80f4bSopenharmony_ci // TODO: maybe need to save uri + contextUri 6808bf80f4bSopenharmony_ci ucm->Create(entity); 6818bf80f4bSopenharmony_ci auto uc = ucm->Get(entity); 6828bf80f4bSopenharmony_ci uc.uri = uri; 6838bf80f4bSopenharmony_ci ucm->Set(entity, uc); 6848bf80f4bSopenharmony_ci } 6858bf80f4bSopenharmony_ci 6868bf80f4bSopenharmony_ci gcm->Create(entity); 6878bf80f4bSopenharmony_ci if (imageHandle) { 6888bf80f4bSopenharmony_ci auto ic = gcm->Get(entity); 6898bf80f4bSopenharmony_ci ic.reference = imageHandle; 6908bf80f4bSopenharmony_ci gcm->Set(entity, ic); 6918bf80f4bSopenharmony_ci 6928bf80f4bSopenharmony_ci done_ = true; 6938bf80f4bSopenharmony_ci return true; 6948bf80f4bSopenharmony_ci } 6958bf80f4bSopenharmony_ci } 6968bf80f4bSopenharmony_ci 6978bf80f4bSopenharmony_ci // NOTE: Always returning true as even when this fails a placeholder entity is created. 6988bf80f4bSopenharmony_ci CORE_LOG_E("Error creating image '%s'", uri.c_str()); 6998bf80f4bSopenharmony_ci CreateDummyEntity(); 7008bf80f4bSopenharmony_ci result_ = { false, "Error creating image" }; 7018bf80f4bSopenharmony_ci done_ = true; 7028bf80f4bSopenharmony_ci return true; 7038bf80f4bSopenharmony_ci } 7048bf80f4bSopenharmony_ci 7058bf80f4bSopenharmony_ciprivate: 7068bf80f4bSopenharmony_ci AssetManager& assetManager_; 7078bf80f4bSopenharmony_ci RENDER_NS::IRenderContext& renderContext_; 7088bf80f4bSopenharmony_ci CORE3D_NS::IGraphicsContext& graphicsContext_; 7098bf80f4bSopenharmony_ci 7108bf80f4bSopenharmony_ci CORE_NS::IEcs& ecs_; 7118bf80f4bSopenharmony_ci IEntityCollection& ec_; 7128bf80f4bSopenharmony_ci BASE_NS::string src_; 7138bf80f4bSopenharmony_ci BASE_NS::string contextUri_; 7148bf80f4bSopenharmony_ci 7158bf80f4bSopenharmony_ci IAssetLoader::Result result_ {}; 7168bf80f4bSopenharmony_ci 7178bf80f4bSopenharmony_ci vector<AssetLoader::Ptr> dependencies_; 7188bf80f4bSopenharmony_ci 7198bf80f4bSopenharmony_ci bool done_ { false }; 7208bf80f4bSopenharmony_ci bool cancelled_ { false }; 7218bf80f4bSopenharmony_ci bool async_ { false }; 7228bf80f4bSopenharmony_ci 7238bf80f4bSopenharmony_ci GLTFLoadResult loadResult_ {}; 7248bf80f4bSopenharmony_ci IGLTF2Importer::Ptr importer_ {}; 7258bf80f4bSopenharmony_ci 7268bf80f4bSopenharmony_ci vector<IAssetLoader::IListener*> listeners_; 7278bf80f4bSopenharmony_ci IFileManager& fileManager_; 7288bf80f4bSopenharmony_ci}; 7298bf80f4bSopenharmony_ci 7308bf80f4bSopenharmony_ciIAssetLoader::Ptr CreateAssetLoader(AssetManager& assetManager, IRenderContext& renderContext, 7318bf80f4bSopenharmony_ci IGraphicsContext& graphicsContext, IEntityCollection& ec, string_view src, string_view contextUri) 7328bf80f4bSopenharmony_ci{ 7338bf80f4bSopenharmony_ci return IAssetLoader::Ptr { new AssetLoader(assetManager, renderContext, graphicsContext, ec, src, contextUri) }; 7348bf80f4bSopenharmony_ci} 7358bf80f4bSopenharmony_ci 7368bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 737