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 "scene_holder.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <algorithm> 198bf80f4bSopenharmony_ci#include <chrono> 208bf80f4bSopenharmony_ci#include <inttypes.h> 218bf80f4bSopenharmony_ci#include <scene_plugin/api/material.h> 228bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_scene.h> 238bf80f4bSopenharmony_ci 248bf80f4bSopenharmony_ci#include <3d/ecs/components/environment_component.h> 258bf80f4bSopenharmony_ci#include <3d/ecs/components/local_matrix_component.h> 268bf80f4bSopenharmony_ci#include <3d/ecs/components/post_process_component.h> 278bf80f4bSopenharmony_ci#include <3d/ecs/components/render_configuration_component.h> 288bf80f4bSopenharmony_ci#include <3d/ecs/components/render_handle_component.h> 298bf80f4bSopenharmony_ci#include <3d/ecs/components/render_mesh_batch_component.h> 308bf80f4bSopenharmony_ci#include <3d/ecs/components/transform_component.h> 318bf80f4bSopenharmony_ci#include <3d/ecs/components/uri_component.h> 328bf80f4bSopenharmony_ci#include <3d/ecs/components/world_matrix_component.h> 338bf80f4bSopenharmony_ci#include <3d/ecs/systems/intf_render_preprocessor_system.h> 348bf80f4bSopenharmony_ci#include <3d/implementation_uids.h> 358bf80f4bSopenharmony_ci#include <3d/render/default_material_constants.h> 368bf80f4bSopenharmony_ci#include <3d/util/intf_mesh_builder.h> 378bf80f4bSopenharmony_ci#include <3d/util/intf_scene_util.h> 388bf80f4bSopenharmony_ci#include <base/util/uid_util.h> 398bf80f4bSopenharmony_ci#include <core/ecs/intf_system_graph_loader.h> 408bf80f4bSopenharmony_ci#include <core/intf_engine.h> 418bf80f4bSopenharmony_ci#include <core/plugin/intf_class_factory.h> 428bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h> 438bf80f4bSopenharmony_ci#include <render/device/intf_shader_manager.h> 448bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 458bf80f4bSopenharmony_ci#include <render/intf_renderer.h> 468bf80f4bSopenharmony_ci#include <render/util/intf_render_util.h> 478bf80f4bSopenharmony_ci 488bf80f4bSopenharmony_ci#include <meta/api/make_callback.h> 498bf80f4bSopenharmony_ci#include <meta/base/shared_ptr.h> 508bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h> 518bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue_registry.h> 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_ci#include "asset_loader.h" 548bf80f4bSopenharmony_ci#include "asset_manager.h" 558bf80f4bSopenharmony_ci#include "ecs_util.h" 568bf80f4bSopenharmony_ci#include "entity_collection.h" 578bf80f4bSopenharmony_ci#include "intf_node_private.h" 588bf80f4bSopenharmony_ci#include "task_utils.h" 598bf80f4bSopenharmony_ci 608bf80f4bSopenharmony_ci// Initialize ecs on scene holder initialization or do it lazily when there's a scene to load 618bf80f4bSopenharmony_ci 628bf80f4bSopenharmony_ciusing namespace BASE_NS; 638bf80f4bSopenharmony_ciusing namespace CORE_NS; 648bf80f4bSopenharmony_ciusing namespace CORE3D_NS; 658bf80f4bSopenharmony_ciusing namespace RENDER_NS; 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask; 688bf80f4bSopenharmony_ci 698bf80f4bSopenharmony_cinamespace { 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_cibool TickFrame(IEcs& ecs, uint64_t totalTime, uint64_t deltaTime) 728bf80f4bSopenharmony_ci{ 738bf80f4bSopenharmony_ci // run garbage collection before updating the systems to ensure only valid entities/ components are available. 748bf80f4bSopenharmony_ci ecs.ProcessEvents(); 758bf80f4bSopenharmony_ci 768bf80f4bSopenharmony_ci const bool needRender = ecs.Update(totalTime, deltaTime); 778bf80f4bSopenharmony_ci 788bf80f4bSopenharmony_ci // do gc also after the systems have been updated to ensure any deletes done by systems are effective 798bf80f4bSopenharmony_ci // and client doesn't see stale entities. 808bf80f4bSopenharmony_ci ecs.ProcessEvents(); 818bf80f4bSopenharmony_ci 828bf80f4bSopenharmony_ci return needRender; 838bf80f4bSopenharmony_ci} 848bf80f4bSopenharmony_ciconstexpr GpuImageDesc GetColorImageDesc(const uint32_t width, const uint32_t height) 858bf80f4bSopenharmony_ci{ 868bf80f4bSopenharmony_ci GpuImageDesc resolveDesc; 878bf80f4bSopenharmony_ci resolveDesc.width = width; 888bf80f4bSopenharmony_ci resolveDesc.height = height; 898bf80f4bSopenharmony_ci resolveDesc.depth = 1; 908bf80f4bSopenharmony_ci resolveDesc.format = BASE_NS::Format::BASE_FORMAT_R8G8B8A8_SRGB; 918bf80f4bSopenharmony_ci resolveDesc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 928bf80f4bSopenharmony_ci resolveDesc.usageFlags = 938bf80f4bSopenharmony_ci ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT; 948bf80f4bSopenharmony_ci resolveDesc.imageType = ImageType::CORE_IMAGE_TYPE_2D; 958bf80f4bSopenharmony_ci resolveDesc.imageTiling = ImageTiling::CORE_IMAGE_TILING_OPTIMAL; 968bf80f4bSopenharmony_ci resolveDesc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_2D; 978bf80f4bSopenharmony_ci resolveDesc.engineCreationFlags = EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS; 988bf80f4bSopenharmony_ci return resolveDesc; 998bf80f4bSopenharmony_ci} 1008bf80f4bSopenharmony_ci 1018bf80f4bSopenharmony_ciconstexpr GpuImageDesc GetDepthImageDesc(const uint32_t width, const uint32_t height) 1028bf80f4bSopenharmony_ci{ 1038bf80f4bSopenharmony_ci GpuImageDesc resolveDesc; 1048bf80f4bSopenharmony_ci resolveDesc.width = width; 1058bf80f4bSopenharmony_ci resolveDesc.height = height; 1068bf80f4bSopenharmony_ci resolveDesc.depth = 1; 1078bf80f4bSopenharmony_ci resolveDesc.format = BASE_NS::Format::BASE_FORMAT_D16_UNORM; 1088bf80f4bSopenharmony_ci resolveDesc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 1098bf80f4bSopenharmony_ci resolveDesc.usageFlags = ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | 1108bf80f4bSopenharmony_ci ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT; 1118bf80f4bSopenharmony_ci resolveDesc.imageType = ImageType::CORE_IMAGE_TYPE_2D; 1128bf80f4bSopenharmony_ci resolveDesc.imageTiling = ImageTiling::CORE_IMAGE_TILING_OPTIMAL; 1138bf80f4bSopenharmony_ci resolveDesc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_2D; 1148bf80f4bSopenharmony_ci resolveDesc.engineCreationFlags = EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS; 1158bf80f4bSopenharmony_ci return resolveDesc; 1168bf80f4bSopenharmony_ci} 1178bf80f4bSopenharmony_ci 1188bf80f4bSopenharmony_cistatic BASE_NS::string ROOTNODE_NAME = "rootNode_"; 1198bf80f4bSopenharmony_cistatic BASE_NS::string ROOTNODE_PATH = "/" + ROOTNODE_NAME + "/"; 1208bf80f4bSopenharmony_ci 1218bf80f4bSopenharmony_ciBASE_NS::string_view RemoveRootNodeFromPath(const BASE_NS::string_view& path) 1228bf80f4bSopenharmony_ci{ 1238bf80f4bSopenharmony_ci if (path.starts_with(ROOTNODE_PATH)) { 1248bf80f4bSopenharmony_ci return path.substr(ROOTNODE_PATH.length()); 1258bf80f4bSopenharmony_ci } 1268bf80f4bSopenharmony_ci 1278bf80f4bSopenharmony_ci if (path.starts_with("/")) { 1288bf80f4bSopenharmony_ci return path.substr(1); 1298bf80f4bSopenharmony_ci } 1308bf80f4bSopenharmony_ci 1318bf80f4bSopenharmony_ci return path; 1328bf80f4bSopenharmony_ci} 1338bf80f4bSopenharmony_ci} // namespace 1348bf80f4bSopenharmony_ci 1358bf80f4bSopenharmony_ciSceneHolder::SceneHolder(META_NS::InstanceId uid, META_NS::IObjectRegistry& registry, 1368bf80f4bSopenharmony_ci const BASE_NS::shared_ptr<RENDER_NS::IRenderContext>& gc, META_NS::ITaskQueue::Ptr appQueue, 1378bf80f4bSopenharmony_ci META_NS::ITaskQueue::Ptr engineQueue) 1388bf80f4bSopenharmony_ci : instanceId_(uid), renderContext_(gc), appTaskQueue_(appQueue), engineTaskQueue_(engineQueue), 1398bf80f4bSopenharmony_ci objectRegistry_(registry) 1408bf80f4bSopenharmony_ci{} 1418bf80f4bSopenharmony_ci 1428bf80f4bSopenharmony_ciSceneHolder::~SceneHolder() 1438bf80f4bSopenharmony_ci{ 1448bf80f4bSopenharmony_ci ResetScene(false); 1458bf80f4bSopenharmony_ci} 1468bf80f4bSopenharmony_ci 1478bf80f4bSopenharmony_ciCORE_NS::IEcs::Ptr SceneHolder::GetEcs() 1488bf80f4bSopenharmony_ci{ 1498bf80f4bSopenharmony_ci // once we offer Ecs to anyone, we cannot know it is intact 1508bf80f4bSopenharmony_ci scenePrepared_ = false; 1518bf80f4bSopenharmony_ci return ecs_; 1528bf80f4bSopenharmony_ci} 1538bf80f4bSopenharmony_ci 1548bf80f4bSopenharmony_civoid SceneHolder::Initialize(WeakPtr me) 1558bf80f4bSopenharmony_ci{ 1568bf80f4bSopenharmony_ci me_ = me; 1578bf80f4bSopenharmony_ci InitializeScene(); 1588bf80f4bSopenharmony_ci} 1598bf80f4bSopenharmony_ci 1608bf80f4bSopenharmony_civoid SceneHolder::Uninitialize() 1618bf80f4bSopenharmony_ci{ 1628bf80f4bSopenharmony_ci // Remove callbacks, these are no longer needed. 1638bf80f4bSopenharmony_ci SetInitializeCallback({}, me_); 1648bf80f4bSopenharmony_ci SetSceneLoadedCallback({}, me_); 1658bf80f4bSopenharmony_ci 1668bf80f4bSopenharmony_ci // Move processing to engine thread. 1678bf80f4bSopenharmony_ci UninitializeScene(); 1688bf80f4bSopenharmony_ci} 1698bf80f4bSopenharmony_civoid SceneHolder::SetRenderSize(uint32_t width, uint32_t height, uint64_t cameraHandle) 1708bf80f4bSopenharmony_ci{ 1718bf80f4bSopenharmony_ci // Render size changed, schedule update engine thread. 1728bf80f4bSopenharmony_ci UpdateViewportSize(width, height, cameraHandle); 1738bf80f4bSopenharmony_ci} 1748bf80f4bSopenharmony_ci 1758bf80f4bSopenharmony_civoid SceneHolder::SetCameraTarget( 1768bf80f4bSopenharmony_ci const SCENE_NS::ICamera::Ptr& camera, BASE_NS::Math::UVec2 size, RENDER_NS::RenderHandleReference ref) 1778bf80f4bSopenharmony_ci{ 1788bf80f4bSopenharmony_ci auto cameraEnt = interface_cast<SCENE_NS::IEcsObject>(camera)->GetEntity(); 1798bf80f4bSopenharmony_ci 1808bf80f4bSopenharmony_ci CameraData::Ptr cd; 1818bf80f4bSopenharmony_ci for (auto c : cameras_) { 1828bf80f4bSopenharmony_ci if (c->entity == cameraEnt) { 1838bf80f4bSopenharmony_ci cd = c; 1848bf80f4bSopenharmony_ci break; 1858bf80f4bSopenharmony_ci } 1868bf80f4bSopenharmony_ci } 1878bf80f4bSopenharmony_ci if (!cd) { 1888bf80f4bSopenharmony_ci // invalid. 1898bf80f4bSopenharmony_ci return; 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci cd->width = size.x; 1928bf80f4bSopenharmony_ci cd->height = size.y; 1938bf80f4bSopenharmony_ci if (!ref) { 1948bf80f4bSopenharmony_ci cd->colorImage = {}; 1958bf80f4bSopenharmony_ci cd->ownsColorImage = true; 1968bf80f4bSopenharmony_ci RecreateOutputTexture(cd); 1978bf80f4bSopenharmony_ci } else { 1988bf80f4bSopenharmony_ci cd->colorImage = ref; 1998bf80f4bSopenharmony_ci cd->ownsColorImage = false; 2008bf80f4bSopenharmony_ci } 2018bf80f4bSopenharmony_ci cd->updateTargets = true; 2028bf80f4bSopenharmony_ci} 2038bf80f4bSopenharmony_ci 2048bf80f4bSopenharmony_civoid SceneHolder::RequestReload() 2058bf80f4bSopenharmony_ci{ 2068bf80f4bSopenharmony_ci LoadScene(); 2078bf80f4bSopenharmony_ci} 2088bf80f4bSopenharmony_ci 2098bf80f4bSopenharmony_civoid SceneHolder::Load(const BASE_NS::string& uri) 2108bf80f4bSopenharmony_ci{ 2118bf80f4bSopenharmony_ci // Scene systems graph uri changed, schedule update to engine thread. 2128bf80f4bSopenharmony_ci if (sceneUri_ != uri) { 2138bf80f4bSopenharmony_ci sceneUri_ = uri; 2148bf80f4bSopenharmony_ci 2158bf80f4bSopenharmony_ci RequestReload(); 2168bf80f4bSopenharmony_ci } 2178bf80f4bSopenharmony_ci} 2188bf80f4bSopenharmony_ci 2198bf80f4bSopenharmony_civoid SceneHolder::SetSystemGraphUri(const string& uri) 2208bf80f4bSopenharmony_ci{ 2218bf80f4bSopenharmony_ci // Scene systems graph uri changed, schedule update to engine thread. 2228bf80f4bSopenharmony_ci if (uri != sceneSystemGraphUri_) { 2238bf80f4bSopenharmony_ci sceneSystemGraphUri_ = uri; 2248bf80f4bSopenharmony_ci 2258bf80f4bSopenharmony_ci RequestReload(); 2268bf80f4bSopenharmony_ci } 2278bf80f4bSopenharmony_ci} 2288bf80f4bSopenharmony_ci 2298bf80f4bSopenharmony_civoid SceneHolder::SetInitializeCallback(ISceneInitialized::Ptr callback, SceneHolder::WeakPtr weakMe) 2308bf80f4bSopenharmony_ci{ 2318bf80f4bSopenharmony_ci // Schedule update of callback to engine thread. 2328bf80f4bSopenharmony_ci sceneInitializedCallback_ = callback; 2338bf80f4bSopenharmony_ci} 2348bf80f4bSopenharmony_ci 2358bf80f4bSopenharmony_civoid SceneHolder::SetSceneLoadedCallback(ISceneLoaded::Ptr callback, SceneHolder::WeakPtr weakMe) 2368bf80f4bSopenharmony_ci{ 2378bf80f4bSopenharmony_ci // Schedule update of callback to engine thread. 2388bf80f4bSopenharmony_ci sceneLoadedCallback_ = callback; 2398bf80f4bSopenharmony_ci} 2408bf80f4bSopenharmony_ci 2418bf80f4bSopenharmony_civoid SceneHolder::SetUninitializeCallback(ISceneUninitialized::Ptr callback, SceneHolder::WeakPtr weakMe) 2428bf80f4bSopenharmony_ci{ 2438bf80f4bSopenharmony_ci // Schedule update of callback to engine thread. 2448bf80f4bSopenharmony_ci sceneUninitializedCallback_ = callback; 2458bf80f4bSopenharmony_ci} 2468bf80f4bSopenharmony_ci 2478bf80f4bSopenharmony_civoid SceneHolder::ActivateCamera(const Entity& cameraEntity) const 2488bf80f4bSopenharmony_ci{ 2498bf80f4bSopenharmony_ci if (!(cameraComponentManager_ && EntityUtil::IsValid(cameraEntity))) { 2508bf80f4bSopenharmony_ci CORE_LOG_W("SceneHolder::ActivateCamera: Can not be activated. cameraEntity: %" PRIx64 2518bf80f4bSopenharmony_ci ", cameraComponentManager_: %d, IsValid(cameraEntity): %d", 2528bf80f4bSopenharmony_ci cameraEntity.id, static_cast<bool>(cameraComponentManager_), EntityUtil::IsValid(cameraEntity)); 2538bf80f4bSopenharmony_ci return; 2548bf80f4bSopenharmony_ci } 2558bf80f4bSopenharmony_ci 2568bf80f4bSopenharmony_ci CameraComponent cameraComponent = cameraComponentManager_->Get(cameraEntity); 2578bf80f4bSopenharmony_ci cameraComponent.sceneFlags |= CameraComponent::ACTIVE_RENDER_BIT; 2588bf80f4bSopenharmony_ci cameraComponentManager_->Set(cameraEntity, cameraComponent); 2598bf80f4bSopenharmony_ci} 2608bf80f4bSopenharmony_ci 2618bf80f4bSopenharmony_civoid SceneHolder::DeactivateCamera(const Entity& cameraEntity) const 2628bf80f4bSopenharmony_ci{ 2638bf80f4bSopenharmony_ci if (!(cameraComponentManager_ && EntityUtil::IsValid(cameraEntity))) { 2648bf80f4bSopenharmony_ci CORE_LOG_W("SceneHolder::DeactivateCamera: Can not be deactivated. cameraEntity: %" PRIx64 2658bf80f4bSopenharmony_ci ", cameraComponentManager_: %d, IsValid(cameraEntity): %d", 2668bf80f4bSopenharmony_ci cameraEntity.id, static_cast<bool>(cameraComponentManager_), EntityUtil::IsValid(cameraEntity)); 2678bf80f4bSopenharmony_ci return; 2688bf80f4bSopenharmony_ci } 2698bf80f4bSopenharmony_ci 2708bf80f4bSopenharmony_ci CameraComponent cameraComponent = cameraComponentManager_->Get(cameraEntity); 2718bf80f4bSopenharmony_ci cameraComponent.sceneFlags &= ~(CameraComponent::ACTIVE_RENDER_BIT /* | CameraComponent::MAIN_CAMERA_BIT*/); 2728bf80f4bSopenharmony_ci cameraComponentManager_->Set(cameraEntity, cameraComponent); 2738bf80f4bSopenharmony_ci} 2748bf80f4bSopenharmony_ci 2758bf80f4bSopenharmony_cibool SceneHolder::IsCameraActive(const Entity& cameraEntity) const 2768bf80f4bSopenharmony_ci{ 2778bf80f4bSopenharmony_ci if (!(cameraComponentManager_ && EntityUtil::IsValid(cameraEntity))) { 2788bf80f4bSopenharmony_ci CORE_LOG_W("SceneHolder::DeactivateCamera: Can not be deactivated. cameraEntity: %" PRIx64 2798bf80f4bSopenharmony_ci ", cameraComponentManager_: %d, IsValid(cameraEntity): %d", 2808bf80f4bSopenharmony_ci cameraEntity.id, static_cast<bool>(cameraComponentManager_), EntityUtil::IsValid(cameraEntity)); 2818bf80f4bSopenharmony_ci return false; 2828bf80f4bSopenharmony_ci } 2838bf80f4bSopenharmony_ci 2848bf80f4bSopenharmony_ci CameraComponent cameraComponent = cameraComponentManager_->Get(cameraEntity); 2858bf80f4bSopenharmony_ci return cameraComponent.sceneFlags & (CameraComponent::ACTIVE_RENDER_BIT); 2868bf80f4bSopenharmony_ci} 2878bf80f4bSopenharmony_ci 2888bf80f4bSopenharmony_cibool SceneHolder::InitializeScene() 2898bf80f4bSopenharmony_ci{ 2908bf80f4bSopenharmony_ci graphicsContext3D_ = CreateInstance<CORE3D_NS::IGraphicsContext>( 2918bf80f4bSopenharmony_ci *renderContext_->GetInterface<IClassFactory>(), UID_GRAPHICS_CONTEXT); 2928bf80f4bSopenharmony_ci graphicsContext3D_->Init(); 2938bf80f4bSopenharmony_ci 2948bf80f4bSopenharmony_ci picking_ = GetInstance<CORE3D_NS::IPicking>(*renderContext_->GetInterface<IClassRegister>(), UID_PICKING); 2958bf80f4bSopenharmony_ci 2968bf80f4bSopenharmony_ci // scene loading was attempted before initialization, retry now 2978bf80f4bSopenharmony_ci if (loadSceneFailed_) { 2988bf80f4bSopenharmony_ci loadSceneFailed_ = false; 2998bf80f4bSopenharmony_ci RequestReload(); 3008bf80f4bSopenharmony_ci } else { 3018bf80f4bSopenharmony_ci // business as usual, set up things according build time settings 3028bf80f4bSopenharmony_ci#ifdef INITIALIZE_ECS_IMMEDIATELY 3038bf80f4bSopenharmony_ci ResetScene(true); 3048bf80f4bSopenharmony_ci scenePrepared_ = true; 3058bf80f4bSopenharmony_ci#else 3068bf80f4bSopenharmony_ci ResetScene(false); 3078bf80f4bSopenharmony_ci#endif 3088bf80f4bSopenharmony_ci } 3098bf80f4bSopenharmony_ci 3108bf80f4bSopenharmony_ci // This is one-time init. 3118bf80f4bSopenharmony_ci return false; 3128bf80f4bSopenharmony_ci} 3138bf80f4bSopenharmony_ci 3148bf80f4bSopenharmony_ciBASE_NS::vector<CORE_NS::Entity> SceneHolder::RenderCameras() 3158bf80f4bSopenharmony_ci{ 3168bf80f4bSopenharmony_ci // nobody has asked for updates, yet 3178bf80f4bSopenharmony_ci if (!ecs_ /*|| isReadyForNewFrame_.empty()*/) { 3188bf80f4bSopenharmony_ci return {}; 3198bf80f4bSopenharmony_ci } 3208bf80f4bSopenharmony_ci 3218bf80f4bSopenharmony_ci bool busy = false; 3228bf80f4bSopenharmony_ci BASE_NS::vector<CORE_NS::Entity> activeCameras; 3238bf80f4bSopenharmony_ci for (auto& camera : cameras_) { 3248bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(camera->entity)) 3258bf80f4bSopenharmony_ci continue; 3268bf80f4bSopenharmony_ci 3278bf80f4bSopenharmony_ci if (auto cc = cameraComponentManager_->Read(camera->entity)) { 3288bf80f4bSopenharmony_ci if (cc->sceneFlags & CameraComponent::SceneFlagBits::ACTIVE_RENDER_BIT) { 3298bf80f4bSopenharmony_ci if (camera->updateTargets) { 3308bf80f4bSopenharmony_ci UpdateCameraRenderTarget(camera); 3318bf80f4bSopenharmony_ci camera->updateTargets = false; 3328bf80f4bSopenharmony_ci } 3338bf80f4bSopenharmony_ci activeCameras.push_back(camera->entity); 3348bf80f4bSopenharmony_ci } 3358bf80f4bSopenharmony_ci } 3368bf80f4bSopenharmony_ci } 3378bf80f4bSopenharmony_ci isRunningFrame_ = true; 3388bf80f4bSopenharmony_ci // Tick frame. One camera could have static view while other is moving 3398bf80f4bSopenharmony_ci IEcs* ecs = ecs_.get(); 3408bf80f4bSopenharmony_ci ecs->ProcessEvents(); 3418bf80f4bSopenharmony_ci using namespace std::chrono; 3428bf80f4bSopenharmony_ci const auto currentTime = 3438bf80f4bSopenharmony_ci static_cast<uint64_t>(duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count()); 3448bf80f4bSopenharmony_ci if (firstTime_ == ~0u) { 3458bf80f4bSopenharmony_ci previousFrameTime_ = firstTime_ = currentTime; 3468bf80f4bSopenharmony_ci } 3478bf80f4bSopenharmony_ci auto deltaTime = currentTime - previousFrameTime_; 3488bf80f4bSopenharmony_ci constexpr auto limitHz = duration_cast<microseconds>(duration<float, std::ratio<1, 15u>>(1)).count(); 3498bf80f4bSopenharmony_ci if (deltaTime > limitHz) { 3508bf80f4bSopenharmony_ci deltaTime = limitHz; // clampthe time step to no longer than 15hz. 3518bf80f4bSopenharmony_ci } 3528bf80f4bSopenharmony_ci previousFrameTime_ = currentTime; 3538bf80f4bSopenharmony_ci const uint64_t totalTime = currentTime - firstTime_; 3548bf80f4bSopenharmony_ci const bool needsRender = ecs->Update(totalTime, deltaTime); 3558bf80f4bSopenharmony_ci ecs->ProcessEvents(); 3568bf80f4bSopenharmony_ci auto renderHandles = graphicsContext3D_->GetRenderNodeGraphs(*ecs_); 3578bf80f4bSopenharmony_ci 3588bf80f4bSopenharmony_ci if ((needsRender) && (!renderHandles.empty())) { 3598bf80f4bSopenharmony_ci // The scene needs to be rendered. 3608bf80f4bSopenharmony_ci RENDER_NS::IRenderer& renderer = renderContext_->GetRenderer(); 3618bf80f4bSopenharmony_ci renderer.RenderDeferred(renderHandles); 3628bf80f4bSopenharmony_ci } else { 3638bf80f4bSopenharmony_ci // did not render anything. 3648bf80f4bSopenharmony_ci bool nr = needsRender; 3658bf80f4bSopenharmony_ci activeCameras.clear(); 3668bf80f4bSopenharmony_ci } 3678bf80f4bSopenharmony_ci isRunningFrame_ = false; 3688bf80f4bSopenharmony_ci 3698bf80f4bSopenharmony_ci if (requiresEventProcessing_) { 3708bf80f4bSopenharmony_ci ProcessEvents(); 3718bf80f4bSopenharmony_ci } 3728bf80f4bSopenharmony_ci 3738bf80f4bSopenharmony_ci // Schedule new update to scene. 3748bf80f4bSopenharmony_ci return activeCameras; 3758bf80f4bSopenharmony_ci} 3768bf80f4bSopenharmony_ci 3778bf80f4bSopenharmony_cibool SceneHolder::UninitializeScene() 3788bf80f4bSopenharmony_ci{ 3798bf80f4bSopenharmony_ci ResetScene(); 3808bf80f4bSopenharmony_ci 3818bf80f4bSopenharmony_ci if (ecs_) { 3828bf80f4bSopenharmony_ci ecs_->Uninitialize(); 3838bf80f4bSopenharmony_ci ecs_.reset(); 3848bf80f4bSopenharmony_ci } 3858bf80f4bSopenharmony_ci 3868bf80f4bSopenharmony_ci if (sceneUninitializedCallback_) { 3878bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 3888bf80f4bSopenharmony_ci [](auto callback) { 3898bf80f4bSopenharmony_ci callback->Invoke(); 3908bf80f4bSopenharmony_ci return false; 3918bf80f4bSopenharmony_ci }, 3928bf80f4bSopenharmony_ci sceneUninitializedCallback_), 3938bf80f4bSopenharmony_ci false); 3948bf80f4bSopenharmony_ci } 3958bf80f4bSopenharmony_ci 3968bf80f4bSopenharmony_ci sceneInitializedCallback_.reset(); 3978bf80f4bSopenharmony_ci sceneUpdatedCallback_.reset(); 3988bf80f4bSopenharmony_ci sceneUninitializedCallback_.reset(); 3998bf80f4bSopenharmony_ci 4008bf80f4bSopenharmony_ci return false; 4018bf80f4bSopenharmony_ci} 4028bf80f4bSopenharmony_ci 4038bf80f4bSopenharmony_civoid SceneHolder::ProcessEvents() 4048bf80f4bSopenharmony_ci{ 4058bf80f4bSopenharmony_ci if (isRunningFrame_) { 4068bf80f4bSopenharmony_ci requiresEventProcessing_ = true; 4078bf80f4bSopenharmony_ci return; 4088bf80f4bSopenharmony_ci } 4098bf80f4bSopenharmony_ci 4108bf80f4bSopenharmony_ci if (ecsListener_ && ecsListener_->IsCallbackActive()) { 4118bf80f4bSopenharmony_ci requiresEventProcessing_ = true; 4128bf80f4bSopenharmony_ci return; 4138bf80f4bSopenharmony_ci } 4148bf80f4bSopenharmony_ci 4158bf80f4bSopenharmony_ci if (ecs_) { 4168bf80f4bSopenharmony_ci ecs_->ProcessEvents(); 4178bf80f4bSopenharmony_ci requiresEventProcessing_ = false; 4188bf80f4bSopenharmony_ci } 4198bf80f4bSopenharmony_ci} 4208bf80f4bSopenharmony_ci 4218bf80f4bSopenharmony_cibool SceneHolder::CreateDefaultEcs() 4228bf80f4bSopenharmony_ci{ 4238bf80f4bSopenharmony_ci if (!renderContext_) { 4248bf80f4bSopenharmony_ci CORE_LOG_W("%s: Graphics contexts is not available, can not create ecs", __func__); 4258bf80f4bSopenharmony_ci return false; 4268bf80f4bSopenharmony_ci } 4278bf80f4bSopenharmony_ci 4288bf80f4bSopenharmony_ci auto& engine = renderContext_->GetEngine(); 4298bf80f4bSopenharmony_ci 4308bf80f4bSopenharmony_ci ecs_ = engine.CreateEcs(); 4318bf80f4bSopenharmony_ci ecs_->SetRenderMode(renderMode_); 4328bf80f4bSopenharmony_ci 4338bf80f4bSopenharmony_ci if (!ecsListener_) { 4348bf80f4bSopenharmony_ci ecsListener_ = BASE_NS::shared_ptr<SCENE_NS::EcsListener>(new SCENE_NS::EcsListener()); 4358bf80f4bSopenharmony_ci } 4368bf80f4bSopenharmony_ci ecsListener_->SetEcs(ecs_); 4378bf80f4bSopenharmony_ci 4388bf80f4bSopenharmony_ci // Get systemGraphLoader factory from global plugin registry. 4398bf80f4bSopenharmony_ci auto* factory = GetInstance<ISystemGraphLoaderFactory>(UID_SYSTEM_GRAPH_LOADER); 4408bf80f4bSopenharmony_ci auto systemGraphLoader = factory->Create(engine.GetFileManager()); 4418bf80f4bSopenharmony_ci 4428bf80f4bSopenharmony_ci // First try to load project-specific system graph. 4438bf80f4bSopenharmony_ci auto result = sceneSystemGraphUri_.empty() ? false : systemGraphLoader->Load(sceneSystemGraphUri_, *ecs_).success; 4448bf80f4bSopenharmony_ci 4458bf80f4bSopenharmony_ci if (!result) { 4468bf80f4bSopenharmony_ci // Fall back to default graph. 4478bf80f4bSopenharmony_ci systemGraphLoader->Load("rofs3D://systemGraph.json", *ecs_); 4488bf80f4bSopenharmony_ci } 4498bf80f4bSopenharmony_ci 4508bf80f4bSopenharmony_ci auto renderPreprocessorSystem = GetSystem<IRenderPreprocessorSystem>(*ecs_); 4518bf80f4bSopenharmony_ci 4528bf80f4bSopenharmony_ci string dataStorePrefix = "renderDataStore:" + GetUniqueName(); 4538bf80f4bSopenharmony_ci 4548bf80f4bSopenharmony_ci auto& renderDataStoreManager = renderContext_->GetRenderDataStoreManager(); 4558bf80f4bSopenharmony_ci 4568bf80f4bSopenharmony_ci auto sceneDataStore = dataStorePrefix + "RenderDataStoreDefaultScene"; 4578bf80f4bSopenharmony_ci auto cameraDataStore = dataStorePrefix + "RenderDataStoreDefaultCamera"; 4588bf80f4bSopenharmony_ci auto lightDataStore = dataStorePrefix + "RenderDataStoreDefaultLight"; 4598bf80f4bSopenharmony_ci auto materialDataStore = dataStorePrefix + "RenderDataStoreDefaultMaterial"; 4608bf80f4bSopenharmony_ci auto morphDataStore = dataStorePrefix + "RenderDataStoreMorph"; 4618bf80f4bSopenharmony_ci 4628bf80f4bSopenharmony_ci if (renderPreprocessorSystem) { 4638bf80f4bSopenharmony_ci IRenderPreprocessorSystem::Properties props; 4648bf80f4bSopenharmony_ci props.dataStorePrefix = dataStorePrefix; 4658bf80f4bSopenharmony_ci props.dataStoreScene = sceneDataStore; 4668bf80f4bSopenharmony_ci props.dataStoreCamera = cameraDataStore; 4678bf80f4bSopenharmony_ci props.dataStoreLight = lightDataStore; 4688bf80f4bSopenharmony_ci props.dataStoreMaterial = materialDataStore; 4698bf80f4bSopenharmony_ci props.dataStoreMorph = morphDataStore; 4708bf80f4bSopenharmony_ci 4718bf80f4bSopenharmony_ci *ScopedHandle<IRenderPreprocessorSystem::Properties>(renderPreprocessorSystem->GetProperties()) = props; 4728bf80f4bSopenharmony_ci } 4738bf80f4bSopenharmony_ci 4748bf80f4bSopenharmony_ci if (auto callback = ecsInitializationCallback_.lock()) { 4758bf80f4bSopenharmony_ci auto result = callback->Invoke(ecs_); 4768bf80f4bSopenharmony_ci if (!result) { 4778bf80f4bSopenharmony_ci CORE_LOG_W("Ecs initialization failed in the callback, expect trouble"); 4788bf80f4bSopenharmony_ci } 4798bf80f4bSopenharmony_ci } 4808bf80f4bSopenharmony_ci 4818bf80f4bSopenharmony_ci ecs_->Initialize(); 4828bf80f4bSopenharmony_ci 4838bf80f4bSopenharmony_ci animationComponentManager_ = CORE_NS::GetManager<CORE3D_NS::IAnimationComponentManager>(*ecs_); 4848bf80f4bSopenharmony_ci cameraComponentManager_ = GetManager<CORE3D_NS::ICameraComponentManager>(*ecs_); 4858bf80f4bSopenharmony_ci envComponentManager_ = GetManager<CORE3D_NS::IEnvironmentComponentManager>(*ecs_); 4868bf80f4bSopenharmony_ci layerComponentManager_ = GetManager<CORE3D_NS::ILayerComponentManager>(*ecs_); 4878bf80f4bSopenharmony_ci lightComponentManager_ = GetManager<CORE3D_NS::ILightComponentManager>(*ecs_); 4888bf80f4bSopenharmony_ci materialComponentManager_ = GetManager<CORE3D_NS::IMaterialComponentManager>(*ecs_); 4898bf80f4bSopenharmony_ci meshComponentManager_ = GetManager<CORE3D_NS::IMeshComponentManager>(*ecs_); 4908bf80f4bSopenharmony_ci nameComponentManager_ = GetManager<CORE3D_NS::INameComponentManager>(*ecs_); 4918bf80f4bSopenharmony_ci nodeComponentManager_ = GetManager<CORE3D_NS::INodeComponentManager>(*ecs_); 4928bf80f4bSopenharmony_ci renderMeshComponentManager_ = GetManager<CORE3D_NS::IRenderMeshComponentManager>(*ecs_); 4938bf80f4bSopenharmony_ci rhComponentManager_ = GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs_); 4948bf80f4bSopenharmony_ci transformComponentManager_ = GetManager<CORE3D_NS::ITransformComponentManager>(*ecs_); 4958bf80f4bSopenharmony_ci uriComponentManager_ = GetManager<CORE3D_NS::IUriComponentManager>(*ecs_); 4968bf80f4bSopenharmony_ci 4978bf80f4bSopenharmony_ci if (animationComponentManager_) { 4988bf80f4bSopenharmony_ci animationQuery_.reset(new CORE_NS::ComponentQuery()); 4998bf80f4bSopenharmony_ci animationQuery_->SetEcsListenersEnabled(true); 5008bf80f4bSopenharmony_ci const ComponentQuery::Operation operations[] = { { *nodeComponentManager_, 5018bf80f4bSopenharmony_ci ComponentQuery::Operation::OPTIONAL }, 5028bf80f4bSopenharmony_ci { *nameComponentManager_, ComponentQuery::Operation::OPTIONAL } }; 5038bf80f4bSopenharmony_ci animationQuery_->SetupQuery(*animationComponentManager_, operations); 5048bf80f4bSopenharmony_ci } 5058bf80f4bSopenharmony_ci 5068bf80f4bSopenharmony_ci if (meshComponentManager_) { 5078bf80f4bSopenharmony_ci meshQuery_.reset(new CORE_NS::ComponentQuery()); 5088bf80f4bSopenharmony_ci meshQuery_->SetEcsListenersEnabled(true); 5098bf80f4bSopenharmony_ci const ComponentQuery::Operation operations[] = { { *nodeComponentManager_, 5108bf80f4bSopenharmony_ci ComponentQuery::Operation::OPTIONAL }, 5118bf80f4bSopenharmony_ci { *nameComponentManager_, ComponentQuery::Operation::OPTIONAL } }; 5128bf80f4bSopenharmony_ci meshQuery_->SetupQuery(*meshComponentManager_, operations); 5138bf80f4bSopenharmony_ci } 5148bf80f4bSopenharmony_ci 5158bf80f4bSopenharmony_ci if (materialComponentManager_) { 5168bf80f4bSopenharmony_ci materialQuery_.reset(new CORE_NS::ComponentQuery()); 5178bf80f4bSopenharmony_ci materialQuery_->SetEcsListenersEnabled(true); 5188bf80f4bSopenharmony_ci const ComponentQuery::Operation operations[] = { { *nodeComponentManager_, 5198bf80f4bSopenharmony_ci ComponentQuery::Operation::OPTIONAL }, 5208bf80f4bSopenharmony_ci { *nameComponentManager_, ComponentQuery::Operation::OPTIONAL }, 5218bf80f4bSopenharmony_ci { *uriComponentManager_, ComponentQuery::Operation::OPTIONAL } }; 5228bf80f4bSopenharmony_ci materialQuery_->SetupQuery(*materialComponentManager_, operations); 5238bf80f4bSopenharmony_ci } 5248bf80f4bSopenharmony_ci nodeSystem_ = static_cast<CORE3D_NS::INodeSystem*>(ecs_->GetSystem(CORE3D_NS::INodeSystem::UID)); 5258bf80f4bSopenharmony_ci return true; 5268bf80f4bSopenharmony_ci} 5278bf80f4bSopenharmony_ci 5288bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateCamera(const BASE_NS::string& name, uint32_t flagBits) 5298bf80f4bSopenharmony_ci{ 5308bf80f4bSopenharmony_ci return CreateCamera({}, name, flagBits); 5318bf80f4bSopenharmony_ci} 5328bf80f4bSopenharmony_ci 5338bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateCamera(const BASE_NS::string& path, const BASE_NS::string& name, uint32_t flagBits) 5348bf80f4bSopenharmony_ci{ 5358bf80f4bSopenharmony_ci if (ecs_) { 5368bf80f4bSopenharmony_ci auto pathWithoutRootNode = RemoveRootNodeFromPath(path); 5378bf80f4bSopenharmony_ci 5388bf80f4bSopenharmony_ci // Create camera. Scene util produces an invalid node so set up our camera from node system ourself 5398bf80f4bSopenharmony_ci auto nodeSystem = GetSystem<INodeSystem>(*ecs_); 5408bf80f4bSopenharmony_ci auto node = nodeSystem->CreateNode(); 5418bf80f4bSopenharmony_ci auto entity = node->GetEntity(); 5428bf80f4bSopenharmony_ci 5438bf80f4bSopenharmony_ci CORE3D_NS::ISceneNode* parent = nullptr; 5448bf80f4bSopenharmony_ci if (pathWithoutRootNode.empty()) { 5458bf80f4bSopenharmony_ci parent = rootNode_; 5468bf80f4bSopenharmony_ci } else { 5478bf80f4bSopenharmony_ci parent = rootNode_->LookupNodeByPath(pathWithoutRootNode); 5488bf80f4bSopenharmony_ci } 5498bf80f4bSopenharmony_ci 5508bf80f4bSopenharmony_ci CORE_ASSERT(parent); 5518bf80f4bSopenharmony_ci 5528bf80f4bSopenharmony_ci node->SetParent(*parent); 5538bf80f4bSopenharmony_ci node->SetName(name); 5548bf80f4bSopenharmony_ci 5558bf80f4bSopenharmony_ci auto tcm = GetManager<ITransformComponentManager>(*ecs_); 5568bf80f4bSopenharmony_ci TransformComponent tc; 5578bf80f4bSopenharmony_ci tc.position = Math::Vec3(0.0f, 0.0f, 2.5f); 5588bf80f4bSopenharmony_ci tc.rotation = {}; 5598bf80f4bSopenharmony_ci tcm->Set(entity, tc); 5608bf80f4bSopenharmony_ci 5618bf80f4bSopenharmony_ci CameraComponent cc; 5628bf80f4bSopenharmony_ci cc.sceneFlags |= CameraComponent::SceneFlagBits::ACTIVE_RENDER_BIT; 5638bf80f4bSopenharmony_ci cc.projection = CameraComponent::Projection::PERSPECTIVE; 5648bf80f4bSopenharmony_ci cc.yFov = Math::DEG2RAD * 60.f; 5658bf80f4bSopenharmony_ci cc.zNear = 0.1f; 5668bf80f4bSopenharmony_ci cc.zFar = 100.f; 5678bf80f4bSopenharmony_ci cc.sceneFlags |= flagBits; 5688bf80f4bSopenharmony_ci cameraComponentManager_->Set(entity, cc); 5698bf80f4bSopenharmony_ci 5708bf80f4bSopenharmony_ci cameras_.emplace_back(CameraData::Create(entity)); 5718bf80f4bSopenharmony_ci return entity; 5728bf80f4bSopenharmony_ci } else { 5738bf80f4bSopenharmony_ci CORE_LOG_E("%s: Ecs not available, can not create camera %s", __func__, name.c_str()); 5748bf80f4bSopenharmony_ci } 5758bf80f4bSopenharmony_ci return CORE_NS::Entity(); 5768bf80f4bSopenharmony_ci} 5778bf80f4bSopenharmony_ci 5788bf80f4bSopenharmony_civoid SceneHolder::SetDefaultCamera() 5798bf80f4bSopenharmony_ci{ 5808bf80f4bSopenharmony_ci if (cameraComponentManager_) { 5818bf80f4bSopenharmony_ci auto cameraCount = cameraComponentManager_->GetComponentCount(); 5828bf80f4bSopenharmony_ci while (cameraCount) { 5838bf80f4bSopenharmony_ci --cameraCount; 5848bf80f4bSopenharmony_ci // if the scene already contains main camera, respect it 5858bf80f4bSopenharmony_ci if (cameraComponentManager_->Get(cameraComponentManager_->GetEntity(cameraCount)).sceneFlags & 5868bf80f4bSopenharmony_ci CameraComponent::MAIN_CAMERA_BIT) { 5878bf80f4bSopenharmony_ci auto entity = cameraComponentManager_->GetEntity(cameraCount); 5888bf80f4bSopenharmony_ci cameras_.emplace_back(CameraData::Create(entity)); 5898bf80f4bSopenharmony_ci defaultCameraEntity_ = entity; 5908bf80f4bSopenharmony_ci SetMainCamera(entity); 5918bf80f4bSopenharmony_ci return; 5928bf80f4bSopenharmony_ci } 5938bf80f4bSopenharmony_ci } 5948bf80f4bSopenharmony_ci } 5958bf80f4bSopenharmony_ci} 5968bf80f4bSopenharmony_ci 5978bf80f4bSopenharmony_civoid SceneHolder::SetMainCamera(const Entity& entity) 5988bf80f4bSopenharmony_ci{ 5998bf80f4bSopenharmony_ci if (cameras_.empty() || (mainCamera_ && entity == mainCamera_->entity)) { 6008bf80f4bSopenharmony_ci return; 6018bf80f4bSopenharmony_ci } 6028bf80f4bSopenharmony_ci 6038bf80f4bSopenharmony_ci if (mainCamera_ && cameraComponentManager_ && EntityUtil::IsValid(mainCamera_->entity)) { 6048bf80f4bSopenharmony_ci bool isAlive = ecs_->GetEntityManager().IsAlive(mainCamera_->entity); 6058bf80f4bSopenharmony_ci if (isAlive) { 6068bf80f4bSopenharmony_ci // Mark previous main camera as inactive. 6078bf80f4bSopenharmony_ci CameraComponent cameraComponent = cameraComponentManager_->Get(mainCamera_->entity); 6088bf80f4bSopenharmony_ci cameraComponent.sceneFlags &= ~CameraComponent::MAIN_CAMERA_BIT; 6098bf80f4bSopenharmony_ci cameraComponentManager_->Set(mainCamera_->entity, cameraComponent); 6108bf80f4bSopenharmony_ci } 6118bf80f4bSopenharmony_ci } 6128bf80f4bSopenharmony_ci 6138bf80f4bSopenharmony_ci mainCamera_ = {}; 6148bf80f4bSopenharmony_ci 6158bf80f4bSopenharmony_ci for (auto& camera : cameras_) { 6168bf80f4bSopenharmony_ci if (camera->entity == entity) { 6178bf80f4bSopenharmony_ci mainCamera_ = camera; 6188bf80f4bSopenharmony_ci break; 6198bf80f4bSopenharmony_ci } 6208bf80f4bSopenharmony_ci } 6218bf80f4bSopenharmony_ci 6228bf80f4bSopenharmony_ci if (!mainCamera_) { 6238bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 6248bf80f4bSopenharmony_ci CORE_LOG_W("%s: was not able to set camera for: %" PRIx64 " ", __func__, entity.id); 6258bf80f4bSopenharmony_ci } 6268bf80f4bSopenharmony_ci return; 6278bf80f4bSopenharmony_ci } 6288bf80f4bSopenharmony_ci 6298bf80f4bSopenharmony_ci if (cameraComponentManager_ && EntityUtil::IsValid(mainCamera_->entity)) { 6308bf80f4bSopenharmony_ci // Mark new camera as active. 6318bf80f4bSopenharmony_ci CameraComponent cameraComponent = cameraComponentManager_->Get(mainCamera_->entity); 6328bf80f4bSopenharmony_ci cameraComponent.sceneFlags |= CameraComponent::MAIN_CAMERA_BIT; 6338bf80f4bSopenharmony_ci cameraComponentManager_->Set(mainCamera_->entity, cameraComponent); 6348bf80f4bSopenharmony_ci UpdateViewportSize(mainCamera_->width, mainCamera_->height, mainCamera_->entity.id); 6358bf80f4bSopenharmony_ci } 6368bf80f4bSopenharmony_ci} 6378bf80f4bSopenharmony_ci 6388bf80f4bSopenharmony_civoid SceneHolder::AddCamera(const CORE_NS::Entity& entity) 6398bf80f4bSopenharmony_ci{ 6408bf80f4bSopenharmony_ci for (auto c : cameras_) { 6418bf80f4bSopenharmony_ci if (c->entity == entity) { 6428bf80f4bSopenharmony_ci return; 6438bf80f4bSopenharmony_ci } 6448bf80f4bSopenharmony_ci } 6458bf80f4bSopenharmony_ci cameras_.emplace_back(CameraData::Create(entity)); 6468bf80f4bSopenharmony_ci} 6478bf80f4bSopenharmony_ci 6488bf80f4bSopenharmony_civoid SceneHolder::RemoveCamera(const CORE_NS::Entity& entity) 6498bf80f4bSopenharmony_ci{ 6508bf80f4bSopenharmony_ci auto it = std::find_if(cameras_.begin(), cameras_.end(), [entity](const auto& item) { 6518bf80f4bSopenharmony_ci // Check if camera entities are the same. 6528bf80f4bSopenharmony_ci return item->entity == entity; 6538bf80f4bSopenharmony_ci }); 6548bf80f4bSopenharmony_ci 6558bf80f4bSopenharmony_ci if (it != cameras_.end()) { 6568bf80f4bSopenharmony_ci cameras_.erase(it); 6578bf80f4bSopenharmony_ci } 6588bf80f4bSopenharmony_ci} 6598bf80f4bSopenharmony_ci 6608bf80f4bSopenharmony_civoid SceneHolder::UpdateViewportSize(uint32_t width, uint32_t height, uint64_t cameraHandle) 6618bf80f4bSopenharmony_ci{ 6628bf80f4bSopenharmony_ci CORE_LOG_D("%s: w: %u h: %u", __func__, width, height); 6638bf80f4bSopenharmony_ci // these would be never valid as render target so use some default values to make sure that buffers are prepared 6648bf80f4bSopenharmony_ci if (width == 0) { 6658bf80f4bSopenharmony_ci width = 128; // 128 default width 6668bf80f4bSopenharmony_ci } 6678bf80f4bSopenharmony_ci if (height == 0) { 6688bf80f4bSopenharmony_ci height = 128; // // 128 default height 6698bf80f4bSopenharmony_ci } 6708bf80f4bSopenharmony_ci 6718bf80f4bSopenharmony_ci if (ecs_) { 6728bf80f4bSopenharmony_ci if (cameraHandle == 0 && !cameras_.empty()) { 6738bf80f4bSopenharmony_ci // short circuit defaut camera 6748bf80f4bSopenharmony_ci cameraHandle = cameras_.front()->entity.id; 6758bf80f4bSopenharmony_ci } 6768bf80f4bSopenharmony_ci 6778bf80f4bSopenharmony_ci // Make sure that render target will be updated 6788bf80f4bSopenharmony_ci // ToDo: Clean this up to select the correct camera instance 6798bf80f4bSopenharmony_ci CameraData::Ptr camera; 6808bf80f4bSopenharmony_ci 6818bf80f4bSopenharmony_ci for (auto& c : cameras_) { 6828bf80f4bSopenharmony_ci if (c->entity.id == cameraHandle) { 6838bf80f4bSopenharmony_ci camera = c; 6848bf80f4bSopenharmony_ci break; 6858bf80f4bSopenharmony_ci } 6868bf80f4bSopenharmony_ci } 6878bf80f4bSopenharmony_ci if (!camera) { 6888bf80f4bSopenharmony_ci return; 6898bf80f4bSopenharmony_ci } 6908bf80f4bSopenharmony_ci if (!camera->ownsColorImage) { 6918bf80f4bSopenharmony_ci // we don't own the bitmap so. 6928bf80f4bSopenharmony_ci return; 6938bf80f4bSopenharmony_ci } 6948bf80f4bSopenharmony_ci 6958bf80f4bSopenharmony_ci camera->width = width; 6968bf80f4bSopenharmony_ci camera->height = height; 6978bf80f4bSopenharmony_ci RecreateOutputTexture(camera); 6988bf80f4bSopenharmony_ci 6998bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(camera->entity)) { 7008bf80f4bSopenharmony_ci return; 7018bf80f4bSopenharmony_ci } 7028bf80f4bSopenharmony_ci camera->updateTargets = true; 7038bf80f4bSopenharmony_ci ecs_->RequestRender(); 7048bf80f4bSopenharmony_ci } 7058bf80f4bSopenharmony_ci} 7068bf80f4bSopenharmony_ci 7078bf80f4bSopenharmony_civoid SceneHolder::RecreateOutputTexture(CameraData::Ptr camera) 7088bf80f4bSopenharmony_ci{ 7098bf80f4bSopenharmony_ci if ((renderContext_) && (camera)) { 7108bf80f4bSopenharmony_ci if (camera->ownsColorImage) { 7118bf80f4bSopenharmony_ci camera->colorImage = renderContext_->GetDevice().GetGpuResourceManager().Create( 7128bf80f4bSopenharmony_ci GetColorImageDesc(camera->width, camera->height)); 7138bf80f4bSopenharmony_ci#ifdef SCENE_PLUGIN_CREATE_IMPLICIT_DEPTH_TARGET 7148bf80f4bSopenharmony_ci camera->depthImage = renderContext_->GetDevice().GetGpuResourceManager().Create( 7158bf80f4bSopenharmony_ci GetDepthImageDesc(camera->width, camera->height)); 7168bf80f4bSopenharmony_ci#endif 7178bf80f4bSopenharmony_ci } 7188bf80f4bSopenharmony_ci } 7198bf80f4bSopenharmony_ci} 7208bf80f4bSopenharmony_ci 7218bf80f4bSopenharmony_cibool SceneHolder::UpdateCameraRenderTarget(CameraData::Ptr camera) 7228bf80f4bSopenharmony_ci{ 7238bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(camera->entity)) 7248bf80f4bSopenharmony_ci return false; 7258bf80f4bSopenharmony_ci 7268bf80f4bSopenharmony_ci if (auto cc = cameraComponentManager_->Write(camera->entity)) { 7278bf80f4bSopenharmony_ci auto& em = ecs_->GetEntityManager(); 7288bf80f4bSopenharmony_ci cc->renderResolution[0] = static_cast<float>(camera->width); 7298bf80f4bSopenharmony_ci cc->renderResolution[1] = static_cast<float>(camera->height); 7308bf80f4bSopenharmony_ci cc->customColorTargets = { GetOrCreateEntityReference(em, *rhComponentManager_, camera->colorImage) }; 7318bf80f4bSopenharmony_ci if (camera->depthImage) { 7328bf80f4bSopenharmony_ci cc->customDepthTarget = GetOrCreateEntityReference(em, *rhComponentManager_, camera->depthImage); 7338bf80f4bSopenharmony_ci } 7348bf80f4bSopenharmony_ci if (cc->sceneFlags & CameraComponent::SceneFlagBits::ACTIVE_RENDER_BIT) { 7358bf80f4bSopenharmony_ci // please render also. 7368bf80f4bSopenharmony_ci return true; 7378bf80f4bSopenharmony_ci } 7388bf80f4bSopenharmony_ci } 7398bf80f4bSopenharmony_ci // no render. 7408bf80f4bSopenharmony_ci return false; 7418bf80f4bSopenharmony_ci} 7428bf80f4bSopenharmony_ci 7438bf80f4bSopenharmony_civoid SceneHolder::ResetScene(bool initialize) 7448bf80f4bSopenharmony_ci{ 7458bf80f4bSopenharmony_ci bool wasScenePrepared = scenePrepared_; 7468bf80f4bSopenharmony_ci scenePrepared_ = false; 7478bf80f4bSopenharmony_ci if (wasScenePrepared && initialize) { 7488bf80f4bSopenharmony_ci return; 7498bf80f4bSopenharmony_ci } 7508bf80f4bSopenharmony_ci 7518bf80f4bSopenharmony_ci SetMainCamera({}); 7528bf80f4bSopenharmony_ci cameras_.clear(); 7538bf80f4bSopenharmony_ci 7548bf80f4bSopenharmony_ci animations_.clear(); 7558bf80f4bSopenharmony_ci 7568bf80f4bSopenharmony_ci // Release resource data. 7578bf80f4bSopenharmony_ci gltfResourceData_ = {}; 7588bf80f4bSopenharmony_ci sceneEntity_ = {}; 7598bf80f4bSopenharmony_ci 7608bf80f4bSopenharmony_ci // Release default camera. 7618bf80f4bSopenharmony_ci defaultCameraEntity_ = {}; 7628bf80f4bSopenharmony_ci 7638bf80f4bSopenharmony_ci // Release scene 7648bf80f4bSopenharmony_ci scene_ = {}; 7658bf80f4bSopenharmony_ci assetManager_ = {}; 7668bf80f4bSopenharmony_ci 7678bf80f4bSopenharmony_ci // Release scene root. 7688bf80f4bSopenharmony_ci rootNode_ = {}; 7698bf80f4bSopenharmony_ci 7708bf80f4bSopenharmony_ci // fully recreate ECS if requested 7718bf80f4bSopenharmony_ci if (ecs_) { 7728bf80f4bSopenharmony_ci cameraComponentManager_ = {}; 7738bf80f4bSopenharmony_ci meshComponentManager_ = {}; 7748bf80f4bSopenharmony_ci nameComponentManager_ = {}; 7758bf80f4bSopenharmony_ci nodeComponentManager_ = {}; 7768bf80f4bSopenharmony_ci meshQuery_ = {}; 7778bf80f4bSopenharmony_ci materialQuery_ = {}; 7788bf80f4bSopenharmony_ci animationQuery_ = {}; 7798bf80f4bSopenharmony_ci ecsListener_->Reset(); 7808bf80f4bSopenharmony_ci ecs_->Uninitialize(); 7818bf80f4bSopenharmony_ci ecs_.reset(); 7828bf80f4bSopenharmony_ci } 7838bf80f4bSopenharmony_ci 7848bf80f4bSopenharmony_ci if (sceneUninitializedCallback_) { 7858bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 7868bf80f4bSopenharmony_ci [](auto callback) { 7878bf80f4bSopenharmony_ci callback->Invoke(); 7888bf80f4bSopenharmony_ci return false; 7898bf80f4bSopenharmony_ci }, 7908bf80f4bSopenharmony_ci sceneUninitializedCallback_), 7918bf80f4bSopenharmony_ci false); 7928bf80f4bSopenharmony_ci } 7938bf80f4bSopenharmony_ci 7948bf80f4bSopenharmony_ci if (initialize && CreateDefaultEcs()) { 7958bf80f4bSopenharmony_ci // Create new root node. 7968bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem& nodeSystem = *GetSystem<CORE3D_NS::INodeSystem>(*ecs_); 7978bf80f4bSopenharmony_ci rootNode_ = nodeSystem.CreateNode(); 7988bf80f4bSopenharmony_ci rootNode_->SetName(ROOTNODE_NAME); 7998bf80f4bSopenharmony_ci if (nodeComponentManager_) { 8008bf80f4bSopenharmony_ci nodeComponentManager_->Create(rootNode_->GetEntity()); 8018bf80f4bSopenharmony_ci } 8028bf80f4bSopenharmony_ci scene_ = SCENE_NS::IEntityCollection::Ptr { new SCENE_NS::EntityCollection(*ecs_, "scene", {}) }; 8038bf80f4bSopenharmony_ci 8048bf80f4bSopenharmony_ci // it seems that having our root entity as a part of loaded entify has no significant effect on 8058bf80f4bSopenharmony_ci // anything Presumably it is ok to keep it out of the serialization auto entityRef = 8068bf80f4bSopenharmony_ci 8078bf80f4bSopenharmony_ci rootNode_->SetEnabled(true); 8088bf80f4bSopenharmony_ci 8098bf80f4bSopenharmony_ci assetManager_ = 8108bf80f4bSopenharmony_ci SCENE_NS::IAssetManager::Ptr { new SCENE_NS::AssetManager(*renderContext_, *graphicsContext3D_) }; 8118bf80f4bSopenharmony_ci } 8128bf80f4bSopenharmony_ci} 8138bf80f4bSopenharmony_ci 8148bf80f4bSopenharmony_civoid SceneHolder::SetSceneSystemGraph(const BASE_NS::string& uri) 8158bf80f4bSopenharmony_ci{ 8168bf80f4bSopenharmony_ci if (uri != sceneSystemGraphUri_) { 8178bf80f4bSopenharmony_ci sceneSystemGraphUri_ = uri; 8188bf80f4bSopenharmony_ci scenePrepared_ = false; 8198bf80f4bSopenharmony_ci if (scene_) { 8208bf80f4bSopenharmony_ci // reload with new graph 8218bf80f4bSopenharmony_ci LoadScene(); 8228bf80f4bSopenharmony_ci 8238bf80f4bSopenharmony_ci } else if (sceneLoadedCallback_) { 8248bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 8258bf80f4bSopenharmony_ci [](auto sceneLoadedCallback) { 8268bf80f4bSopenharmony_ci if (sceneLoadedCallback) { 8278bf80f4bSopenharmony_ci sceneLoadedCallback->Invoke(SCENE_NS::IScene::SCENE_STATUS_UNINITIALIZED); 8288bf80f4bSopenharmony_ci } 8298bf80f4bSopenharmony_ci return false; 8308bf80f4bSopenharmony_ci }, 8318bf80f4bSopenharmony_ci sceneLoadedCallback_), 8328bf80f4bSopenharmony_ci false); 8338bf80f4bSopenharmony_ci } 8348bf80f4bSopenharmony_ci } 8358bf80f4bSopenharmony_ci} 8368bf80f4bSopenharmony_ci 8378bf80f4bSopenharmony_civoid SceneHolder::LoadScene(const BASE_NS::string& uri) 8388bf80f4bSopenharmony_ci{ 8398bf80f4bSopenharmony_ci // ToDo: LoadScene shoud deal with this, but currently triggers a problem when we swap between instances 8408bf80f4bSopenharmony_ci if (sceneUri_ == uri) { 8418bf80f4bSopenharmony_ci if (sceneLoadedCallback_) { 8428bf80f4bSopenharmony_ci bool haveEcs = (ecs_ == nullptr); 8438bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 8448bf80f4bSopenharmony_ci [haveEcs](auto sceneLoadedCallback) { 8458bf80f4bSopenharmony_ci if (sceneLoadedCallback) { 8468bf80f4bSopenharmony_ci sceneLoadedCallback->Invoke( 8478bf80f4bSopenharmony_ci haveEcs ? SCENE_NS::IScene::SCENE_STATUS_READY 8488bf80f4bSopenharmony_ci : SCENE_NS::IScene::SCENE_STATUS_LOADING_FAILED); 8498bf80f4bSopenharmony_ci } 8508bf80f4bSopenharmony_ci return false; 8518bf80f4bSopenharmony_ci }, 8528bf80f4bSopenharmony_ci sceneLoadedCallback_), 8538bf80f4bSopenharmony_ci false); 8548bf80f4bSopenharmony_ci } 8558bf80f4bSopenharmony_ci return; 8568bf80f4bSopenharmony_ci } 8578bf80f4bSopenharmony_ci sceneUri_ = uri; 8588bf80f4bSopenharmony_ci LoadScene(); 8598bf80f4bSopenharmony_ci} 8608bf80f4bSopenharmony_ci 8618bf80f4bSopenharmony_cistatic constexpr BASE_NS::string_view KDUMMY_STRING { "!#&/dummy" }; 8628bf80f4bSopenharmony_ci 8638bf80f4bSopenharmony_civoid SceneHolder::IntrospectNodeless() 8648bf80f4bSopenharmony_ci{ 8658bf80f4bSopenharmony_ci#ifndef NDEBUG 8668bf80f4bSopenharmony_ci Entity dummy {}; 8678bf80f4bSopenharmony_ci FindMesh(KDUMMY_STRING, KDUMMY_STRING, dummy); 8688bf80f4bSopenharmony_ci FindMaterial(KDUMMY_STRING, KDUMMY_STRING, dummy); 8698bf80f4bSopenharmony_ci#endif // !NDEBUG 8708bf80f4bSopenharmony_ci 8718bf80f4bSopenharmony_ci RemoveUriComponentsFromMeshes(); 8728bf80f4bSopenharmony_ci ResolveAnimations(); 8738bf80f4bSopenharmony_ci} 8748bf80f4bSopenharmony_ci 8758bf80f4bSopenharmony_cibool GetEntityId(const CORE_NS::Entity& entity, BASE_NS::string_view& entityName, 8768bf80f4bSopenharmony_ci SCENE_NS::IEntityCollection& collection, BASE_NS::string_view backupCollection, 8778bf80f4bSopenharmony_ci CORE3D_NS::INameComponentManager& nameComponentManager) 8788bf80f4bSopenharmony_ci{ 8798bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 8808bf80f4bSopenharmony_ci entityName = collection.GetUniqueIdentifierRecursive(entity); 8818bf80f4bSopenharmony_ci if (!entityName.empty() && entityName != "/") { 8828bf80f4bSopenharmony_ci return true; 8838bf80f4bSopenharmony_ci } else { 8848bf80f4bSopenharmony_ci if (auto readHandle = nameComponentManager.Read(entity)) { 8858bf80f4bSopenharmony_ci entityName = readHandle->name; 8868bf80f4bSopenharmony_ci collection.AddEntityToSubcollection(backupCollection, entityName, entity, true); 8878bf80f4bSopenharmony_ci auto gltfCollectionIx = collection.GetSubCollectionIndex(backupCollection); 8888bf80f4bSopenharmony_ci if (auto gltfCollection = collection.GetSubCollection(gltfCollectionIx)) { 8898bf80f4bSopenharmony_ci entityName = gltfCollection->GetUniqueIdentifier(entity); 8908bf80f4bSopenharmony_ci return true; 8918bf80f4bSopenharmony_ci } 8928bf80f4bSopenharmony_ci } else { 8938bf80f4bSopenharmony_ci // ToDo: we could store entity id even it did not have name component 8948bf80f4bSopenharmony_ci CORE_LOG_W("%s: entity missing from collections", __func__); 8958bf80f4bSopenharmony_ci } 8968bf80f4bSopenharmony_ci } 8978bf80f4bSopenharmony_ci } 8988bf80f4bSopenharmony_ci return false; 8998bf80f4bSopenharmony_ci} 9008bf80f4bSopenharmony_ci 9018bf80f4bSopenharmony_civoid ExtractQueryResults(CORE_NS::ComponentQuery& query, SCENE_NS::IEntityCollection& collection, 9028bf80f4bSopenharmony_ci BASE_NS::string_view backupCollection, BASE_NS::shared_ptr<BASE_NS::vector<BASE_NS::string_view>>& result, 9038bf80f4bSopenharmony_ci CORE3D_NS::INameComponentManager& nameComponentManager) 9048bf80f4bSopenharmony_ci{ 9058bf80f4bSopenharmony_ci query.Execute(); 9068bf80f4bSopenharmony_ci auto results = query.GetResults(); 9078bf80f4bSopenharmony_ci for (auto& row : results) { 9088bf80f4bSopenharmony_ci BASE_NS::string_view id; 9098bf80f4bSopenharmony_ci if (GetEntityId(row.entity, id, collection, backupCollection, nameComponentManager)) { 9108bf80f4bSopenharmony_ci result->push_back(id); 9118bf80f4bSopenharmony_ci } 9128bf80f4bSopenharmony_ci } 9138bf80f4bSopenharmony_ci} 9148bf80f4bSopenharmony_ci 9158bf80f4bSopenharmony_ciBASE_NS::shared_ptr<BASE_NS::vector<BASE_NS::string_view>> SceneHolder::ListMaterialNames() 9168bf80f4bSopenharmony_ci{ 9178bf80f4bSopenharmony_ci BASE_NS::shared_ptr<BASE_NS::vector<BASE_NS::string_view>> ret { new BASE_NS::vector<BASE_NS::string_view> }; 9188bf80f4bSopenharmony_ci if (materialQuery_ && scene_) { 9198bf80f4bSopenharmony_ci ExtractQueryResults(*materialQuery_, *scene_.get(), "GLTF_Materials", ret, *nameComponentManager_); 9208bf80f4bSopenharmony_ci } 9218bf80f4bSopenharmony_ci return ret; 9228bf80f4bSopenharmony_ci} 9238bf80f4bSopenharmony_ci 9248bf80f4bSopenharmony_ciBASE_NS::shared_ptr<BASE_NS::vector<BASE_NS::string_view>> SceneHolder::ListMeshNames() 9258bf80f4bSopenharmony_ci{ 9268bf80f4bSopenharmony_ci BASE_NS::shared_ptr<BASE_NS::vector<BASE_NS::string_view>> ret { new BASE_NS::vector<BASE_NS::string_view> }; 9278bf80f4bSopenharmony_ci if (meshQuery_ && scene_) { 9288bf80f4bSopenharmony_ci ExtractQueryResults(*meshQuery_, *scene_.get(), "GLTF_Meshes", ret, *nameComponentManager_); 9298bf80f4bSopenharmony_ci } 9308bf80f4bSopenharmony_ci return ret; 9318bf80f4bSopenharmony_ci} 9328bf80f4bSopenharmony_ci 9338bf80f4bSopenharmony_civoid SceneHolder::RemoveUriComponentsFromMeshes() 9348bf80f4bSopenharmony_ci{ 9358bf80f4bSopenharmony_ci meshQuery_->Execute(); 9368bf80f4bSopenharmony_ci auto meshes = meshQuery_->GetResults(); 9378bf80f4bSopenharmony_ci 9388bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("found %zu meshes", meshes.size()); 9398bf80f4bSopenharmony_ci 9408bf80f4bSopenharmony_ci // Remove uri component from meshes, since it causes issues with prefab loading. 9418bf80f4bSopenharmony_ci // The gltf importer shares the meshes between collections, if they have 9428bf80f4bSopenharmony_ci // similar uri. 9438bf80f4bSopenharmony_ci // However, this is not desired behavior, because scene-overridden property 9448bf80f4bSopenharmony_ci // values will propagate to future prefab instances (e.g. material). 9458bf80f4bSopenharmony_ci for (auto& mesh : meshes) { 9468bf80f4bSopenharmony_ci if (uriComponentManager_->HasComponent(mesh.entity)) { 9478bf80f4bSopenharmony_ci uriComponentManager_->Destroy(mesh.entity); 9488bf80f4bSopenharmony_ci } 9498bf80f4bSopenharmony_ci } 9508bf80f4bSopenharmony_ci} 9518bf80f4bSopenharmony_ci 9528bf80f4bSopenharmony_cibool SceneHolder::FindMesh(const BASE_NS::string_view name, const BASE_NS::string_view fullPath, Entity& entity) 9538bf80f4bSopenharmony_ci{ 9548bf80f4bSopenharmony_ci if (ecs_) { 9558bf80f4bSopenharmony_ci entity = scene_->GetEntityRecursive(fullPath); 9568bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(entity)) { 9578bf80f4bSopenharmony_ci return true; 9588bf80f4bSopenharmony_ci } 9598bf80f4bSopenharmony_ci 9608bf80f4bSopenharmony_ci meshQuery_->Execute(); 9618bf80f4bSopenharmony_ci auto meshes = meshQuery_->GetResults(); 9628bf80f4bSopenharmony_ci 9638bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("found %zu meshes", meshes.size()); 9648bf80f4bSopenharmony_ci 9658bf80f4bSopenharmony_ci#ifdef NDEBUG 9668bf80f4bSopenharmony_ci if (name == KDUMMY_STRING) { 9678bf80f4bSopenharmony_ci return false; 9688bf80f4bSopenharmony_ci } 9698bf80f4bSopenharmony_ci#endif 9708bf80f4bSopenharmony_ci 9718bf80f4bSopenharmony_ci for (auto&& mesh : meshes) { 9728bf80f4bSopenharmony_ci bool effectivelyEnabled = false; 9738bf80f4bSopenharmony_ci if (auto readHandle = nodeComponentManager_->Read(mesh.components[1])) { 9748bf80f4bSopenharmony_ci effectivelyEnabled = readHandle->effectivelyEnabled; 9758bf80f4bSopenharmony_ci } 9768bf80f4bSopenharmony_ci BASE_NS::string entityName; 9778bf80f4bSopenharmony_ci if (auto readHandle = nameComponentManager_->Read(mesh.components[2])) { 9788bf80f4bSopenharmony_ci entityName = readHandle->name; 9798bf80f4bSopenharmony_ci } 9808bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("name: %s enabled: %i", entityName.c_str(), effectivelyEnabled); 9818bf80f4bSopenharmony_ci if (name == entityName || fullPath == entityName) { 9828bf80f4bSopenharmony_ci entity = mesh.entity; 9838bf80f4bSopenharmony_ci return true; 9848bf80f4bSopenharmony_ci } 9858bf80f4bSopenharmony_ci } 9868bf80f4bSopenharmony_ci // Could not find the mesh with given the name, try if it has a node 9878bf80f4bSopenharmony_ci const auto& root = nodeSystem_->GetRootNode(); 9888bf80f4bSopenharmony_ci if (auto ecsNode = root.LookupNodeByPath(fullPath)) { 9898bf80f4bSopenharmony_ci entity = ecsNode->GetEntity(); 9908bf80f4bSopenharmony_ci return true; 9918bf80f4bSopenharmony_ci } 9928bf80f4bSopenharmony_ci } 9938bf80f4bSopenharmony_ci return false; 9948bf80f4bSopenharmony_ci} 9958bf80f4bSopenharmony_ci 9968bf80f4bSopenharmony_ciBASE_NS::string SceneHolder::GetResourceId(CORE_NS::Entity entity) 9978bf80f4bSopenharmony_ci{ 9988bf80f4bSopenharmony_ci BASE_NS::string result; 9998bf80f4bSopenharmony_ci 10008bf80f4bSopenharmony_ci if (scene_) { 10018bf80f4bSopenharmony_ci result = scene_->GetUniqueIdentifierRecursive(entity); 10028bf80f4bSopenharmony_ci } 10038bf80f4bSopenharmony_ci return result; 10048bf80f4bSopenharmony_ci} 10058bf80f4bSopenharmony_ci 10068bf80f4bSopenharmony_cibool SceneHolder::FindMaterial(const BASE_NS::string_view name, const BASE_NS::string_view fullPath, Entity& entity) 10078bf80f4bSopenharmony_ci{ 10088bf80f4bSopenharmony_ci if (ecs_) { 10098bf80f4bSopenharmony_ci entity = scene_->GetEntityRecursive(fullPath); 10108bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(entity)) { 10118bf80f4bSopenharmony_ci return true; 10128bf80f4bSopenharmony_ci } 10138bf80f4bSopenharmony_ci 10148bf80f4bSopenharmony_ci materialQuery_->Execute(); 10158bf80f4bSopenharmony_ci auto materials = materialQuery_->GetResults(); 10168bf80f4bSopenharmony_ci 10178bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("found %zu materials", materials.size()); 10188bf80f4bSopenharmony_ci 10198bf80f4bSopenharmony_ci#ifdef NDEBUG 10208bf80f4bSopenharmony_ci if (name == KDUMMY_STRING) { 10218bf80f4bSopenharmony_ci return false; 10228bf80f4bSopenharmony_ci } 10238bf80f4bSopenharmony_ci#endif 10248bf80f4bSopenharmony_ci 10258bf80f4bSopenharmony_ci for (auto&& material : materials) { 10268bf80f4bSopenharmony_ci bool effectivelyEnabled = false; 10278bf80f4bSopenharmony_ci if (auto readHandle = nodeComponentManager_->Read(material.components[1])) { 10288bf80f4bSopenharmony_ci effectivelyEnabled = readHandle->effectivelyEnabled; 10298bf80f4bSopenharmony_ci } 10308bf80f4bSopenharmony_ci BASE_NS::string entityName; 10318bf80f4bSopenharmony_ci if (auto readHandle = nameComponentManager_->Read(material.components[2])) { 10328bf80f4bSopenharmony_ci entityName = readHandle->name; 10338bf80f4bSopenharmony_ci } 10348bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("name: %s enabled: %i", entityName.c_str(), effectivelyEnabled); 10358bf80f4bSopenharmony_ci if (name == entityName) { 10368bf80f4bSopenharmony_ci entity = material.entity; 10378bf80f4bSopenharmony_ci return true; 10388bf80f4bSopenharmony_ci } 10398bf80f4bSopenharmony_ci if (auto readHandle = uriComponentManager_->Read(material.components[3])) { 10408bf80f4bSopenharmony_ci entityName = readHandle->uri; 10418bf80f4bSopenharmony_ci } 10428bf80f4bSopenharmony_ci 10438bf80f4bSopenharmony_ci if (!entityName.empty()) { 10448bf80f4bSopenharmony_ci if (name == entityName || fullPath == entityName) { 10458bf80f4bSopenharmony_ci entity = material.entity; 10468bf80f4bSopenharmony_ci return true; 10478bf80f4bSopenharmony_ci } 10488bf80f4bSopenharmony_ci } 10498bf80f4bSopenharmony_ci } 10508bf80f4bSopenharmony_ci // Could not find the material with the given name, try if it has a node 10518bf80f4bSopenharmony_ci const auto& root = nodeSystem_->GetRootNode(); 10528bf80f4bSopenharmony_ci if (auto ecsNode = root.LookupNodeByPath(fullPath)) { 10538bf80f4bSopenharmony_ci entity = ecsNode->GetEntity(); 10548bf80f4bSopenharmony_ci return true; 10558bf80f4bSopenharmony_ci } 10568bf80f4bSopenharmony_ci // Desperate measures, to be rectified 10578bf80f4bSopenharmony_ci if (auto created = rootNode_->LookupNodeByPath(fullPath)) { 10588bf80f4bSopenharmony_ci entity = created->GetEntity(); 10598bf80f4bSopenharmony_ci return true; 10608bf80f4bSopenharmony_ci } 10618bf80f4bSopenharmony_ci } 10628bf80f4bSopenharmony_ci return false; 10638bf80f4bSopenharmony_ci} 10648bf80f4bSopenharmony_ci 10658bf80f4bSopenharmony_cibool SceneHolder::FindAnimation(const BASE_NS::string_view name, const BASE_NS::string_view fullPath, Entity& entity) 10668bf80f4bSopenharmony_ci{ 10678bf80f4bSopenharmony_ci if (ecs_) { 10688bf80f4bSopenharmony_ci if (!animations_.empty()) { 10698bf80f4bSopenharmony_ci size_t ix = name.rfind(":"); 10708bf80f4bSopenharmony_ci if (ix != BASE_NS::string_view::npos && ix != name.size() - 1) { 10718bf80f4bSopenharmony_ci char* dummy = nullptr; 10728bf80f4bSopenharmony_ci auto entityId = strtoll(name.substr(ix + 1).data(), &dummy, 16); 10738bf80f4bSopenharmony_ci if (animations_.find(entityId) != animations_.cend()) { 10748bf80f4bSopenharmony_ci entity.id = entityId; 10758bf80f4bSopenharmony_ci return true; 10768bf80f4bSopenharmony_ci } 10778bf80f4bSopenharmony_ci } 10788bf80f4bSopenharmony_ci 10798bf80f4bSopenharmony_ci for (auto&& animation : animations_) { 10808bf80f4bSopenharmony_ci if (META_NS::GetValue(interface_pointer_cast<META_NS::INamed>(animation.second)->Name()) == name) { 10818bf80f4bSopenharmony_ci entity.id = animation.first; 10828bf80f4bSopenharmony_ci return true; 10838bf80f4bSopenharmony_ci } 10848bf80f4bSopenharmony_ci } 10858bf80f4bSopenharmony_ci } else { 10868bf80f4bSopenharmony_ci animationQuery_->Execute(); 10878bf80f4bSopenharmony_ci auto animations = animationQuery_->GetResults(); 10888bf80f4bSopenharmony_ci 10898bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("found %zu animations", animations.size()); 10908bf80f4bSopenharmony_ci 10918bf80f4bSopenharmony_ci#ifdef NDEBUG 10928bf80f4bSopenharmony_ci if (name == KDUMMY_STRING) { 10938bf80f4bSopenharmony_ci return false; 10948bf80f4bSopenharmony_ci } 10958bf80f4bSopenharmony_ci#endif 10968bf80f4bSopenharmony_ci 10978bf80f4bSopenharmony_ci for (auto&& animation : animations) { 10988bf80f4bSopenharmony_ci bool effectivelyEnabled = false; 10998bf80f4bSopenharmony_ci if (auto readHandle = nodeComponentManager_->Read(animation.components[1])) { 11008bf80f4bSopenharmony_ci effectivelyEnabled = readHandle->effectivelyEnabled; 11018bf80f4bSopenharmony_ci } 11028bf80f4bSopenharmony_ci BASE_NS::string entityName; 11038bf80f4bSopenharmony_ci if (auto readHandle = nameComponentManager_->Read(animation.components[2])) { 11048bf80f4bSopenharmony_ci entityName = readHandle->name; 11058bf80f4bSopenharmony_ci } 11068bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("name: %s enabled: %i", entityName.c_str(), effectivelyEnabled); 11078bf80f4bSopenharmony_ci if (name == entityName || fullPath == entityName) { 11088bf80f4bSopenharmony_ci entity = animation.entity; 11098bf80f4bSopenharmony_ci return true; 11108bf80f4bSopenharmony_ci } 11118bf80f4bSopenharmony_ci } 11128bf80f4bSopenharmony_ci // Could not find the animation with given the name, try if it has a node 11138bf80f4bSopenharmony_ci const auto& root = nodeSystem_->GetRootNode(); 11148bf80f4bSopenharmony_ci if (auto ecsNode = root.LookupNodeByPath(fullPath)) { 11158bf80f4bSopenharmony_ci entity = ecsNode->GetEntity(); 11168bf80f4bSopenharmony_ci return true; 11178bf80f4bSopenharmony_ci } 11188bf80f4bSopenharmony_ci } 11198bf80f4bSopenharmony_ci } 11208bf80f4bSopenharmony_ci return false; 11218bf80f4bSopenharmony_ci} 11228bf80f4bSopenharmony_ci 11238bf80f4bSopenharmony_civoid SceneHolder::ResolveAnimations() 11248bf80f4bSopenharmony_ci{ 11258bf80f4bSopenharmony_ci if (ecs_) { 11268bf80f4bSopenharmony_ci animationQuery_->Execute(); 11278bf80f4bSopenharmony_ci auto animations = animationQuery_->GetResults(); 11288bf80f4bSopenharmony_ci 11298bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("%s, found %zu animations", __func__, animations.size()); 11308bf80f4bSopenharmony_ci 11318bf80f4bSopenharmony_ci for (auto&& animation : animations) { 11328bf80f4bSopenharmony_ci if (animations_.find(animation.entity.id) == animations_.cend()) { 11338bf80f4bSopenharmony_ci animations_[animation.entity.id] = 11348bf80f4bSopenharmony_ci GetObjectRegistry().Create<SCENE_NS::IEcsAnimation>(SCENE_NS::ClassId::EcsAnimation); 11358bf80f4bSopenharmony_ci if (auto ecsProxyIf = 11368bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::IEcsProxyObject>(animations_[animation.entity.id])) { 11378bf80f4bSopenharmony_ci ecsProxyIf->SetCommonListener(GetCommonEcsListener()); 11388bf80f4bSopenharmony_ci } 11398bf80f4bSopenharmony_ci animations_[animation.entity.id]->SetEntity(*ecs_, animation.entity); 11408bf80f4bSopenharmony_ci } 11418bf80f4bSopenharmony_ci } 11428bf80f4bSopenharmony_ci } 11438bf80f4bSopenharmony_ci} 11448bf80f4bSopenharmony_ci 11458bf80f4bSopenharmony_civoid SceneHolder::UpdateAttachments(SCENE_NS::IEcsObject::Ptr& ecsObject) 11468bf80f4bSopenharmony_ci{ 11478bf80f4bSopenharmony_ci if (ecs_) { 11488bf80f4bSopenharmony_ci auto entity = ecsObject->GetEntity(); 11498bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 11508bf80f4bSopenharmony_ci for (auto&& animation : animations_) { 11518bf80f4bSopenharmony_ci if (animation.second->GetRootEntity() == entity) { 11528bf80f4bSopenharmony_ci ecsObject->AddAttachment(animation.second->GetEntity()); 11538bf80f4bSopenharmony_ci } 11548bf80f4bSopenharmony_ci } 11558bf80f4bSopenharmony_ci } 11568bf80f4bSopenharmony_ci } 11578bf80f4bSopenharmony_ci} 11588bf80f4bSopenharmony_ci 11598bf80f4bSopenharmony_ci// This could be highly inefficient, in most cases we should have a clue of resource type 11608bf80f4bSopenharmony_cibool SceneHolder::FindResource(const BASE_NS::string_view name, const BASE_NS::string_view fullPath, Entity& entity) 11618bf80f4bSopenharmony_ci{ 11628bf80f4bSopenharmony_ci if (ecs_ && scene_) { 11638bf80f4bSopenharmony_ci if (FindAnimation(name, fullPath, entity) || FindMaterial(name, fullPath, entity) || 11648bf80f4bSopenharmony_ci FindMesh(name, fullPath, entity)) { 11658bf80f4bSopenharmony_ci return true; 11668bf80f4bSopenharmony_ci } 11678bf80f4bSopenharmony_ci 11688bf80f4bSopenharmony_ci // traverse through scene collection 11698bf80f4bSopenharmony_ci for (size_t ix = 0; ix < scene_->GetSubCollectionCount(); ix++) { 11708bf80f4bSopenharmony_ci if (const auto& subcollection = scene_->GetSubCollection(ix); subcollection->GetUri() == fullPath) { 11718bf80f4bSopenharmony_ci // the assumption is that we do not have to dig deeper 11728bf80f4bSopenharmony_ci if (subcollection->GetEntityCount() > 0) { 11738bf80f4bSopenharmony_ci entity = subcollection->GetEntity(0); 11748bf80f4bSopenharmony_ci return true; 11758bf80f4bSopenharmony_ci } 11768bf80f4bSopenharmony_ci } 11778bf80f4bSopenharmony_ci } 11788bf80f4bSopenharmony_ci 11798bf80f4bSopenharmony_ci // Try finding an existing resource with an uri. This is needed e.g. for the images loaded from an glTF 11808bf80f4bSopenharmony_ci // file where the uri does not point to an actual image file but the resource is just a entity with uri in 11818bf80f4bSopenharmony_ci // ECS. 11828bf80f4bSopenharmony_ci if (renderMeshComponentManager_ && uriComponentManager_) { 11838bf80f4bSopenharmony_ci for (size_t i = 0; i < uriComponentManager_->GetComponentCount(); ++i) { 11848bf80f4bSopenharmony_ci const Entity currentEntity = 11858bf80f4bSopenharmony_ci uriComponentManager_->GetEntity(static_cast<IComponentManager::ComponentId>(i)); 11868bf80f4bSopenharmony_ci if (ecs_->GetEntityManager().IsAlive(currentEntity)) { 11878bf80f4bSopenharmony_ci if (auto uriComponent = uriComponentManager_->Read(currentEntity); 11888bf80f4bSopenharmony_ci uriComponent && uriComponent->uri == fullPath) { 11898bf80f4bSopenharmony_ci if (renderMeshComponentManager_->HasComponent(currentEntity)) { 11908bf80f4bSopenharmony_ci entity = currentEntity; 11918bf80f4bSopenharmony_ci return true; 11928bf80f4bSopenharmony_ci } 11938bf80f4bSopenharmony_ci } 11948bf80f4bSopenharmony_ci } 11958bf80f4bSopenharmony_ci } 11968bf80f4bSopenharmony_ci } 11978bf80f4bSopenharmony_ci } 11988bf80f4bSopenharmony_ci 11998bf80f4bSopenharmony_ci return false; 12008bf80f4bSopenharmony_ci} 12018bf80f4bSopenharmony_ci 12028bf80f4bSopenharmony_cibool SceneHolder::GetImageEntity(CORE_NS::Entity material, size_t index, CORE_NS::Entity& entity) 12038bf80f4bSopenharmony_ci{ 12048bf80f4bSopenharmony_ci bool ret { false }; 12058bf80f4bSopenharmony_ci if (ecs_ && scene_ && CORE_NS::EntityUtil::IsValid(material)) { 12068bf80f4bSopenharmony_ci if (auto handle = materialComponentManager_->Read(material)) { 12078bf80f4bSopenharmony_ci entity = handle->textures[index].image; 12088bf80f4bSopenharmony_ci ret = true; 12098bf80f4bSopenharmony_ci } 12108bf80f4bSopenharmony_ci } 12118bf80f4bSopenharmony_ci 12128bf80f4bSopenharmony_ci return ret; 12138bf80f4bSopenharmony_ci} 12148bf80f4bSopenharmony_ci 12158bf80f4bSopenharmony_cibool SceneHolder::GetRenderHandleUri(const RENDER_NS::RenderHandle& handle, BASE_NS::string& uriString) 12168bf80f4bSopenharmony_ci{ 12178bf80f4bSopenharmony_ci if (ecs_) { 12188bf80f4bSopenharmony_ci auto& renderUtil = graphicsContext3D_->GetRenderContext().GetRenderUtil(); 12198bf80f4bSopenharmony_ci 12208bf80f4bSopenharmony_ci size_t index { 0 }; 12218bf80f4bSopenharmony_ci while (auto handleReference = rhComponentManager_->GetRenderHandleReference(index)) { 12228bf80f4bSopenharmony_ci if (handleReference.GetHandle() == handle) { 12238bf80f4bSopenharmony_ci auto& renderUtil = graphicsContext3D_->GetRenderContext().GetRenderUtil(); 12248bf80f4bSopenharmony_ci const auto desc = renderUtil.GetRenderHandleDesc(handleReference); 12258bf80f4bSopenharmony_ci if (desc.type == RenderHandleType::GPU_IMAGE && !desc.name.empty()) { 12268bf80f4bSopenharmony_ci // Note: assuming that the name is the image uri. Ignore the name if not in uri format. 12278bf80f4bSopenharmony_ci if (desc.name.find(":/") != BASE_NS::string::npos) { 12288bf80f4bSopenharmony_ci uriString = desc.name; 12298bf80f4bSopenharmony_ci return true; 12308bf80f4bSopenharmony_ci } 12318bf80f4bSopenharmony_ci } 12328bf80f4bSopenharmony_ci } 12338bf80f4bSopenharmony_ci index++; 12348bf80f4bSopenharmony_ci } 12358bf80f4bSopenharmony_ci } 12368bf80f4bSopenharmony_ci return false; 12378bf80f4bSopenharmony_ci} 12388bf80f4bSopenharmony_ci 12398bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreatePostProcess() 12408bf80f4bSopenharmony_ci{ 12418bf80f4bSopenharmony_ci CORE_NS::Entity entity; 12428bf80f4bSopenharmony_ci if (ecs_) { 12438bf80f4bSopenharmony_ci auto pm = CORE_NS::GetManager<CORE3D_NS::IPostProcessComponentManager>(*ecs_); 12448bf80f4bSopenharmony_ci entity = ecs_->GetEntityManager().Create(); 12458bf80f4bSopenharmony_ci // createComponent 12468bf80f4bSopenharmony_ci pm->Create(entity); 12478bf80f4bSopenharmony_ci } 12488bf80f4bSopenharmony_ci return entity; 12498bf80f4bSopenharmony_ci} 12508bf80f4bSopenharmony_ci 12518bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateRenderConfiguration() 12528bf80f4bSopenharmony_ci{ 12538bf80f4bSopenharmony_ci CORE_NS::Entity entity; 12548bf80f4bSopenharmony_ci if (ecs_) { 12558bf80f4bSopenharmony_ci entity = ecs_->GetEntityManager().Create(); 12568bf80f4bSopenharmony_ci 12578bf80f4bSopenharmony_ci auto rcm = CORE_NS::GetManager<CORE3D_NS::IRenderConfigurationComponentManager>(*ecs_); 12588bf80f4bSopenharmony_ci rcm->Create(entity); 12598bf80f4bSopenharmony_ci } 12608bf80f4bSopenharmony_ci return entity; 12618bf80f4bSopenharmony_ci} 12628bf80f4bSopenharmony_ci 12638bf80f4bSopenharmony_civoid SceneHolder::SetRenderHandle(const CORE_NS::Entity& target, const CORE_NS::Entity& source) 12648bf80f4bSopenharmony_ci{ 12658bf80f4bSopenharmony_ci if (ecs_) { 12668bf80f4bSopenharmony_ci if (auto sourceHandle = rhComponentManager_->GetRenderHandleReference(source)) { 12678bf80f4bSopenharmony_ci if (!rhComponentManager_->HasComponent(target)) { 12688bf80f4bSopenharmony_ci rhComponentManager_->Create(target); 12698bf80f4bSopenharmony_ci } 12708bf80f4bSopenharmony_ci if (auto handle = rhComponentManager_->Write(target)) { 12718bf80f4bSopenharmony_ci handle->reference = sourceHandle; 12728bf80f4bSopenharmony_ci } 12738bf80f4bSopenharmony_ci } 12748bf80f4bSopenharmony_ci } 12758bf80f4bSopenharmony_ci} 12768bf80f4bSopenharmony_ci 12778bf80f4bSopenharmony_cibool SceneHolder::GetEntityUri(const CORE_NS::Entity& entity, BASE_NS::string& uriString) 12788bf80f4bSopenharmony_ci{ 12798bf80f4bSopenharmony_ci bool ret { false }; 12808bf80f4bSopenharmony_ci if (ecs_ && scene_ && CORE_NS::EntityUtil::IsValid(entity)) { 12818bf80f4bSopenharmony_ci if (auto handle = uriComponentManager_->Read(entity)) { 12828bf80f4bSopenharmony_ci uriString = BASE_NS::string(handle->uri.data(), handle->uri.size()); 12838bf80f4bSopenharmony_ci ret = true; 12848bf80f4bSopenharmony_ci } 12858bf80f4bSopenharmony_ci } 12868bf80f4bSopenharmony_ci 12878bf80f4bSopenharmony_ci if (!ret) { 12888bf80f4bSopenharmony_ci // Special handling for render handles (automatically loaded images in the ecs are now just render handles 12898bf80f4bSopenharmony_ci // with a name containing the uri). 12908bf80f4bSopenharmony_ci auto handle = rhComponentManager_->GetRenderHandleReference(entity); 12918bf80f4bSopenharmony_ci if (handle) { 12928bf80f4bSopenharmony_ci auto& renderUtil = renderContext_->GetRenderUtil(); 12938bf80f4bSopenharmony_ci const auto desc = renderUtil.GetRenderHandleDesc(handle); 12948bf80f4bSopenharmony_ci if (desc.type == RenderHandleType::GPU_IMAGE && !desc.name.empty()) { 12958bf80f4bSopenharmony_ci // Note: assuming that the name is the image uri. Ignore the name if not in uri format. 12968bf80f4bSopenharmony_ci if (desc.name.find(":/") != BASE_NS::string::npos) { 12978bf80f4bSopenharmony_ci uriString = desc.name; 12988bf80f4bSopenharmony_ci ret = true; 12998bf80f4bSopenharmony_ci } 13008bf80f4bSopenharmony_ci } 13018bf80f4bSopenharmony_ci } 13028bf80f4bSopenharmony_ci } 13038bf80f4bSopenharmony_ci 13048bf80f4bSopenharmony_ci return ret; 13058bf80f4bSopenharmony_ci} 13068bf80f4bSopenharmony_cibool SceneHolder::GetImageHandle( 13078bf80f4bSopenharmony_ci const CORE_NS::Entity& entity, RENDER_NS::RenderHandleReference& handle, RENDER_NS::GpuImageDesc& desc) 13088bf80f4bSopenharmony_ci{ 13098bf80f4bSopenharmony_ci if (rhComponentManager_->HasComponent(entity)) { 13108bf80f4bSopenharmony_ci handle = rhComponentManager_->GetRenderHandleReference(entity); 13118bf80f4bSopenharmony_ci desc = renderContext_->GetDevice().GetGpuResourceManager().GetImageDescriptor(handle); 13128bf80f4bSopenharmony_ci return true; 13138bf80f4bSopenharmony_ci } 13148bf80f4bSopenharmony_ci return false; 13158bf80f4bSopenharmony_ci} 13168bf80f4bSopenharmony_ci 13178bf80f4bSopenharmony_cibool SceneHolder::SetEntityUri(const CORE_NS::Entity& entity, const BASE_NS::string& uriString) 13188bf80f4bSopenharmony_ci{ 13198bf80f4bSopenharmony_ci bool ret { false }; 13208bf80f4bSopenharmony_ci if (ecs_ && scene_ && CORE_NS::EntityUtil::IsValid(entity)) { 13218bf80f4bSopenharmony_ci if (!uriComponentManager_->HasComponent(entity)) { 13228bf80f4bSopenharmony_ci uriComponentManager_->Create(entity); 13238bf80f4bSopenharmony_ci } 13248bf80f4bSopenharmony_ci 13258bf80f4bSopenharmony_ci if (auto handle = uriComponentManager_->Write(entity)) { 13268bf80f4bSopenharmony_ci handle->uri = uriString; 13278bf80f4bSopenharmony_ci ret = true; 13288bf80f4bSopenharmony_ci } 13298bf80f4bSopenharmony_ci } 13308bf80f4bSopenharmony_ci 13318bf80f4bSopenharmony_ci return ret; 13328bf80f4bSopenharmony_ci} 13338bf80f4bSopenharmony_ci 13348bf80f4bSopenharmony_cibool SceneHolder::GetEntityName(const CORE_NS::Entity& entity, BASE_NS::string& nameString) 13358bf80f4bSopenharmony_ci{ 13368bf80f4bSopenharmony_ci bool ret { false }; 13378bf80f4bSopenharmony_ci if (ecs_ && scene_ && CORE_NS::EntityUtil::IsValid(entity)) { 13388bf80f4bSopenharmony_ci if (auto handle = nameComponentManager_->Read(entity)) { 13398bf80f4bSopenharmony_ci nameString = BASE_NS::string(handle->name.data(), handle->name.size()); 13408bf80f4bSopenharmony_ci ret = true; 13418bf80f4bSopenharmony_ci } 13428bf80f4bSopenharmony_ci } 13438bf80f4bSopenharmony_ci 13448bf80f4bSopenharmony_ci return ret; 13458bf80f4bSopenharmony_ci} 13468bf80f4bSopenharmony_ci 13478bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::GetEntityByUri(BASE_NS::string_view uriString) 13488bf80f4bSopenharmony_ci{ 13498bf80f4bSopenharmony_ci for (size_t i = 0; i < uriComponentManager_->GetComponentCount(); ++i) { 13508bf80f4bSopenharmony_ci const Entity entity = uriComponentManager_->GetEntity(static_cast<IComponentManager::ComponentId>(i)); 13518bf80f4bSopenharmony_ci if (ecs_->GetEntityManager().IsAlive(entity)) { 13528bf80f4bSopenharmony_ci if (auto uriComponent = uriComponentManager_->Read(entity); 13538bf80f4bSopenharmony_ci uriComponent && uriComponent->uri == uriString) { 13548bf80f4bSopenharmony_ci return entity; 13558bf80f4bSopenharmony_ci } 13568bf80f4bSopenharmony_ci } 13578bf80f4bSopenharmony_ci } 13588bf80f4bSopenharmony_ci 13598bf80f4bSopenharmony_ci return {}; 13608bf80f4bSopenharmony_ci} 13618bf80f4bSopenharmony_ci 13628bf80f4bSopenharmony_cibool ResolveNodeFullPath(CORE3D_NS::ISceneNode* node, BASE_NS::string& path) 13638bf80f4bSopenharmony_ci{ 13648bf80f4bSopenharmony_ci if (node) { 13658bf80f4bSopenharmony_ci path = node->GetName(); 13668bf80f4bSopenharmony_ci while ((node = node->GetParent())) { 13678bf80f4bSopenharmony_ci path.insert(0, "/"); 13688bf80f4bSopenharmony_ci auto name = node->GetName(); 13698bf80f4bSopenharmony_ci path.insert(0, name.data(), name.size()); 13708bf80f4bSopenharmony_ci } 13718bf80f4bSopenharmony_ci } 13728bf80f4bSopenharmony_ci return (!path.empty()); 13738bf80f4bSopenharmony_ci} 13748bf80f4bSopenharmony_ci 13758bf80f4bSopenharmony_ciBASE_NS::string ResolveNodeFullPath(CORE_NS::IEcs& ecs, const CORE_NS::Entity& entity) 13768bf80f4bSopenharmony_ci{ 13778bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem& nodeSystem = *CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(ecs); 13788bf80f4bSopenharmony_ci BASE_NS::string ret; 13798bf80f4bSopenharmony_ci ResolveNodeFullPath(nodeSystem.GetNode(entity), ret); 13808bf80f4bSopenharmony_ci return ret; 13818bf80f4bSopenharmony_ci} 13828bf80f4bSopenharmony_ci 13838bf80f4bSopenharmony_civoid SceneHolder::LoadScene() 13848bf80f4bSopenharmony_ci{ 13858bf80f4bSopenharmony_ci // Reset scene to default. 13868bf80f4bSopenharmony_ci CORE_LOG_I("Loading scene: '%s'", sceneUri_.c_str()); 13878bf80f4bSopenharmony_ci uint32_t loadingStatus = SCENE_NS::IScene::SCENE_STATUS_LOADING_FAILED; 13888bf80f4bSopenharmony_ci bool replacedRoot { false }; 13898bf80f4bSopenharmony_ci 13908bf80f4bSopenharmony_ci while (true) { 13918bf80f4bSopenharmony_ci if (sceneUri_.empty()) { 13928bf80f4bSopenharmony_ci ResetScene(); 13938bf80f4bSopenharmony_ci loadingStatus = SCENE_NS::IScene::SCENE_STATUS_UNINITIALIZED; 13948bf80f4bSopenharmony_ci break; 13958bf80f4bSopenharmony_ci } 13968bf80f4bSopenharmony_ci 13978bf80f4bSopenharmony_ci auto params = SCENE_NS::PathUtil::GetUriParameters(sceneUri_); 13988bf80f4bSopenharmony_ci auto ite = params.find("target"); 13998bf80f4bSopenharmony_ci if (!scene_ || ite == params.end() || ite->second.empty()) { 14008bf80f4bSopenharmony_ci ResetScene(true); 14018bf80f4bSopenharmony_ci replacedRoot = true; 14028bf80f4bSopenharmony_ci } else { 14038bf80f4bSopenharmony_ci CORE_LOG_I("Load into scene: %s", ite->second.c_str()); 14048bf80f4bSopenharmony_ci } 14058bf80f4bSopenharmony_ci 14068bf80f4bSopenharmony_ci // If ecs initializing failed, report it back and return 14078bf80f4bSopenharmony_ci if (!ecs_) { 14088bf80f4bSopenharmony_ci break; 14098bf80f4bSopenharmony_ci } 14108bf80f4bSopenharmony_ci 14118bf80f4bSopenharmony_ci if (assetManager_) { 14128bf80f4bSopenharmony_ci if ((sceneUri_ != "scene://empty") && !assetManager_->LoadAsset(*scene_, sceneUri_, "project://")) { 14138bf80f4bSopenharmony_ci CORE_LOG_E("Loading scene %s failed", sceneUri_.c_str()); 14148bf80f4bSopenharmony_ci ResetScene(); 14158bf80f4bSopenharmony_ci break; 14168bf80f4bSopenharmony_ci } else { // ToDo: This is currently done also when a node is added to container, so no need to do it 14178bf80f4bSopenharmony_ci // here 14188bf80f4bSopenharmony_ci // Rearrange scene to have a concrete common root node, this will be more important for prefabs 14198bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem& nodeSystem = *CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*ecs_); 14208bf80f4bSopenharmony_ci auto& root = nodeSystem.GetRootNode(); 14218bf80f4bSopenharmony_ci 14228bf80f4bSopenharmony_ci // ToDo: should this fetch the named root node instead 14238bf80f4bSopenharmony_ci auto ourRoot = root.GetChildren().at(0); 14248bf80f4bSopenharmony_ci ourRoot->SetEnabled(true); 14258bf80f4bSopenharmony_ci 14268bf80f4bSopenharmony_ci auto ite = root.GetChildren().begin() + 1; 14278bf80f4bSopenharmony_ci while (ite != root.GetChildren().end()) { 14288bf80f4bSopenharmony_ci (*ite)->SetParent(*ourRoot); 14298bf80f4bSopenharmony_ci ite = root.GetChildren().begin() + 1; 14308bf80f4bSopenharmony_ci } 14318bf80f4bSopenharmony_ci } 14328bf80f4bSopenharmony_ci 14338bf80f4bSopenharmony_ci // Loading might have cached some assets (in case there are multiple 14348bf80f4bSopenharmony_ci // instances). Scene widget will not need them after loading so clear the 14358bf80f4bSopenharmony_ci // cache. 14368bf80f4bSopenharmony_ci if (replacedRoot) { 14378bf80f4bSopenharmony_ci assetManager_->ClearCache(); 14388bf80f4bSopenharmony_ci } 14398bf80f4bSopenharmony_ci } 14408bf80f4bSopenharmony_ci if (sceneUri_ != "scene://empty") { 14418bf80f4bSopenharmony_ci // Set default camera. 14428bf80f4bSopenharmony_ci SetDefaultCamera(); 14438bf80f4bSopenharmony_ci } 14448bf80f4bSopenharmony_ci // ask synchronous update 14458bf80f4bSopenharmony_ci RenderCameras(); 14468bf80f4bSopenharmony_ci loadingStatus = SCENE_NS::IScene::SCENE_STATUS_READY; 14478bf80f4bSopenharmony_ci break; 14488bf80f4bSopenharmony_ci } 14498bf80f4bSopenharmony_ci 14508bf80f4bSopenharmony_ci // If ecs initialization fails, all we can do is to retry loading later 14518bf80f4bSopenharmony_ci if (!ecs_) { 14528bf80f4bSopenharmony_ci loadSceneFailed_ = true; 14538bf80f4bSopenharmony_ci 14548bf80f4bSopenharmony_ci if (sceneLoadedCallback_) { 14558bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 14568bf80f4bSopenharmony_ci [](auto sceneLoadedCallback, auto loadingStatus) { 14578bf80f4bSopenharmony_ci if (sceneLoadedCallback) 14588bf80f4bSopenharmony_ci sceneLoadedCallback->Invoke(loadingStatus); 14598bf80f4bSopenharmony_ci return false; 14608bf80f4bSopenharmony_ci }, 14618bf80f4bSopenharmony_ci sceneLoadedCallback_, loadingStatus), 14628bf80f4bSopenharmony_ci false); 14638bf80f4bSopenharmony_ci } 14648bf80f4bSopenharmony_ci return; 14658bf80f4bSopenharmony_ci } 14668bf80f4bSopenharmony_ci 14678bf80f4bSopenharmony_ci // make sure that components get updated 14688bf80f4bSopenharmony_ci ProcessEvents(); 14698bf80f4bSopenharmony_ci 14708bf80f4bSopenharmony_ci IntrospectNodeless(); 14718bf80f4bSopenharmony_ci // Call back the app thread, notify that the graphics and ecs are ready. This 14728bf80f4bSopenharmony_ci // is not quite true, though 14738bf80f4bSopenharmony_ci if (ecs_ && replacedRoot && sceneInitializedCallback_) { 14748bf80f4bSopenharmony_ci BASE_NS::string id { rootNode_->GetName() }; 14758bf80f4bSopenharmony_ci BASE_NS::string cameraId = ResolveNodeFullPath(*ecs_, defaultCameraEntity_); 14768bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 14778bf80f4bSopenharmony_ci [](auto sceneInitializedCallback, auto id, auto cameraId) { 14788bf80f4bSopenharmony_ci if (sceneInitializedCallback) { 14798bf80f4bSopenharmony_ci sceneInitializedCallback->Invoke(id, cameraId); 14808bf80f4bSopenharmony_ci } 14818bf80f4bSopenharmony_ci return false; 14828bf80f4bSopenharmony_ci }, 14838bf80f4bSopenharmony_ci sceneInitializedCallback_, id, cameraId), 14848bf80f4bSopenharmony_ci false); 14858bf80f4bSopenharmony_ci } else if (sceneLoadedCallback_) { // Call back the app thread, notify that new scene is loaded 14868bf80f4bSopenharmony_ci QueueApplicationTask(MakeTask( 14878bf80f4bSopenharmony_ci [](auto sceneLoadedCallback, auto loadingStatus) { 14888bf80f4bSopenharmony_ci if (sceneLoadedCallback) { 14898bf80f4bSopenharmony_ci sceneLoadedCallback->Invoke(loadingStatus); 14908bf80f4bSopenharmony_ci } 14918bf80f4bSopenharmony_ci return false; 14928bf80f4bSopenharmony_ci }, 14938bf80f4bSopenharmony_ci sceneLoadedCallback_, loadingStatus), 14948bf80f4bSopenharmony_ci false); 14958bf80f4bSopenharmony_ci } 14968bf80f4bSopenharmony_ci} 14978bf80f4bSopenharmony_ci 14988bf80f4bSopenharmony_civoid SceneHolder::ChangeCamera(SCENE_NS::ICamera::Ptr camera) 14998bf80f4bSopenharmony_ci{ 15008bf80f4bSopenharmony_ci if (auto cameraObject = interface_pointer_cast<SCENE_NS::IEcsObject>(camera)) { 15018bf80f4bSopenharmony_ci auto entity = cameraObject->GetEntity(); 15028bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 15038bf80f4bSopenharmony_ci SetMainCamera(entity); 15048bf80f4bSopenharmony_ci } 15058bf80f4bSopenharmony_ci } 15068bf80f4bSopenharmony_ci} 15078bf80f4bSopenharmony_ci 15088bf80f4bSopenharmony_civoid logNodes(const CORE3D_NS::ISceneNode& node, BASE_NS::string path) 15098bf80f4bSopenharmony_ci{ 15108bf80f4bSopenharmony_ci if (!path.empty() && path.back() != '/') { 15118bf80f4bSopenharmony_ci path.append("/"); 15128bf80f4bSopenharmony_ci } 15138bf80f4bSopenharmony_ci if (!node.GetName().empty()) { 15148bf80f4bSopenharmony_ci path.append(node.GetName()); 15158bf80f4bSopenharmony_ci } else { 15168bf80f4bSopenharmony_ci path.append("["); 15178bf80f4bSopenharmony_ci path.append(BASE_NS::to_string(node.GetEntity().id)); 15188bf80f4bSopenharmony_ci path.append("]"); 15198bf80f4bSopenharmony_ci } 15208bf80f4bSopenharmony_ci CORE_LOG_I("%s", path.c_str()); 15218bf80f4bSopenharmony_ci 15228bf80f4bSopenharmony_ci for (const auto child : node.GetChildren()) 15238bf80f4bSopenharmony_ci logNodes(*child, path); 15248bf80f4bSopenharmony_ci} 15258bf80f4bSopenharmony_ci 15268bf80f4bSopenharmony_civoid SceneHolder::SaveScene(const BASE_NS::string& fileName) 15278bf80f4bSopenharmony_ci{ 15288bf80f4bSopenharmony_ci assetManager_->SaveJsonEntityCollection(*scene_.get(), fileName.empty() ? sceneUri_ : fileName, "file://"); 15298bf80f4bSopenharmony_ci 15308bf80f4bSopenharmony_ci // Verbose logs, to be suppressed at some point 15318bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem& nodeSystem = *GetSystem<CORE3D_NS::INodeSystem>(*ecs_); 15328bf80f4bSopenharmony_ci logNodes(nodeSystem.GetRootNode(), "/"); 15338bf80f4bSopenharmony_ci IntrospectNodeless(); 15348bf80f4bSopenharmony_ci} 15358bf80f4bSopenharmony_ci 15368bf80f4bSopenharmony_ciCORE3D_NS::ISceneNode* SceneHolder::CreateNode(const BASE_NS::string& name) 15378bf80f4bSopenharmony_ci{ 15388bf80f4bSopenharmony_ci return CreateNode({}, name); 15398bf80f4bSopenharmony_ci} 15408bf80f4bSopenharmony_ci 15418bf80f4bSopenharmony_ciCORE3D_NS::ISceneNode* SceneHolder::CreateNode(const BASE_NS::string& path, const BASE_NS::string& name) 15428bf80f4bSopenharmony_ci{ 15438bf80f4bSopenharmony_ci if (ecs_) { 15448bf80f4bSopenharmony_ci auto pathWithoutRootNode = RemoveRootNodeFromPath(path); 15458bf80f4bSopenharmony_ci 15468bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem& nodeSystem = *GetSystem<CORE3D_NS::INodeSystem>(*ecs_); 15478bf80f4bSopenharmony_ci 15488bf80f4bSopenharmony_ci CORE3D_NS::ISceneNode* parent = nullptr; 15498bf80f4bSopenharmony_ci if (pathWithoutRootNode.empty()) { 15508bf80f4bSopenharmony_ci parent = rootNode_; 15518bf80f4bSopenharmony_ci } else { 15528bf80f4bSopenharmony_ci parent = rootNode_->LookupNodeByPath(pathWithoutRootNode); 15538bf80f4bSopenharmony_ci } 15548bf80f4bSopenharmony_ci 15558bf80f4bSopenharmony_ci CORE_ASSERT(parent); 15568bf80f4bSopenharmony_ci 15578bf80f4bSopenharmony_ci auto instanceRoot = nodeSystem.CreateNode(); 15588bf80f4bSopenharmony_ci instanceRoot->SetName(name); 15598bf80f4bSopenharmony_ci instanceRoot->SetParent(*parent); 15608bf80f4bSopenharmony_ci return instanceRoot; 15618bf80f4bSopenharmony_ci } else { 15628bf80f4bSopenharmony_ci CORE_LOG_E("%s: Ecs not available, can not create node %s", __func__, name.c_str()); 15638bf80f4bSopenharmony_ci } 15648bf80f4bSopenharmony_ci 15658bf80f4bSopenharmony_ci return nullptr; 15668bf80f4bSopenharmony_ci} 15678bf80f4bSopenharmony_ci 15688bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateMaterial(const BASE_NS::string& name) 15698bf80f4bSopenharmony_ci{ 15708bf80f4bSopenharmony_ci if (ecs_) { 15718bf80f4bSopenharmony_ci auto entity = ecs_->GetEntityManager().Create(); 15728bf80f4bSopenharmony_ci 15738bf80f4bSopenharmony_ci RenameEntity(entity, name); 15748bf80f4bSopenharmony_ci 15758bf80f4bSopenharmony_ci materialComponentManager_->Create(entity); 15768bf80f4bSopenharmony_ci scene_->AddEntityToSubcollection("created_materials", name, entity); 15778bf80f4bSopenharmony_ci ProcessEvents(); 15788bf80f4bSopenharmony_ci return entity; 15798bf80f4bSopenharmony_ci 15808bf80f4bSopenharmony_ci } else { 15818bf80f4bSopenharmony_ci CORE_LOG_E("%s: Ecs not available, can not create material %s", __func__, name.c_str()); 15828bf80f4bSopenharmony_ci } 15838bf80f4bSopenharmony_ci 15848bf80f4bSopenharmony_ci return {}; 15858bf80f4bSopenharmony_ci} 15868bf80f4bSopenharmony_ci 15878bf80f4bSopenharmony_civoid SceneHolder::RenameEntity(CORE_NS::Entity entity, const BASE_NS::string& name) 15888bf80f4bSopenharmony_ci{ 15898bf80f4bSopenharmony_ci if (ecs_) { 15908bf80f4bSopenharmony_ci // Name Component 15918bf80f4bSopenharmony_ci if (!nameComponentManager_->HasComponent(entity)) { 15928bf80f4bSopenharmony_ci nameComponentManager_->Create(entity); 15938bf80f4bSopenharmony_ci } 15948bf80f4bSopenharmony_ci if (auto nameHandle = nameComponentManager_->Write(entity)) { 15958bf80f4bSopenharmony_ci nameHandle->name = name; 15968bf80f4bSopenharmony_ci } 15978bf80f4bSopenharmony_ci 15988bf80f4bSopenharmony_ci // Root level entity collection item 15998bf80f4bSopenharmony_ci if (BASE_NS::string_view prevName = scene_->GetUniqueIdentifier(entity); !prevName.empty()) { 16008bf80f4bSopenharmony_ci scene_->SetUniqueIdentifier(name, scene_->GetEntity(prevName)); 16018bf80f4bSopenharmony_ci } else if (nodeComponentManager_->HasComponent(entity)) { 16028bf80f4bSopenharmony_ci if (auto ecsNode = nodeSystem_->GetNode(entity)) { 16038bf80f4bSopenharmony_ci if (const auto& children = ecsNode->GetChildren(); children.size()) { 16048bf80f4bSopenharmony_ci if (auto ix = scene_->GetSubCollectionIndexByRoot(children[0]->GetEntity()); ix != -1) { 16058bf80f4bSopenharmony_ci scene_->GetSubCollection(ix)->SetUri(name); 16068bf80f4bSopenharmony_ci } 16078bf80f4bSopenharmony_ci } 16088bf80f4bSopenharmony_ci } 16098bf80f4bSopenharmony_ci } 16108bf80f4bSopenharmony_ci // Experimentals: Subcollection root (will not traverse further, the rest should go through normal property 16118bf80f4bSopenharmony_ci // serialization) 16128bf80f4bSopenharmony_ci } 16138bf80f4bSopenharmony_ci} 16148bf80f4bSopenharmony_ci 16158bf80f4bSopenharmony_ci// Clone the entity, reference will be stored 16168bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CloneEntity(CORE_NS::Entity entity, const BASE_NS::string& name, bool storeWithUniqueId) 16178bf80f4bSopenharmony_ci{ 16188bf80f4bSopenharmony_ci CORE_NS::Entity ret {}; 16198bf80f4bSopenharmony_ci 16208bf80f4bSopenharmony_ci if (ecs_ && scene_) { 16218bf80f4bSopenharmony_ci ret = ecs_->GetEntityManager().Create(); 16228bf80f4bSopenharmony_ci CORE_NS::CloneComponents(*ecs_, entity, *ecs_, ret); 16238bf80f4bSopenharmony_ci RenameEntity(ret, name); 16248bf80f4bSopenharmony_ci // when cloning, we trust that implementation uses unique name so no padding required 16258bf80f4bSopenharmony_ci scene_->AddEntityToSubcollection("cloned_entities", name, ret, storeWithUniqueId); 16268bf80f4bSopenharmony_ci } 16278bf80f4bSopenharmony_ci return ret; 16288bf80f4bSopenharmony_ci} 16298bf80f4bSopenharmony_ci 16308bf80f4bSopenharmony_civoid SceneHolder::DestroyEntity(CORE_NS::Entity entity) 16318bf80f4bSopenharmony_ci{ 16328bf80f4bSopenharmony_ci // Destroy created materials & meshes here. 16338bf80f4bSopenharmony_ci auto meshCollectionIndex = scene_->GetSubCollectionIndex("GLTF_Meshes"); 16348bf80f4bSopenharmony_ci if (meshCollectionIndex != -1) { 16358bf80f4bSopenharmony_ci auto meshCollection = scene_->GetSubCollection(meshCollectionIndex); 16368bf80f4bSopenharmony_ci if (meshCollection->Contains(entity)) { 16378bf80f4bSopenharmony_ci auto ref = meshCollection->GetReference(entity); 16388bf80f4bSopenharmony_ci meshCollection->RemoveEntity(ref); 16398bf80f4bSopenharmony_ci } 16408bf80f4bSopenharmony_ci } 16418bf80f4bSopenharmony_ci 16428bf80f4bSopenharmony_ci auto materialCollectionIndex = scene_->GetSubCollectionIndex("GLTF_Materials"); 16438bf80f4bSopenharmony_ci if (materialCollectionIndex != -1) { 16448bf80f4bSopenharmony_ci auto materialCollection = scene_->GetSubCollection(materialCollectionIndex); 16458bf80f4bSopenharmony_ci if (materialCollection->Contains(entity)) { 16468bf80f4bSopenharmony_ci auto ref = materialCollection->GetReference(entity); 16478bf80f4bSopenharmony_ci materialCollection->RemoveEntity(ref); 16488bf80f4bSopenharmony_ci } 16498bf80f4bSopenharmony_ci } 16508bf80f4bSopenharmony_ci scene_->RemoveEntityRecursive(entity); 16518bf80f4bSopenharmony_ci} 16528bf80f4bSopenharmony_ci 16538bf80f4bSopenharmony_civoid SceneHolder::SetEntityActive(CORE_NS::Entity entity, bool active) 16548bf80f4bSopenharmony_ci{ 16558bf80f4bSopenharmony_ci ecs_->GetEntityManager().SetActive(entity, active); 16568bf80f4bSopenharmony_ci} 16578bf80f4bSopenharmony_ci 16588bf80f4bSopenharmony_cibool SceneHolder::ReparentEntity(CORE_NS::Entity entity, const BASE_NS::string& parentPath, size_t index) 16598bf80f4bSopenharmony_ci{ 16608bf80f4bSopenharmony_ci auto& root = nodeSystem_->GetRootNode(); 16618bf80f4bSopenharmony_ci 16628bf80f4bSopenharmony_ci auto node = nodeSystem_->GetNode(entity); 16638bf80f4bSopenharmony_ci if (!node) { 16648bf80f4bSopenharmony_ci CORE_LOG_W("SceneHolder::ReparentEntity, Failed to find node from entity."); 16658bf80f4bSopenharmony_ci return false; 16668bf80f4bSopenharmony_ci } 16678bf80f4bSopenharmony_ci 16688bf80f4bSopenharmony_ci auto parentNode = root.LookupNodeByPath(parentPath); 16698bf80f4bSopenharmony_ci if (!parentNode) { 16708bf80f4bSopenharmony_ci if (parentPath == "/" || parentPath.empty()) { 16718bf80f4bSopenharmony_ci parentNode = &root; 16728bf80f4bSopenharmony_ci } else { 16738bf80f4bSopenharmony_ci CORE_LOG_W("SceneHolder::ReparentEntity, Failed to find parent node '%s'", parentPath.c_str()); 16748bf80f4bSopenharmony_ci return false; 16758bf80f4bSopenharmony_ci } 16768bf80f4bSopenharmony_ci } 16778bf80f4bSopenharmony_ci 16788bf80f4bSopenharmony_ci if (parentNode != node->GetParent()) { 16798bf80f4bSopenharmony_ci if (index != SIZE_MAX) { 16808bf80f4bSopenharmony_ci parentNode->InsertChild(index, *node); 16818bf80f4bSopenharmony_ci } else { 16828bf80f4bSopenharmony_ci parentNode->AddChild(*node); 16838bf80f4bSopenharmony_ci } 16848bf80f4bSopenharmony_ci } 16858bf80f4bSopenharmony_ci 16868bf80f4bSopenharmony_ci return true; 16878bf80f4bSopenharmony_ci} 16888bf80f4bSopenharmony_ci 16898bf80f4bSopenharmony_ciconst CORE3D_NS::ISceneNode* SceneHolder::ReparentEntity(const BASE_NS::string& parentPath, const BASE_NS::string& name) 16908bf80f4bSopenharmony_ci{ 16918bf80f4bSopenharmony_ci if (ecs_) { 16928bf80f4bSopenharmony_ci const auto& root = nodeSystem_->GetRootNode(); 16938bf80f4bSopenharmony_ci auto ecsNode = root.LookupNodeByPath(name); 16948bf80f4bSopenharmony_ci auto parentNode = root.LookupNodeByPath(parentPath); 16958bf80f4bSopenharmony_ci 16968bf80f4bSopenharmony_ci if (!ecsNode && parentNode) { 16978bf80f4bSopenharmony_ci if (ecsNode = parentNode->LookupNodeByPath(name); !ecsNode) { 16988bf80f4bSopenharmony_ci CORE_LOG_W("Could not find: '%s', tried root and parent '%s'", name.c_str(), parentPath.c_str()); 16998bf80f4bSopenharmony_ci } 17008bf80f4bSopenharmony_ci } else if (parentNode && parentNode != ecsNode) { // prefabs may get have their path pointing them self 17018bf80f4bSopenharmony_ci // before they are positioned into scene 17028bf80f4bSopenharmony_ci const_cast<CORE3D_NS::ISceneNode*>(ecsNode)->SetParent(*parentNode); 17038bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("reparenting '%s' to '%s'", name.c_str(), parentPath.c_str()); 17048bf80f4bSopenharmony_ci } else if (!parentPath.empty() && parentPath != "/") { 17058bf80f4bSopenharmony_ci CORE_LOG_W("Could not find parent '%s'", parentPath.c_str()); 17068bf80f4bSopenharmony_ci // Even parent is not found, we can still activate the bindings, still we could 17078bf80f4bSopenharmony_ci // reschedule retry here 17088bf80f4bSopenharmony_ci } 17098bf80f4bSopenharmony_ci return ecsNode; 17108bf80f4bSopenharmony_ci } 17118bf80f4bSopenharmony_ci return {}; 17128bf80f4bSopenharmony_ci} 17138bf80f4bSopenharmony_ci 17148bf80f4bSopenharmony_civoid SceneHolder::SetMesh(CORE_NS::Entity targetEntity, CORE_NS::Entity mesh) 17158bf80f4bSopenharmony_ci{ 17168bf80f4bSopenharmony_ci if (ecs_) { 17178bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity) && EntityUtil::IsValid(mesh)) { 17188bf80f4bSopenharmony_ci // ToDo: should perhaps generate render mesh component for entity if it does not exist yet? 17198bf80f4bSopenharmony_ci 17208bf80f4bSopenharmony_ci if (!renderMeshComponentManager_->HasComponent(targetEntity)) { 17218bf80f4bSopenharmony_ci renderMeshComponentManager_->Create(targetEntity); 17228bf80f4bSopenharmony_ci } 17238bf80f4bSopenharmony_ci 17248bf80f4bSopenharmony_ci if (auto handle = renderMeshComponentManager_->Write(targetEntity)) { 17258bf80f4bSopenharmony_ci handle->mesh = mesh; 17268bf80f4bSopenharmony_ci } 17278bf80f4bSopenharmony_ci } 17288bf80f4bSopenharmony_ci } 17298bf80f4bSopenharmony_ci} 17308bf80f4bSopenharmony_ci 17318bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::GetMaterial(CORE_NS::Entity meshEntity, int64_t submeshIndex) 17328bf80f4bSopenharmony_ci{ 17338bf80f4bSopenharmony_ci CORE_NS::Entity material; 17348bf80f4bSopenharmony_ci if (ecs_) { 17358bf80f4bSopenharmony_ci if (EntityUtil::IsValid(meshEntity)) { 17368bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Read(meshEntity)) { 17378bf80f4bSopenharmony_ci if (submeshIndex >= 0 && submeshIndex < handle->submeshes.size()) { 17388bf80f4bSopenharmony_ci material = handle->submeshes[submeshIndex].material; 17398bf80f4bSopenharmony_ci } 17408bf80f4bSopenharmony_ci } 17418bf80f4bSopenharmony_ci } 17428bf80f4bSopenharmony_ci } 17438bf80f4bSopenharmony_ci return material; 17448bf80f4bSopenharmony_ci} 17458bf80f4bSopenharmony_ci 17468bf80f4bSopenharmony_ciBASE_NS::string_view SceneHolder::GetMaterialName(CORE_NS::Entity meshEntity, int64_t submeshIndex) 17478bf80f4bSopenharmony_ci{ 17488bf80f4bSopenharmony_ci BASE_NS::string_view entityName; 17498bf80f4bSopenharmony_ci auto entity = GetMaterial(meshEntity, submeshIndex); 17508bf80f4bSopenharmony_ci 17518bf80f4bSopenharmony_ci if (!GetEntityId(entity, entityName, *scene_.get(), "GLTF_Materials", *nameComponentManager_)) { 17528bf80f4bSopenharmony_ci CORE_LOG_W("%s: could not find material", __func__); 17538bf80f4bSopenharmony_ci } 17548bf80f4bSopenharmony_ci 17558bf80f4bSopenharmony_ci return entityName; 17568bf80f4bSopenharmony_ci} 17578bf80f4bSopenharmony_ci 17588bf80f4bSopenharmony_ciBASE_NS::string_view SceneHolder::GetMeshName(CORE_NS::Entity referringEntity) 17598bf80f4bSopenharmony_ci{ 17608bf80f4bSopenharmony_ci BASE_NS::string_view entityName; 17618bf80f4bSopenharmony_ci 17628bf80f4bSopenharmony_ci if (EntityUtil::IsValid(referringEntity)) { 17638bf80f4bSopenharmony_ci CORE_NS::Entity meshEntity; 17648bf80f4bSopenharmony_ci 17658bf80f4bSopenharmony_ci if (renderMeshComponentManager_->HasComponent(referringEntity)) { 17668bf80f4bSopenharmony_ci if (auto handle = renderMeshComponentManager_->Read(referringEntity)) { 17678bf80f4bSopenharmony_ci meshEntity = handle->mesh; 17688bf80f4bSopenharmony_ci } 17698bf80f4bSopenharmony_ci } else { 17708bf80f4bSopenharmony_ci CORE_LOG_W("%s: could not find mesh from entity", __func__); 17718bf80f4bSopenharmony_ci } 17728bf80f4bSopenharmony_ci if (!GetEntityId(meshEntity, entityName, *scene_.get(), "GLTF_Meshes", *nameComponentManager_)) { 17738bf80f4bSopenharmony_ci CORE_LOG_W("%s: could not find valid mesh", __func__); 17748bf80f4bSopenharmony_ci } 17758bf80f4bSopenharmony_ci } 17768bf80f4bSopenharmony_ci return entityName; 17778bf80f4bSopenharmony_ci} 17788bf80f4bSopenharmony_ci 17798bf80f4bSopenharmony_civoid SceneHolder::SetMaterial(CORE_NS::Entity targetEntity, CORE_NS::Entity material, int64_t submeshIndex) 17808bf80f4bSopenharmony_ci{ 17818bf80f4bSopenharmony_ci if (ecs_) { 17828bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 17838bf80f4bSopenharmony_ci // ToDo: should perhaps generate mesh component for entity if it does not exist yet? 17848bf80f4bSopenharmony_ci 17858bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Write(targetEntity)) { 17868bf80f4bSopenharmony_ci if (submeshIndex == -1) { 17878bf80f4bSopenharmony_ci for (auto&& submesh : handle->submeshes) { 17888bf80f4bSopenharmony_ci submesh.material = material; 17898bf80f4bSopenharmony_ci } 17908bf80f4bSopenharmony_ci } else if (submeshIndex >= 0 && submeshIndex < handle->submeshes.size()) { 17918bf80f4bSopenharmony_ci handle->submeshes[submeshIndex].material = material; 17928bf80f4bSopenharmony_ci } 17938bf80f4bSopenharmony_ci } 17948bf80f4bSopenharmony_ci } 17958bf80f4bSopenharmony_ci } 17968bf80f4bSopenharmony_ci} 17978bf80f4bSopenharmony_ci 17988bf80f4bSopenharmony_ciCORE_NS::EntityReference SceneHolder::BindUIBitmap(SCENE_NS::IBitmap::Ptr bitmap, bool createNew) 17998bf80f4bSopenharmony_ci{ 18008bf80f4bSopenharmony_ci if (ecs_) { 18018bf80f4bSopenharmony_ci BASE_NS::string uri; 18028bf80f4bSopenharmony_ci RENDER_NS::RenderHandleReference imageHandle {}; 18038bf80f4bSopenharmony_ci 18048bf80f4bSopenharmony_ci // Need two things, uri 18058bf80f4bSopenharmony_ci if (auto uriBmp = interface_pointer_cast<SCENE_NS::IBitmap>(bitmap)) { 18068bf80f4bSopenharmony_ci uri = uriBmp->Uri()->GetValue(); 18078bf80f4bSopenharmony_ci } else { 18088bf80f4bSopenharmony_ci uri = interface_pointer_cast<META_NS::IObjectInstance>(bitmap)->GetInstanceId().ToString(); 18098bf80f4bSopenharmony_ci } 18108bf80f4bSopenharmony_ci 18118bf80f4bSopenharmony_ci // And concrete handle to data 18128bf80f4bSopenharmony_ci if (auto lumeBmp = interface_pointer_cast<SCENE_NS::IBitmap>(bitmap)) { 18138bf80f4bSopenharmony_ci imageHandle = lumeBmp->GetRenderHandle(); 18148bf80f4bSopenharmony_ci } 18158bf80f4bSopenharmony_ci 18168bf80f4bSopenharmony_ci if (imageHandle) { 18178bf80f4bSopenharmony_ci // check if we have existing resource 18188bf80f4bSopenharmony_ci CORE_NS::Entity existing; 18198bf80f4bSopenharmony_ci if (FindResource(uri, uri, existing)) { 18208bf80f4bSopenharmony_ci auto hande = rhComponentManager_->Get(existing); 18218bf80f4bSopenharmony_ci hande.reference = imageHandle; 18228bf80f4bSopenharmony_ci rhComponentManager_->Set(existing, hande); 18238bf80f4bSopenharmony_ci 18248bf80f4bSopenharmony_ci return ecs_->GetEntityManager().GetReferenceCounted(existing); 18258bf80f4bSopenharmony_ci } 18268bf80f4bSopenharmony_ci 18278bf80f4bSopenharmony_ci if (!createNew) { 18288bf80f4bSopenharmony_ci return {}; 18298bf80f4bSopenharmony_ci } 18308bf80f4bSopenharmony_ci 18318bf80f4bSopenharmony_ci // if not, create new one 18328bf80f4bSopenharmony_ci EntityReference entity = ecs_->GetEntityManager().CreateReferenceCounted(); 18338bf80f4bSopenharmony_ci 18348bf80f4bSopenharmony_ci nameComponentManager_->Create(entity); 18358bf80f4bSopenharmony_ci auto component = nameComponentManager_->Get(entity); 18368bf80f4bSopenharmony_ci component.name = uri; 18378bf80f4bSopenharmony_ci nameComponentManager_->Set(entity, component); 18388bf80f4bSopenharmony_ci 18398bf80f4bSopenharmony_ci // Not sure if we should do this, somehow we need to keep the entity alive 18408bf80f4bSopenharmony_ci // with proper uri it could be found afterwards 18418bf80f4bSopenharmony_ci auto& subcollection = scene_->AddSubCollection(uri, "bitmap://"); 18428bf80f4bSopenharmony_ci subcollection.AddEntity(entity); 18438bf80f4bSopenharmony_ci 18448bf80f4bSopenharmony_ci // Or this. We should perhaps use URI component more 18458bf80f4bSopenharmony_ci rhComponentManager_->Create(entity); 18468bf80f4bSopenharmony_ci auto hande = rhComponentManager_->Get(entity); 18478bf80f4bSopenharmony_ci hande.reference = imageHandle; 18488bf80f4bSopenharmony_ci rhComponentManager_->Set(entity, hande); 18498bf80f4bSopenharmony_ci return entity; 18508bf80f4bSopenharmony_ci } 18518bf80f4bSopenharmony_ci } 18528bf80f4bSopenharmony_ci 18538bf80f4bSopenharmony_ci return {}; 18548bf80f4bSopenharmony_ci} 18558bf80f4bSopenharmony_ci 18568bf80f4bSopenharmony_civoid SceneHolder::SetTexture(size_t index, CORE_NS::Entity targetEntity, CORE_NS::EntityReference imageEntity) 18578bf80f4bSopenharmony_ci{ 18588bf80f4bSopenharmony_ci if (ecs_) { 18598bf80f4bSopenharmony_ci if (auto handle = materialComponentManager_->Write(targetEntity)) { 18608bf80f4bSopenharmony_ci handle->textures[index].image = imageEntity; 18618bf80f4bSopenharmony_ci } 18628bf80f4bSopenharmony_ci } 18638bf80f4bSopenharmony_ci} 18648bf80f4bSopenharmony_ci 18658bf80f4bSopenharmony_ciBASE_NS::string_view ResolveSamplerUri(SCENE_NS::ITextureInfo::SamplerId samplerId) 18668bf80f4bSopenharmony_ci{ 18678bf80f4bSopenharmony_ci switch (samplerId) { 18688bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_NEAREST_REPEAT: 18698bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_NEAREST_REPEAT"; 18708bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP: 18718bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_NEAREST_CLAMP"; 18728bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_LINEAR_REPEAT: 18738bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_LINEAR_REPEAT"; 18748bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP: 18758bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_LINEAR_CLAMP"; 18768bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_REPEAT: 18778bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_REPEAT"; 18788bf80f4bSopenharmony_ci case SCENE_NS::ITextureInfo::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP: 18798bf80f4bSopenharmony_ci return "engine://CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP"; 18808bf80f4bSopenharmony_ci default: 18818bf80f4bSopenharmony_ci CORE_LOG_W("%s: unable to find sampler uri for: %d", __func__, samplerId); 18828bf80f4bSopenharmony_ci } 18838bf80f4bSopenharmony_ci 18848bf80f4bSopenharmony_ci return ""; 18858bf80f4bSopenharmony_ci} 18868bf80f4bSopenharmony_ci 18878bf80f4bSopenharmony_cistatic constexpr size_t ENGINE_URI_PREFIX_LEN = BASE_NS::string_view("engine://").size(); 18888bf80f4bSopenharmony_ci 18898bf80f4bSopenharmony_ciSCENE_NS::IShader::Ptr SceneHolder::GetShader(CORE_NS::Entity materialEntity, ShaderType type) 18908bf80f4bSopenharmony_ci{ 18918bf80f4bSopenharmony_ci // Resolve render handle from material. 18928bf80f4bSopenharmony_ci if (!ecs_) { 18938bf80f4bSopenharmony_ci return {}; 18948bf80f4bSopenharmony_ci } 18958bf80f4bSopenharmony_ci 18968bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 18978bf80f4bSopenharmony_ci return {}; 18988bf80f4bSopenharmony_ci } 18998bf80f4bSopenharmony_ci 19008bf80f4bSopenharmony_ci RENDER_NS::RenderHandleReference shaderHandleRef; 19018bf80f4bSopenharmony_ci 19028bf80f4bSopenharmony_ci EntityReference shaderEntityRef {}; 19038bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 19048bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 19058bf80f4bSopenharmony_ci shaderEntityRef = readHandle->materialShader.shader; 19068bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 19078bf80f4bSopenharmony_ci shaderEntityRef = readHandle->depthShader.shader; 19088bf80f4bSopenharmony_ci } 19098bf80f4bSopenharmony_ci } 19108bf80f4bSopenharmony_ci 19118bf80f4bSopenharmony_ci if (shaderEntityRef) { 19128bf80f4bSopenharmony_ci auto rh = rhComponentManager_->GetRenderHandleReference(shaderEntityRef); 19138bf80f4bSopenharmony_ci if (RENDER_NS::RenderHandleUtil::IsValid(rh.GetHandle())) { 19148bf80f4bSopenharmony_ci auto uri = GetHandleUri(rh, HANDLE_TYPE_SHADER); 19158bf80f4bSopenharmony_ci if (!uri.empty()) { 19168bf80f4bSopenharmony_ci auto shader = SCENE_NS::Shader(); 19178bf80f4bSopenharmony_ci 19188bf80f4bSopenharmony_ci auto shaderInterface = interface_pointer_cast<SCENE_NS::IShader>(shader); 19198bf80f4bSopenharmony_ci SetValue(shaderInterface->Uri(), uri); 19208bf80f4bSopenharmony_ci 19218bf80f4bSopenharmony_ci return shader; 19228bf80f4bSopenharmony_ci } 19238bf80f4bSopenharmony_ci } 19248bf80f4bSopenharmony_ci } 19258bf80f4bSopenharmony_ci 19268bf80f4bSopenharmony_ci return {}; 19278bf80f4bSopenharmony_ci} 19288bf80f4bSopenharmony_ci 19298bf80f4bSopenharmony_ciSCENE_NS::IGraphicsState::Ptr SceneHolder::GetGraphicsState(CORE_NS::Entity materialEntity, ShaderType type) 19308bf80f4bSopenharmony_ci{ 19318bf80f4bSopenharmony_ci // Resolve render handle from material. 19328bf80f4bSopenharmony_ci if (!ecs_) { 19338bf80f4bSopenharmony_ci return {}; 19348bf80f4bSopenharmony_ci } 19358bf80f4bSopenharmony_ci 19368bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 19378bf80f4bSopenharmony_ci return {}; 19388bf80f4bSopenharmony_ci } 19398bf80f4bSopenharmony_ci 19408bf80f4bSopenharmony_ci RENDER_NS::RenderHandleReference shaderHandleRef; 19418bf80f4bSopenharmony_ci 19428bf80f4bSopenharmony_ci EntityReference stateEntityRef {}; 19438bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 19448bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 19458bf80f4bSopenharmony_ci stateEntityRef = readHandle->materialShader.graphicsState; 19468bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 19478bf80f4bSopenharmony_ci stateEntityRef = readHandle->depthShader.graphicsState; 19488bf80f4bSopenharmony_ci } 19498bf80f4bSopenharmony_ci } 19508bf80f4bSopenharmony_ci 19518bf80f4bSopenharmony_ci if (stateEntityRef) { 19528bf80f4bSopenharmony_ci auto rh = rhComponentManager_->GetRenderHandleReference(stateEntityRef); 19538bf80f4bSopenharmony_ci if (RENDER_NS::RenderHandleUtil::IsValid(rh.GetHandle())) { 19548bf80f4bSopenharmony_ci auto uri = GetHandleUri(rh); 19558bf80f4bSopenharmony_ci if (!uri.empty()) { 19568bf80f4bSopenharmony_ci auto state = SCENE_NS::GraphicsState(); 19578bf80f4bSopenharmony_ci 19588bf80f4bSopenharmony_ci auto interface = interface_pointer_cast<SCENE_NS::IGraphicsState>(state); 19598bf80f4bSopenharmony_ci 19608bf80f4bSopenharmony_ci // The uri contains either .shader or .shadergs. 19618bf80f4bSopenharmony_ci BASE_NS::string extension = ".shadergs"; 19628bf80f4bSopenharmony_ci if (uri.find(extension) == BASE_NS::string::npos) { 19638bf80f4bSopenharmony_ci extension = ".shader"; 19648bf80f4bSopenharmony_ci } 19658bf80f4bSopenharmony_ci 19668bf80f4bSopenharmony_ci // Split the uri to uri and variant. 19678bf80f4bSopenharmony_ci auto ix = uri.find_last_of(extension); 19688bf80f4bSopenharmony_ci if (ix != BASE_NS::string_view::npos && ix < uri.size() - 1) { 19698bf80f4bSopenharmony_ci SetValue(interface->Uri(), BASE_NS::string(uri.substr(0, ix + 1))); 19708bf80f4bSopenharmony_ci SetValue(interface->Variant(), BASE_NS::string(uri.substr(ix + 1))); 19718bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Got graphics state: %s variant: %s", 19728bf80f4bSopenharmony_ci META_NS::GetValue(interface->Uri()).c_str(), META_NS::GetValue(interface->Variant()).c_str()); 19738bf80f4bSopenharmony_ci } else { 19748bf80f4bSopenharmony_ci SetValue(interface->Uri(), uri); 19758bf80f4bSopenharmony_ci SetValue(interface->Variant(), ""); 19768bf80f4bSopenharmony_ci } 19778bf80f4bSopenharmony_ci 19788bf80f4bSopenharmony_ci if (auto shRef = interface_cast<ISceneHolderRef>(state)) { 19798bf80f4bSopenharmony_ci shRef->SetSceneHolder(me_); 19808bf80f4bSopenharmony_ci shRef->SetIndex(type); 19818bf80f4bSopenharmony_ci } 19828bf80f4bSopenharmony_ci 19838bf80f4bSopenharmony_ci return state; 19848bf80f4bSopenharmony_ci } 19858bf80f4bSopenharmony_ci } 19868bf80f4bSopenharmony_ci } 19878bf80f4bSopenharmony_ci 19888bf80f4bSopenharmony_ci return {}; 19898bf80f4bSopenharmony_ci} 19908bf80f4bSopenharmony_ci 19918bf80f4bSopenharmony_civoid SceneHolder::SetGraphicsState( 19928bf80f4bSopenharmony_ci CORE_NS::Entity materialEntity, ShaderType type, const RENDER_NS::GraphicsState& state) 19938bf80f4bSopenharmony_ci{ 19948bf80f4bSopenharmony_ci if (!ecs_) { 19958bf80f4bSopenharmony_ci return; 19968bf80f4bSopenharmony_ci } 19978bf80f4bSopenharmony_ci 19988bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 19998bf80f4bSopenharmony_ci return; 20008bf80f4bSopenharmony_ci } 20018bf80f4bSopenharmony_ci 20028bf80f4bSopenharmony_ci CORE_NS::EntityReference entityRef; 20038bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 20048bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 20058bf80f4bSopenharmony_ci entityRef = readHandle->materialShader.graphicsState; 20068bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 20078bf80f4bSopenharmony_ci entityRef = readHandle->depthShader.graphicsState; 20088bf80f4bSopenharmony_ci } 20098bf80f4bSopenharmony_ci } 20108bf80f4bSopenharmony_ci 20118bf80f4bSopenharmony_ci auto rh = rhComponentManager_->GetRenderHandleReference(entityRef); 20128bf80f4bSopenharmony_ci if (RENDER_NS::RenderHandleUtil::IsValid(rh.GetHandle())) { 20138bf80f4bSopenharmony_ci auto& engineShaderManager = renderContext_->GetDevice().GetShaderManager(); 20148bf80f4bSopenharmony_ci auto hash = engineShaderManager.HashGraphicsState(state); 20158bf80f4bSopenharmony_ci auto currentState = engineShaderManager.GetGraphicsState(rh); 20168bf80f4bSopenharmony_ci if (hash != engineShaderManager.HashGraphicsState(currentState)) { 20178bf80f4bSopenharmony_ci auto desc = engineShaderManager.GetIdDesc(rh); 20188bf80f4bSopenharmony_ci engineShaderManager.CreateGraphicsState({ desc.path, state }); 20198bf80f4bSopenharmony_ci } 20208bf80f4bSopenharmony_ci } 20218bf80f4bSopenharmony_ci} 20228bf80f4bSopenharmony_ci 20238bf80f4bSopenharmony_cibool SceneHolder::GetGraphicsState( 20248bf80f4bSopenharmony_ci CORE_NS::Entity materialEntity, ShaderType type, const SCENE_NS::IShaderGraphicsState::Ptr& ret) 20258bf80f4bSopenharmony_ci{ 20268bf80f4bSopenharmony_ci if (!ecs_) { 20278bf80f4bSopenharmony_ci return false; 20288bf80f4bSopenharmony_ci } 20298bf80f4bSopenharmony_ci 20308bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 20318bf80f4bSopenharmony_ci return false; 20328bf80f4bSopenharmony_ci } 20338bf80f4bSopenharmony_ci 20348bf80f4bSopenharmony_ci CORE_NS::EntityReference entityRef; 20358bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 20368bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 20378bf80f4bSopenharmony_ci entityRef = readHandle->materialShader.graphicsState; 20388bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 20398bf80f4bSopenharmony_ci entityRef = readHandle->depthShader.graphicsState; 20408bf80f4bSopenharmony_ci } 20418bf80f4bSopenharmony_ci } 20428bf80f4bSopenharmony_ci auto rh = rhComponentManager_->GetRenderHandleReference(entityRef); 20438bf80f4bSopenharmony_ci if (RENDER_NS::RenderHandleUtil::IsValid(rh.GetHandle())) { 20448bf80f4bSopenharmony_ci auto& engineShaderManager = renderContext_->GetDevice().GetShaderManager(); 20458bf80f4bSopenharmony_ci auto state = engineShaderManager.GetGraphicsState(rh); 20468bf80f4bSopenharmony_ci if (auto typed = interface_cast<SCENE_NS::IPendingRequestData<RENDER_NS::GraphicsState>>(ret)) { 20478bf80f4bSopenharmony_ci typed->Add(state); 20488bf80f4bSopenharmony_ci return true; 20498bf80f4bSopenharmony_ci } 20508bf80f4bSopenharmony_ci } 20518bf80f4bSopenharmony_ci return false; 20528bf80f4bSopenharmony_ci} 20538bf80f4bSopenharmony_ci 20548bf80f4bSopenharmony_civoid SceneHolder::SetShader(CORE_NS::Entity materialEntity, ShaderType type, SCENE_NS::IShader::Ptr shader) 20558bf80f4bSopenharmony_ci{ 20568bf80f4bSopenharmony_ci if (!ecs_) { 20578bf80f4bSopenharmony_ci return; 20588bf80f4bSopenharmony_ci } 20598bf80f4bSopenharmony_ci 20608bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 20618bf80f4bSopenharmony_ci return; 20628bf80f4bSopenharmony_ci } 20638bf80f4bSopenharmony_ci 20648bf80f4bSopenharmony_ci EntityReference shaderEntityRef {}; 20658bf80f4bSopenharmony_ci RenderHandleReference rh {}; 20668bf80f4bSopenharmony_ci 20678bf80f4bSopenharmony_ci auto& engineShaderManager = renderContext_->GetDevice().GetShaderManager(); 20688bf80f4bSopenharmony_ci if (shader) { 20698bf80f4bSopenharmony_ci rh = shader->GetRenderHandleReference(engineShaderManager); 20708bf80f4bSopenharmony_ci auto uri = META_NS::GetValue(shader->Uri()); 20718bf80f4bSopenharmony_ci 20728bf80f4bSopenharmony_ci if (RenderHandleUtil::IsValid(rh.GetHandle())) { 20738bf80f4bSopenharmony_ci shaderEntityRef = GetOrCreateEntityReference(ecs_->GetEntityManager(), *rhComponentManager_, rh); 20748bf80f4bSopenharmony_ci // Studio used to update also uri component, maybe someone else should do this 20758bf80f4bSopenharmony_ci // if needed to begin with 20768bf80f4bSopenharmony_ci if (!uriComponentManager_->HasComponent(shaderEntityRef)) { 20778bf80f4bSopenharmony_ci uriComponentManager_->Create(shaderEntityRef); 20788bf80f4bSopenharmony_ci } 20798bf80f4bSopenharmony_ci if (auto handle = uriComponentManager_->Write(shaderEntityRef)) { 20808bf80f4bSopenharmony_ci handle->uri = uri; 20818bf80f4bSopenharmony_ci } 20828bf80f4bSopenharmony_ci } else { 20838bf80f4bSopenharmony_ci CORE_LOG_W("Failed to set shader, invalid render handle: %s", uri.c_str()); 20848bf80f4bSopenharmony_ci return; 20858bf80f4bSopenharmony_ci } 20868bf80f4bSopenharmony_ci if (auto shref = interface_cast<ISceneHolderRef>(shader)) { 20878bf80f4bSopenharmony_ci shref->SetSceneHolder(me_); 20888bf80f4bSopenharmony_ci shref->SetIndex(type); 20898bf80f4bSopenharmony_ci } 20908bf80f4bSopenharmony_ci } 20918bf80f4bSopenharmony_ci 20928bf80f4bSopenharmony_ci // Only writing the value if it has changed. 20938bf80f4bSopenharmony_ci bool valueChanged = false; 20948bf80f4bSopenharmony_ci 20958bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 20968bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 20978bf80f4bSopenharmony_ci valueChanged = readHandle->materialShader.shader != shaderEntityRef; 20988bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 20998bf80f4bSopenharmony_ci valueChanged = readHandle->depthShader.shader != shaderEntityRef; 21008bf80f4bSopenharmony_ci } 21018bf80f4bSopenharmony_ci } 21028bf80f4bSopenharmony_ci 21038bf80f4bSopenharmony_ci if (!valueChanged) { 21048bf80f4bSopenharmony_ci return; 21058bf80f4bSopenharmony_ci } 21068bf80f4bSopenharmony_ci 21078bf80f4bSopenharmony_ci if (auto writeHandle = materialComponentManager_->Write(materialEntity)) { 21088bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 21098bf80f4bSopenharmony_ci writeHandle->materialShader.shader = shaderEntityRef; 21108bf80f4bSopenharmony_ci if (!writeHandle->materialShader.graphicsState) { 21118bf80f4bSopenharmony_ci // initialize the graphics state handle, so we can resolve it later 21128bf80f4bSopenharmony_ci if (auto graphicsStateHandle = engineShaderManager.GetGraphicsStateHandleByShaderHandle(rh)) { 21138bf80f4bSopenharmony_ci writeHandle->materialShader.graphicsState = 21148bf80f4bSopenharmony_ci GetOrCreateEntityReference(ecs_->GetEntityManager(), *rhComponentManager_, graphicsStateHandle); 21158bf80f4bSopenharmony_ci } 21168bf80f4bSopenharmony_ci } 21178bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 21188bf80f4bSopenharmony_ci writeHandle->depthShader.shader = shaderEntityRef; 21198bf80f4bSopenharmony_ci if (!writeHandle->depthShader.graphicsState) { 21208bf80f4bSopenharmony_ci if (auto graphicsStateHandle = engineShaderManager.GetGraphicsStateHandleByShaderHandle(rh)) { 21218bf80f4bSopenharmony_ci writeHandle->depthShader.graphicsState = 21228bf80f4bSopenharmony_ci GetOrCreateEntityReference(ecs_->GetEntityManager(), *rhComponentManager_, graphicsStateHandle); 21238bf80f4bSopenharmony_ci } 21248bf80f4bSopenharmony_ci } 21258bf80f4bSopenharmony_ci } 21268bf80f4bSopenharmony_ci } 21278bf80f4bSopenharmony_ci 21288bf80f4bSopenharmony_ci ProcessEvents(); 21298bf80f4bSopenharmony_ci} 21308bf80f4bSopenharmony_ci 21318bf80f4bSopenharmony_civoid SceneHolder::SetGraphicsState(CORE_NS::Entity materialEntity, ShaderType type, SCENE_NS::IGraphicsState::Ptr state) 21328bf80f4bSopenharmony_ci{ 21338bf80f4bSopenharmony_ci if (!ecs_) { 21348bf80f4bSopenharmony_ci return; 21358bf80f4bSopenharmony_ci } 21368bf80f4bSopenharmony_ci 21378bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(materialEntity)) { 21388bf80f4bSopenharmony_ci return; 21398bf80f4bSopenharmony_ci } 21408bf80f4bSopenharmony_ci 21418bf80f4bSopenharmony_ci EntityReference stateEntityRef {}; 21428bf80f4bSopenharmony_ci if (state) { 21438bf80f4bSopenharmony_ci auto& engineShaderManager = renderContext_->GetDevice().GetShaderManager(); 21448bf80f4bSopenharmony_ci auto rh = state->GetRenderHandleReference(engineShaderManager); 21458bf80f4bSopenharmony_ci 21468bf80f4bSopenharmony_ci if (RenderHandleUtil::IsValid(rh.GetHandle())) { 21478bf80f4bSopenharmony_ci auto uri = META_NS::GetValue(state->Uri()); 21488bf80f4bSopenharmony_ci auto variant = META_NS::GetValue(state->Variant()); 21498bf80f4bSopenharmony_ci 21508bf80f4bSopenharmony_ci stateEntityRef = GetOrCreateEntityReference(ecs_->GetEntityManager(), *rhComponentManager_, rh); 21518bf80f4bSopenharmony_ci // Studio used to update also uri component, maybe someone else should do this 21528bf80f4bSopenharmony_ci // if needed to begin with 21538bf80f4bSopenharmony_ci if (!uriComponentManager_->HasComponent(stateEntityRef)) { 21548bf80f4bSopenharmony_ci uriComponentManager_->Create(stateEntityRef); 21558bf80f4bSopenharmony_ci } 21568bf80f4bSopenharmony_ci if (auto handle = uriComponentManager_->Write(stateEntityRef)) { 21578bf80f4bSopenharmony_ci handle->uri = uri.append(variant); 21588bf80f4bSopenharmony_ci } 21598bf80f4bSopenharmony_ci } else { 21608bf80f4bSopenharmony_ci CORE_LOG_W("Failed to set shader, invalid render handle: %s", META_NS::GetValue(state->Uri()).c_str()); 21618bf80f4bSopenharmony_ci return; 21628bf80f4bSopenharmony_ci } 21638bf80f4bSopenharmony_ci if (auto shref = interface_cast<ISceneHolderRef>(state)) { 21648bf80f4bSopenharmony_ci shref->SetSceneHolder(me_); 21658bf80f4bSopenharmony_ci shref->SetIndex(type); 21668bf80f4bSopenharmony_ci } 21678bf80f4bSopenharmony_ci } 21688bf80f4bSopenharmony_ci 21698bf80f4bSopenharmony_ci // Only writing the value if it has changed. 21708bf80f4bSopenharmony_ci bool valueChanged = false; 21718bf80f4bSopenharmony_ci 21728bf80f4bSopenharmony_ci if (auto readHandle = materialComponentManager_->Read(materialEntity)) { 21738bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 21748bf80f4bSopenharmony_ci valueChanged = readHandle->materialShader.graphicsState != stateEntityRef; 21758bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 21768bf80f4bSopenharmony_ci valueChanged = readHandle->depthShader.graphicsState != stateEntityRef; 21778bf80f4bSopenharmony_ci } 21788bf80f4bSopenharmony_ci } 21798bf80f4bSopenharmony_ci 21808bf80f4bSopenharmony_ci if (!valueChanged) { 21818bf80f4bSopenharmony_ci return; 21828bf80f4bSopenharmony_ci } 21838bf80f4bSopenharmony_ci 21848bf80f4bSopenharmony_ci if (auto writeHandle = materialComponentManager_->Write(materialEntity)) { 21858bf80f4bSopenharmony_ci if (type == ShaderType::MATERIAL_SHADER) { 21868bf80f4bSopenharmony_ci writeHandle->materialShader.graphicsState = stateEntityRef; 21878bf80f4bSopenharmony_ci } else if (type == ShaderType::DEPTH_SHADER) { 21888bf80f4bSopenharmony_ci writeHandle->depthShader.graphicsState = stateEntityRef; 21898bf80f4bSopenharmony_ci } 21908bf80f4bSopenharmony_ci } 21918bf80f4bSopenharmony_ci 21928bf80f4bSopenharmony_ci ProcessEvents(); 21938bf80f4bSopenharmony_ci} 21948bf80f4bSopenharmony_ci 21958bf80f4bSopenharmony_ciBASE_NS::string SceneHolder::GetHandleUri(RENDER_NS::RenderHandleReference renderHandleReference, UriHandleType type) 21968bf80f4bSopenharmony_ci{ 21978bf80f4bSopenharmony_ci if (ecs_ && renderContext_) { 21988bf80f4bSopenharmony_ci auto& device = renderContext_->GetDevice(); 21998bf80f4bSopenharmony_ci 22008bf80f4bSopenharmony_ci auto& shaderManager = device.GetShaderManager(); 22018bf80f4bSopenharmony_ci 22028bf80f4bSopenharmony_ci if ((type == HANDLE_TYPE_SHADER && shaderManager.IsShader(renderHandleReference)) || 22038bf80f4bSopenharmony_ci (type == HANDLE_TYPE_DO_NOT_CARE)) { 22048bf80f4bSopenharmony_ci auto desc = shaderManager.GetIdDesc(renderHandleReference); 22058bf80f4bSopenharmony_ci return desc.path; 22068bf80f4bSopenharmony_ci } 22078bf80f4bSopenharmony_ci } 22088bf80f4bSopenharmony_ci return BASE_NS::string(); 22098bf80f4bSopenharmony_ci} 22108bf80f4bSopenharmony_ci 22118bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::LoadSampler(BASE_NS::string_view uri) 22128bf80f4bSopenharmony_ci{ 22138bf80f4bSopenharmony_ci CORE_NS::Entity ret; 22148bf80f4bSopenharmony_ci if (ecs_ && renderContext_) { 22158bf80f4bSopenharmony_ci const auto name = uri.substr(ENGINE_URI_PREFIX_LEN); 22168bf80f4bSopenharmony_ci auto linearHandle = renderContext_->GetDevice().GetGpuResourceManager().GetSamplerHandle(name); 22178bf80f4bSopenharmony_ci 22188bf80f4bSopenharmony_ci auto entity = rhComponentManager_->GetEntityWithReference(linearHandle); 22198bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(entity)) { 22208bf80f4bSopenharmony_ci // No existing sampler found, prepare one 22218bf80f4bSopenharmony_ci auto uriManager = GetManager<CORE3D_NS::IUriComponentManager>(*ecs_); 22228bf80f4bSopenharmony_ci entity = ecs_->GetEntityManager().Create(); 22238bf80f4bSopenharmony_ci 22248bf80f4bSopenharmony_ci uriManager->Create(entity); 22258bf80f4bSopenharmony_ci uriManager->Write(entity)->uri = uri; 22268bf80f4bSopenharmony_ci 22278bf80f4bSopenharmony_ci rhComponentManager_->Create(entity); 22288bf80f4bSopenharmony_ci rhComponentManager_->Write(entity)->reference = linearHandle; 22298bf80f4bSopenharmony_ci 22308bf80f4bSopenharmony_ci RenameEntity(entity, BASE_NS::string(name.data(), name.size())); 22318bf80f4bSopenharmony_ci scene_->AddEntityToSubcollection("samplers", name, entity, false); 22328bf80f4bSopenharmony_ci } 22338bf80f4bSopenharmony_ci ret = entity; 22348bf80f4bSopenharmony_ci } 22358bf80f4bSopenharmony_ci 22368bf80f4bSopenharmony_ci return ret; 22378bf80f4bSopenharmony_ci} 22388bf80f4bSopenharmony_ci 22398bf80f4bSopenharmony_ciCORE_NS::EntityReference SceneHolder::LoadImage(BASE_NS::string_view uri, RENDER_NS::RenderHandleReference rh) 22408bf80f4bSopenharmony_ci{ 22418bf80f4bSopenharmony_ci CORE_NS::Entity ret; 22428bf80f4bSopenharmony_ci if (FindResource(uri, uri, ret)) { 22438bf80f4bSopenharmony_ci return ecs_->GetEntityManager().GetReferenceCounted(ret); 22448bf80f4bSopenharmony_ci } 22458bf80f4bSopenharmony_ci 22468bf80f4bSopenharmony_ci if (scene_ && assetManager_) { 22478bf80f4bSopenharmony_ci RENDER_NS::RenderHandleReference imageHandle; 22488bf80f4bSopenharmony_ci if (rh) { 22498bf80f4bSopenharmony_ci imageHandle = rh; 22508bf80f4bSopenharmony_ci } else { 22518bf80f4bSopenharmony_ci imageHandle = assetManager_->GetEcsSerializer().LoadImageResource(uri); 22528bf80f4bSopenharmony_ci } 22538bf80f4bSopenharmony_ci if (imageHandle) { 22548bf80f4bSopenharmony_ci return GetOrCreateEntityReference(ecs_->GetEntityManager(), *rhComponentManager_, imageHandle); 22558bf80f4bSopenharmony_ci } 22568bf80f4bSopenharmony_ci } 22578bf80f4bSopenharmony_ci 22588bf80f4bSopenharmony_ci return {}; 22598bf80f4bSopenharmony_ci} 22608bf80f4bSopenharmony_ci 22618bf80f4bSopenharmony_civoid SceneHolder::SetSampler(size_t index, CORE_NS::Entity targetEntity, SCENE_NS::ITextureInfo::SamplerId samplerId) 22628bf80f4bSopenharmony_ci{ 22638bf80f4bSopenharmony_ci if (ecs_) { 22648bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 22658bf80f4bSopenharmony_ci bool wrote = false; 22668bf80f4bSopenharmony_ci if (auto handle = materialComponentManager_->Write(targetEntity)) { 22678bf80f4bSopenharmony_ci auto entity = LoadSampler(ResolveSamplerUri(samplerId)); 22688bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 22698bf80f4bSopenharmony_ci // both scene and texture array will hold a reference to entity 22708bf80f4bSopenharmony_ci handle->textures[index].sampler = ecs_->GetEntityManager().GetReferenceCounted(entity); 22718bf80f4bSopenharmony_ci wrote = true; 22728bf80f4bSopenharmony_ci } 22738bf80f4bSopenharmony_ci } 22748bf80f4bSopenharmony_ci if (wrote) { 22758bf80f4bSopenharmony_ci ProcessEvents(); 22768bf80f4bSopenharmony_ci } 22778bf80f4bSopenharmony_ci } 22788bf80f4bSopenharmony_ci } 22798bf80f4bSopenharmony_ci} 22808bf80f4bSopenharmony_ci 22818bf80f4bSopenharmony_civoid SceneHolder::SetSubmeshRenderSortOrder(CORE_NS::Entity targetEntity, int64_t submeshIndex, uint8_t value) 22828bf80f4bSopenharmony_ci{ 22838bf80f4bSopenharmony_ci if (ecs_) { 22848bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 22858bf80f4bSopenharmony_ci bool wrote = false; 22868bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Write(targetEntity)) { 22878bf80f4bSopenharmony_ci if (submeshIndex >= 0 && submeshIndex < handle->submeshes.size()) { 22888bf80f4bSopenharmony_ci handle->submeshes[submeshIndex].renderSortLayerOrder = value; 22898bf80f4bSopenharmony_ci wrote = true; 22908bf80f4bSopenharmony_ci } 22918bf80f4bSopenharmony_ci } 22928bf80f4bSopenharmony_ci if (wrote) { 22938bf80f4bSopenharmony_ci ProcessEvents(); 22948bf80f4bSopenharmony_ci } 22958bf80f4bSopenharmony_ci } 22968bf80f4bSopenharmony_ci } 22978bf80f4bSopenharmony_ci} 22988bf80f4bSopenharmony_ci 22998bf80f4bSopenharmony_civoid SceneHolder::SetSubmeshAABBMin(CORE_NS::Entity targetEntity, int64_t submeshIndex, const BASE_NS::Math::Vec3& vec) 23008bf80f4bSopenharmony_ci{ 23018bf80f4bSopenharmony_ci if (ecs_) { 23028bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 23038bf80f4bSopenharmony_ci bool wrote = false; 23048bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Write(targetEntity)) { 23058bf80f4bSopenharmony_ci if (submeshIndex >= 0 && submeshIndex < handle->submeshes.size()) { 23068bf80f4bSopenharmony_ci handle->submeshes[submeshIndex].aabbMin = vec; 23078bf80f4bSopenharmony_ci handle->aabbMin = min(handle->aabbMin, vec); 23088bf80f4bSopenharmony_ci wrote = true; 23098bf80f4bSopenharmony_ci } 23108bf80f4bSopenharmony_ci } 23118bf80f4bSopenharmony_ci if (wrote) { 23128bf80f4bSopenharmony_ci ProcessEvents(); 23138bf80f4bSopenharmony_ci } 23148bf80f4bSopenharmony_ci } 23158bf80f4bSopenharmony_ci } 23168bf80f4bSopenharmony_ci} 23178bf80f4bSopenharmony_ci 23188bf80f4bSopenharmony_civoid SceneHolder::RemoveSubmesh(CORE_NS::Entity targetEntity, int64_t submeshIndex) 23198bf80f4bSopenharmony_ci{ 23208bf80f4bSopenharmony_ci if (ecs_) { 23218bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 23228bf80f4bSopenharmony_ci bool wrote = false; 23238bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Write(targetEntity)) { 23248bf80f4bSopenharmony_ci if (submeshIndex < 0) { 23258bf80f4bSopenharmony_ci handle->submeshes.clear(); 23268bf80f4bSopenharmony_ci handle->aabbMin = { 0.f, 0.f, 0.f }; 23278bf80f4bSopenharmony_ci handle->aabbMax = { 0.f, 0.f, 0.f }; 23288bf80f4bSopenharmony_ci wrote = true; 23298bf80f4bSopenharmony_ci } else if (submeshIndex < handle->submeshes.size()) { 23308bf80f4bSopenharmony_ci handle->submeshes.erase(handle->submeshes.begin() + submeshIndex); 23318bf80f4bSopenharmony_ci for (const auto& submesh : handle->submeshes) { 23328bf80f4bSopenharmony_ci handle->aabbMin = BASE_NS::Math::min(handle->aabbMin, submesh.aabbMin); 23338bf80f4bSopenharmony_ci handle->aabbMax = BASE_NS::Math::max(handle->aabbMax, submesh.aabbMax); 23348bf80f4bSopenharmony_ci } 23358bf80f4bSopenharmony_ci wrote = true; 23368bf80f4bSopenharmony_ci } 23378bf80f4bSopenharmony_ci } 23388bf80f4bSopenharmony_ci if (wrote) { 23398bf80f4bSopenharmony_ci ProcessEvents(); 23408bf80f4bSopenharmony_ci } 23418bf80f4bSopenharmony_ci } 23428bf80f4bSopenharmony_ci } 23438bf80f4bSopenharmony_ci} 23448bf80f4bSopenharmony_ci 23458bf80f4bSopenharmony_civoid SceneHolder::SetSubmeshAABBMax(CORE_NS::Entity targetEntity, int64_t submeshIndex, const BASE_NS::Math::Vec3& vec) 23468bf80f4bSopenharmony_ci{ 23478bf80f4bSopenharmony_ci if (ecs_) { 23488bf80f4bSopenharmony_ci if (EntityUtil::IsValid(targetEntity)) { 23498bf80f4bSopenharmony_ci bool wrote = false; 23508bf80f4bSopenharmony_ci if (auto handle = meshComponentManager_->Write(targetEntity)) { 23518bf80f4bSopenharmony_ci if (submeshIndex >= 0 && submeshIndex < handle->submeshes.size()) { 23528bf80f4bSopenharmony_ci handle->submeshes[submeshIndex].aabbMax = vec; 23538bf80f4bSopenharmony_ci handle->aabbMax = max(handle->aabbMax, vec); 23548bf80f4bSopenharmony_ci wrote = true; 23558bf80f4bSopenharmony_ci } 23568bf80f4bSopenharmony_ci } 23578bf80f4bSopenharmony_ci if (wrote) { 23588bf80f4bSopenharmony_ci ProcessEvents(); 23598bf80f4bSopenharmony_ci } 23608bf80f4bSopenharmony_ci } 23618bf80f4bSopenharmony_ci } 23628bf80f4bSopenharmony_ci} 23638bf80f4bSopenharmony_ci 23648bf80f4bSopenharmony_civoid SceneHolder::EnableEnvironmentComponent(CORE_NS::Entity entity) 23658bf80f4bSopenharmony_ci{ 23668bf80f4bSopenharmony_ci if (ecs_) { 23678bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 23688bf80f4bSopenharmony_ci if (!envComponentManager_->HasComponent(entity)) { 23698bf80f4bSopenharmony_ci envComponentManager_->Create(entity); 23708bf80f4bSopenharmony_ci } 23718bf80f4bSopenharmony_ci } 23728bf80f4bSopenharmony_ci } 23738bf80f4bSopenharmony_ci} 23748bf80f4bSopenharmony_ci 23758bf80f4bSopenharmony_civoid SceneHolder::EnableLayerComponent(CORE_NS::Entity entity) 23768bf80f4bSopenharmony_ci{ 23778bf80f4bSopenharmony_ci if (ecs_) { 23788bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 23798bf80f4bSopenharmony_ci if (!layerComponentManager_->HasComponent(entity)) { 23808bf80f4bSopenharmony_ci layerComponentManager_->Create(entity); 23818bf80f4bSopenharmony_ci } 23828bf80f4bSopenharmony_ci } 23838bf80f4bSopenharmony_ci } 23848bf80f4bSopenharmony_ci} 23858bf80f4bSopenharmony_ci 23868bf80f4bSopenharmony_civoid SceneHolder::EnableLightComponent(CORE_NS::Entity entity) 23878bf80f4bSopenharmony_ci{ 23888bf80f4bSopenharmony_ci if (ecs_) { 23898bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 23908bf80f4bSopenharmony_ci if (!lightComponentManager_->HasComponent(entity)) { 23918bf80f4bSopenharmony_ci lightComponentManager_->Create(entity); 23928bf80f4bSopenharmony_ci } 23938bf80f4bSopenharmony_ci } 23948bf80f4bSopenharmony_ci } 23958bf80f4bSopenharmony_ci} 23968bf80f4bSopenharmony_ci 23978bf80f4bSopenharmony_citemplate<typename T> 23988bf80f4bSopenharmony_ciconstexpr inline CORE3D_NS::IMeshBuilder::DataBuffer FillData(array_view<const T> c) noexcept 23998bf80f4bSopenharmony_ci{ 24008bf80f4bSopenharmony_ci Format format = BASE_FORMAT_UNDEFINED; 24018bf80f4bSopenharmony_ci if constexpr (is_same_v<T, Math::Vec2>) { 24028bf80f4bSopenharmony_ci format = BASE_FORMAT_R32G32_SFLOAT; 24038bf80f4bSopenharmony_ci } else if constexpr (is_same_v<T, Math::Vec3>) { 24048bf80f4bSopenharmony_ci format = BASE_FORMAT_R32G32B32_SFLOAT; 24058bf80f4bSopenharmony_ci } else if constexpr (is_same_v<T, Math::Vec4>) { 24068bf80f4bSopenharmony_ci format = BASE_FORMAT_R32G32B32A32_SFLOAT; 24078bf80f4bSopenharmony_ci } else if constexpr (is_same_v<T, uint16_t>) { 24088bf80f4bSopenharmony_ci format = BASE_FORMAT_R16_UINT; 24098bf80f4bSopenharmony_ci } else if constexpr (is_same_v<T, uint32_t>) { 24108bf80f4bSopenharmony_ci format = BASE_FORMAT_R32_UINT; 24118bf80f4bSopenharmony_ci } 24128bf80f4bSopenharmony_ci return CORE3D_NS::IMeshBuilder::DataBuffer { format, sizeof(T), 24138bf80f4bSopenharmony_ci { reinterpret_cast<const uint8_t*>(c.data()), c.size() * sizeof(T) } }; 24148bf80f4bSopenharmony_ci} 24158bf80f4bSopenharmony_ci 24168bf80f4bSopenharmony_citemplate<typename IndicesType> 24178bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateMeshFromArrays(const BASE_NS::string& name, 24188bf80f4bSopenharmony_ci SCENE_NS::MeshGeometryArrayPtr<IndicesType> arrays, RENDER_NS::IndexType indexType, Entity existingEntity, 24198bf80f4bSopenharmony_ci bool append) 24208bf80f4bSopenharmony_ci{ 24218bf80f4bSopenharmony_ci if (!ecs_) { 24228bf80f4bSopenharmony_ci CORE_LOG_W("%s: no ecs, cannot create mesh", __func__); 24238bf80f4bSopenharmony_ci return {}; 24248bf80f4bSopenharmony_ci } 24258bf80f4bSopenharmony_ci 24268bf80f4bSopenharmony_ci if (!arrays || arrays->size() == 0) { 24278bf80f4bSopenharmony_ci if (EntityUtil::IsValid(existingEntity)) { 24288bf80f4bSopenharmony_ci RemoveSubmesh(existingEntity, -1); 24298bf80f4bSopenharmony_ci return existingEntity; 24308bf80f4bSopenharmony_ci } else { 24318bf80f4bSopenharmony_ci // create empty, submeshes may follow 24328bf80f4bSopenharmony_ci auto entity = ecs_->GetEntityManager().Create(); 24338bf80f4bSopenharmony_ci 24348bf80f4bSopenharmony_ci RenameEntity(entity, name); 24358bf80f4bSopenharmony_ci 24368bf80f4bSopenharmony_ci meshComponentManager_->Create(entity); 24378bf80f4bSopenharmony_ci scene_->AddEntityToSubcollection("created_meshes", name, entity); 24388bf80f4bSopenharmony_ci return entity; 24398bf80f4bSopenharmony_ci } 24408bf80f4bSopenharmony_ci } 24418bf80f4bSopenharmony_ci 24428bf80f4bSopenharmony_ci if (EntityUtil::IsValid(existingEntity) && !append) { 24438bf80f4bSopenharmony_ci RemoveSubmesh(existingEntity, -1); 24448bf80f4bSopenharmony_ci } 24458bf80f4bSopenharmony_ci 24468bf80f4bSopenharmony_ci size_t subMeshIndex = 0; 24478bf80f4bSopenharmony_ci auto meshBuilder = CORE_NS::CreateInstance<CORE3D_NS::IMeshBuilder>(*renderContext_, CORE3D_NS::UID_MESH_BUILDER); 24488bf80f4bSopenharmony_ci 24498bf80f4bSopenharmony_ci RENDER_NS::IShaderManager& shaderManager = renderContext_->GetDevice().GetShaderManager(); 24508bf80f4bSopenharmony_ci const RENDER_NS::VertexInputDeclarationView vertexInputDeclaration = 24518bf80f4bSopenharmony_ci shaderManager.GetVertexInputDeclarationView(shaderManager.GetVertexInputDeclarationHandle( 24528bf80f4bSopenharmony_ci CORE3D_NS::DefaultMaterialShaderConstants::VERTEX_INPUT_DECLARATION_FORWARD)); 24538bf80f4bSopenharmony_ci 24548bf80f4bSopenharmony_ci meshBuilder->Initialize(vertexInputDeclaration, 1); 24558bf80f4bSopenharmony_ci 24568bf80f4bSopenharmony_ci for (auto&& geometry : *arrays.get()) { 24578bf80f4bSopenharmony_ci CORE3D_NS::IMeshBuilder::Submesh submesh; 24588bf80f4bSopenharmony_ci 24598bf80f4bSopenharmony_ci submesh.indexType = indexType; 24608bf80f4bSopenharmony_ci submesh.vertexCount = static_cast<uint32_t>(geometry->vertices.size()); 24618bf80f4bSopenharmony_ci submesh.indexCount = static_cast<uint32_t>(geometry->indices.size()); 24628bf80f4bSopenharmony_ci submesh.tangents = geometry->generateTangents; 24638bf80f4bSopenharmony_ci 24648bf80f4bSopenharmony_ci meshBuilder->AddSubmesh(submesh); 24658bf80f4bSopenharmony_ci } 24668bf80f4bSopenharmony_ci meshBuilder->Allocate(); 24678bf80f4bSopenharmony_ci 24688bf80f4bSopenharmony_ci for (auto&& geometry : *arrays.get()) { 24698bf80f4bSopenharmony_ci meshBuilder->SetVertexData(subMeshIndex, FillData<BASE_NS::Math::Vec3>(geometry->vertices), 24708bf80f4bSopenharmony_ci FillData<BASE_NS::Math::Vec3>(geometry->normals), FillData<BASE_NS::Math::Vec2>(geometry->uvs), 24718bf80f4bSopenharmony_ci FillData<BASE_NS::Math::Vec2>(geometry->uv2s), FillData<BASE_NS::Math::Vec4>(geometry->tangents), 24728bf80f4bSopenharmony_ci FillData<BASE_NS::Math::Vec4>(geometry->colors)); 24738bf80f4bSopenharmony_ci meshBuilder->CalculateAABB(subMeshIndex, FillData<BASE_NS::Math::Vec3>(geometry->vertices)); 24748bf80f4bSopenharmony_ci meshBuilder->SetIndexData(subMeshIndex, FillData<IndicesType>(geometry->indices)); 24758bf80f4bSopenharmony_ci } 24768bf80f4bSopenharmony_ci 24778bf80f4bSopenharmony_ci auto entity = meshBuilder->CreateMesh(*ecs_); 24788bf80f4bSopenharmony_ci 24798bf80f4bSopenharmony_ci if (EntityUtil::IsValid(existingEntity)) { 24808bf80f4bSopenharmony_ci for (size_t ii = 0; ii < arrays->size(); ii++) { 24818bf80f4bSopenharmony_ci CopySubMesh(existingEntity, entity, ii); 24828bf80f4bSopenharmony_ci } 24838bf80f4bSopenharmony_ci ecs_->GetEntityManager().Destroy(entity); 24848bf80f4bSopenharmony_ci return existingEntity; 24858bf80f4bSopenharmony_ci } 24868bf80f4bSopenharmony_ci 24878bf80f4bSopenharmony_ci RenameEntity(entity, name); 24888bf80f4bSopenharmony_ci scene_->AddEntityToSubcollection("created_meshes", name, entity); 24898bf80f4bSopenharmony_ci 24908bf80f4bSopenharmony_ci ProcessEvents(); 24918bf80f4bSopenharmony_ci return entity; 24928bf80f4bSopenharmony_ci} 24938bf80f4bSopenharmony_ci 24948bf80f4bSopenharmony_ci// we rely that someone else will ret up correct flags to components 24958bf80f4bSopenharmony_civoid SceneHolder::SetMultiviewCamera(CORE_NS::Entity target, CORE_NS::Entity source) 24968bf80f4bSopenharmony_ci{ 24978bf80f4bSopenharmony_ci if (!ecs_ || !EntityUtil::IsValid(target) || !EntityUtil::IsValid(source) || 24988bf80f4bSopenharmony_ci !cameraComponentManager_->HasComponent(source) || !cameraComponentManager_->HasComponent(target)) { 24998bf80f4bSopenharmony_ci CORE_LOG_W("%s: camera component not valid", __func__); 25008bf80f4bSopenharmony_ci return; 25018bf80f4bSopenharmony_ci } 25028bf80f4bSopenharmony_ci if (auto handle = cameraComponentManager_->Write(target)) { 25038bf80f4bSopenharmony_ci for (auto& ref : handle->multiViewCameras) { 25048bf80f4bSopenharmony_ci if (ref.id == target.id) { 25058bf80f4bSopenharmony_ci return; 25068bf80f4bSopenharmony_ci } 25078bf80f4bSopenharmony_ci } 25088bf80f4bSopenharmony_ci handle->multiViewCameras.push_back(source); 25098bf80f4bSopenharmony_ci } 25108bf80f4bSopenharmony_ci} 25118bf80f4bSopenharmony_ci 25128bf80f4bSopenharmony_ci// we rely that someone else will ret up correct flags to components 25138bf80f4bSopenharmony_civoid SceneHolder::RemoveMultiviewCamera(CORE_NS::Entity target, CORE_NS::Entity source) 25148bf80f4bSopenharmony_ci{ 25158bf80f4bSopenharmony_ci if (!ecs_ || !EntityUtil::IsValid(target) || !EntityUtil::IsValid(source) || 25168bf80f4bSopenharmony_ci !cameraComponentManager_->HasComponent(source) || !cameraComponentManager_->HasComponent(target)) { 25178bf80f4bSopenharmony_ci CORE_LOG_W("%s: camera component not valid", __func__); 25188bf80f4bSopenharmony_ci return; 25198bf80f4bSopenharmony_ci } 25208bf80f4bSopenharmony_ci if (auto handle = cameraComponentManager_->Write(target)) { 25218bf80f4bSopenharmony_ci for (size_t ii = 0; ii < handle->multiViewCameras.size(); ii++) { 25228bf80f4bSopenharmony_ci if (handle->multiViewCameras[ii] == target) { 25238bf80f4bSopenharmony_ci handle->multiViewCameras.erase(handle->multiViewCameras.cbegin() + ii); 25248bf80f4bSopenharmony_ci return; 25258bf80f4bSopenharmony_ci } 25268bf80f4bSopenharmony_ci } 25278bf80f4bSopenharmony_ci } 25288bf80f4bSopenharmony_ci} 25298bf80f4bSopenharmony_ci 25308bf80f4bSopenharmony_civoid SceneHolder::CopySubMesh(CORE_NS::Entity target, CORE_NS::Entity source, size_t index) 25318bf80f4bSopenharmony_ci{ 25328bf80f4bSopenharmony_ci if (!ecs_ || !EntityUtil::IsValid(target) || !EntityUtil::IsValid(source) || 25338bf80f4bSopenharmony_ci !meshComponentManager_->HasComponent(source)) { 25348bf80f4bSopenharmony_ci CORE_LOG_W("%s: cannot copy submesh", __func__); 25358bf80f4bSopenharmony_ci return; 25368bf80f4bSopenharmony_ci } 25378bf80f4bSopenharmony_ci 25388bf80f4bSopenharmony_ci bool wrote = false; 25398bf80f4bSopenharmony_ci if (auto sourceComponent = meshComponentManager_->Read(source)) { 25408bf80f4bSopenharmony_ci if (sourceComponent->submeshes.size() > index) { 25418bf80f4bSopenharmony_ci if (!meshComponentManager_->HasComponent(target)) { 25428bf80f4bSopenharmony_ci meshComponentManager_->Create(target); 25438bf80f4bSopenharmony_ci } 25448bf80f4bSopenharmony_ci if (auto targetComponent = meshComponentManager_->Write(target)) { 25458bf80f4bSopenharmony_ci targetComponent->submeshes.push_back(CORE3D_NS::MeshComponent::Submesh()); 25468bf80f4bSopenharmony_ci // Todo: verify if copy by assignment is enough, or do we need deep copy 25478bf80f4bSopenharmony_ci // and explicit reference modifications 25488bf80f4bSopenharmony_ci targetComponent->submeshes.back() = sourceComponent->submeshes.at(index); 25498bf80f4bSopenharmony_ci for (const auto& submesh : targetComponent->submeshes) { 25508bf80f4bSopenharmony_ci targetComponent->aabbMin = BASE_NS::Math::min(targetComponent->aabbMin, submesh.aabbMin); 25518bf80f4bSopenharmony_ci targetComponent->aabbMax = BASE_NS::Math::max(targetComponent->aabbMax, submesh.aabbMax); 25528bf80f4bSopenharmony_ci } 25538bf80f4bSopenharmony_ci wrote = true; 25548bf80f4bSopenharmony_ci } 25558bf80f4bSopenharmony_ci } 25568bf80f4bSopenharmony_ci } 25578bf80f4bSopenharmony_ci if (wrote) { 25588bf80f4bSopenharmony_ci ProcessEvents(); 25598bf80f4bSopenharmony_ci } 25608bf80f4bSopenharmony_ci} 25618bf80f4bSopenharmony_ci 25628bf80f4bSopenharmony_civoid SceneHolder::ReleaseOwnership(CORE_NS::Entity entity) 25638bf80f4bSopenharmony_ci{ 25648bf80f4bSopenharmony_ci if (ecs_ && scene_) { 25658bf80f4bSopenharmony_ci if (EntityUtil::IsValid(entity)) { 25668bf80f4bSopenharmony_ci if (const auto cachedEntity = FindCachedRelatedEntity(entity); 25678bf80f4bSopenharmony_ci EntityUtil::IsValid(cachedEntity) && entity != cachedEntity) { 25688bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("%s: Cached entity does not match: entity: %I64u, cachedEntity: %I64u", 25698bf80f4bSopenharmony_ci __func__, entity.id, cachedEntity.id); 25708bf80f4bSopenharmony_ci if (auto cachedIdx = scene_->GetSubCollectionIndexByRoot(cachedEntity); cachedIdx != -1) { 25718bf80f4bSopenharmony_ci scene_->GetSubCollection(cachedIdx)->SetActive(false); 25728bf80f4bSopenharmony_ci scene_->RemoveEntityRecursive(cachedEntity); 25738bf80f4bSopenharmony_ci } 25748bf80f4bSopenharmony_ci } 25758bf80f4bSopenharmony_ci scene_->RemoveEntityRecursive(entity); 25768bf80f4bSopenharmony_ci } 25778bf80f4bSopenharmony_ci } 25788bf80f4bSopenharmony_ci} 25798bf80f4bSopenharmony_ci 25808bf80f4bSopenharmony_ci// Reposition a node within its parent 25818bf80f4bSopenharmony_civoid SceneHolder::ReindexEntity(CORE_NS::Entity target, size_t index) 25828bf80f4bSopenharmony_ci{ 25838bf80f4bSopenharmony_ci if (ecs_ && scene_ && EntityUtil::IsValid(target)) { 25848bf80f4bSopenharmony_ci // Get the node 25858bf80f4bSopenharmony_ci if (auto node = nodeSystem_->GetNode(target)) { 25868bf80f4bSopenharmony_ci // Get the parent 25878bf80f4bSopenharmony_ci if (auto parent = node->GetParent()) { 25888bf80f4bSopenharmony_ci parent->RemoveChild(*node); 25898bf80f4bSopenharmony_ci parent->InsertChild(index, *node); 25908bf80f4bSopenharmony_ci } 25918bf80f4bSopenharmony_ci } 25928bf80f4bSopenharmony_ci 25938bf80f4bSopenharmony_ci // do we need to adjust also collection manually (it should be reference only) 25948bf80f4bSopenharmony_ci scene_->MarkModified(true, true); 25958bf80f4bSopenharmony_ci } 25968bf80f4bSopenharmony_ci} 25978bf80f4bSopenharmony_ci 25988bf80f4bSopenharmony_citemplate CORE_NS::Entity SceneHolder::CreateMeshFromArrays<uint16_t>(const BASE_NS::string& name, 25998bf80f4bSopenharmony_ci SCENE_NS::MeshGeometryArrayPtr<uint16_t> arrays, RENDER_NS::IndexType indexType, Entity existingEntity, 26008bf80f4bSopenharmony_ci bool append); 26018bf80f4bSopenharmony_ci 26028bf80f4bSopenharmony_citemplate CORE_NS::Entity SceneHolder::CreateMeshFromArrays<uint32_t>(const BASE_NS::string& name, 26038bf80f4bSopenharmony_ci SCENE_NS::MeshGeometryArrayPtr<uint32_t> arrays, RENDER_NS::IndexType indexType, Entity existingEntity, 26048bf80f4bSopenharmony_ci bool append); 26058bf80f4bSopenharmony_ci 26068bf80f4bSopenharmony_cistring SceneHolder::GetUniqueName() 26078bf80f4bSopenharmony_ci{ 26088bf80f4bSopenharmony_ci return instanceId_.ToString().append(to_string(++instanceNumber_)); 26098bf80f4bSopenharmony_ci} 26108bf80f4bSopenharmony_ci 26118bf80f4bSopenharmony_ci// Enable new multi-mesh batch 26128bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::CreateMultiMeshInstance(CORE_NS::Entity baseComponent) 26138bf80f4bSopenharmony_ci{ 26148bf80f4bSopenharmony_ci if (ecs_) { 26158bf80f4bSopenharmony_ci if (!nodeSystem_->GetNode(baseComponent)) { 26168bf80f4bSopenharmony_ci CORE_LOG_I("%s: selected base entity does not have node on ecs", __func__); 26178bf80f4bSopenharmony_ci 26188bf80f4bSopenharmony_ci // Now, the assumption is that entity should have either RenderMeshComponent or MeshComponent 26198bf80f4bSopenharmony_ci // It is bit open if it has render mesh component, shoud we copy its mesh data implicitly 26208bf80f4bSopenharmony_ci CORE3D_NS::RenderMeshComponent renderMeshData; 26218bf80f4bSopenharmony_ci 26228bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(baseComponent)) { 26238bf80f4bSopenharmony_ci renderMeshData = *data; 26248bf80f4bSopenharmony_ci } 26258bf80f4bSopenharmony_ci 26268bf80f4bSopenharmony_ci auto node = nodeSystem_->CreateNode(); 26278bf80f4bSopenharmony_ci auto nodeEntity = node->GetEntity(); 26288bf80f4bSopenharmony_ci 26298bf80f4bSopenharmony_ci renderMeshComponentManager_->Create(nodeEntity); 26308bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Write(nodeEntity)) { 26318bf80f4bSopenharmony_ci *data = renderMeshData; 26328bf80f4bSopenharmony_ci 26338bf80f4bSopenharmony_ci if (!EntityUtil::IsValid(data->mesh)) { 26348bf80f4bSopenharmony_ci // base component may have mesh component, or then it does not 26358bf80f4bSopenharmony_ci data->mesh = baseComponent; 26368bf80f4bSopenharmony_ci } 26378bf80f4bSopenharmony_ci } 26388bf80f4bSopenharmony_ci baseComponent = nodeEntity; 26398bf80f4bSopenharmony_ci } 26408bf80f4bSopenharmony_ci 26418bf80f4bSopenharmony_ci if (!renderMeshComponentManager_->HasComponent(baseComponent)) { 26428bf80f4bSopenharmony_ci renderMeshComponentManager_->Create(baseComponent); 26438bf80f4bSopenharmony_ci } 26448bf80f4bSopenharmony_ci } 26458bf80f4bSopenharmony_ci 26468bf80f4bSopenharmony_ci return baseComponent; 26478bf80f4bSopenharmony_ci} 26488bf80f4bSopenharmony_ci 26498bf80f4bSopenharmony_cistatic constexpr size_t MULTI_MESH_CHILD_PREFIX_LEN = MULTI_MESH_CHILD_PREFIX.size(); 26508bf80f4bSopenharmony_ci 26518bf80f4bSopenharmony_cibool SceneHolder::IsMultiMeshChild(const CORE3D_NS::ISceneNode* child) 26528bf80f4bSopenharmony_ci{ 26538bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 26548bf80f4bSopenharmony_ci if (auto nameHandle = nameComponentManager_->Read(entity)) { 26558bf80f4bSopenharmony_ci auto name = BASE_NS::string_view(nameHandle->name.data(), nameHandle->name.size()); 26568bf80f4bSopenharmony_ci if (name.compare(0, MULTI_MESH_CHILD_PREFIX_LEN, MULTI_MESH_CHILD_PREFIX) == 0) { 26578bf80f4bSopenharmony_ci return true; 26588bf80f4bSopenharmony_ci } 26598bf80f4bSopenharmony_ci } 26608bf80f4bSopenharmony_ci return false; 26618bf80f4bSopenharmony_ci} 26628bf80f4bSopenharmony_ci 26638bf80f4bSopenharmony_ciCORE_NS::Entity SceneHolder::FindCachedRelatedEntity(const CORE_NS::Entity& entity) 26648bf80f4bSopenharmony_ci{ 26658bf80f4bSopenharmony_ci if (!(scene_ && nodeSystem_ && CORE_NS::EntityUtil::IsValid(entity))) { 26668bf80f4bSopenharmony_ci return {}; 26678bf80f4bSopenharmony_ci } 26688bf80f4bSopenharmony_ci 26698bf80f4bSopenharmony_ci CORE_NS::Entity cachedEntity {}; 26708bf80f4bSopenharmony_ci if (const auto node = nodeSystem_->GetNode(entity)) { 26718bf80f4bSopenharmony_ci if (const auto idx = scene_->GetSubCollectionIndex(node->GetName()); idx != -1) { 26728bf80f4bSopenharmony_ci cachedEntity = scene_->GetSubCollection(idx)->GetEntity("/"); 26738bf80f4bSopenharmony_ci } 26748bf80f4bSopenharmony_ci } 26758bf80f4bSopenharmony_ci 26768bf80f4bSopenharmony_ci return cachedEntity; 26778bf80f4bSopenharmony_ci} 26788bf80f4bSopenharmony_ci 26798bf80f4bSopenharmony_ci// Set mesh to multi-mesh 26808bf80f4bSopenharmony_civoid SceneHolder::SetMeshMultimeshArray(CORE_NS::Entity target, CORE_NS::Entity mesh) 26818bf80f4bSopenharmony_ci{ 26828bf80f4bSopenharmony_ci if (ecs_) { 26838bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Write(target)) { 26848bf80f4bSopenharmony_ci data->mesh = mesh; 26858bf80f4bSopenharmony_ci } 26868bf80f4bSopenharmony_ci 26878bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 26888bf80f4bSopenharmony_ci MeshComponent givenData; 26898bf80f4bSopenharmony_ci if (auto givenMeshData = meshComponentManager_->Read(mesh)) { 26908bf80f4bSopenharmony_ci givenData = *givenMeshData; 26918bf80f4bSopenharmony_ci } 26928bf80f4bSopenharmony_ci 26938bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 26948bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 26958bf80f4bSopenharmony_ci if (!IsMultiMeshChild(child)) { 26968bf80f4bSopenharmony_ci continue; 26978bf80f4bSopenharmony_ci } 26988bf80f4bSopenharmony_ci 26998bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(entity)) { 27008bf80f4bSopenharmony_ci auto mesh = data->mesh; 27018bf80f4bSopenharmony_ci if (auto meshData = meshComponentManager_->Write(mesh)) { 27028bf80f4bSopenharmony_ci *meshData = givenData; 27038bf80f4bSopenharmony_ci } 27048bf80f4bSopenharmony_ci } 27058bf80f4bSopenharmony_ci 27068bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Write(entity)) { 27078bf80f4bSopenharmony_ci data->renderMeshBatch = target; 27088bf80f4bSopenharmony_ci } 27098bf80f4bSopenharmony_ci } 27108bf80f4bSopenharmony_ci } 27118bf80f4bSopenharmony_ci } 27128bf80f4bSopenharmony_ci} 27138bf80f4bSopenharmony_ci 27148bf80f4bSopenharmony_civoid SetAll(CORE_NS::Entity target, CORE_NS::Entity material, BASE_NS::vector<CORE_NS::Entity>& ret, 27158bf80f4bSopenharmony_ci CORE3D_NS::IMeshComponentManager* meshComponentManager) 27168bf80f4bSopenharmony_ci{ 27178bf80f4bSopenharmony_ci if (EntityUtil::IsValid(target)) { 27188bf80f4bSopenharmony_ci if (auto handle = meshComponentManager->Write(target)) { 27198bf80f4bSopenharmony_ci for (auto&& submesh : handle->submeshes) { 27208bf80f4bSopenharmony_ci ret.push_back(submesh.material); 27218bf80f4bSopenharmony_ci submesh.material = material; 27228bf80f4bSopenharmony_ci } 27238bf80f4bSopenharmony_ci } 27248bf80f4bSopenharmony_ci } 27258bf80f4bSopenharmony_ci} 27268bf80f4bSopenharmony_ci 27278bf80f4bSopenharmony_civoid ResetAll(CORE_NS::Entity target, BASE_NS::vector<CORE_NS::Entity>& in, 27288bf80f4bSopenharmony_ci CORE3D_NS::IMeshComponentManager* meshComponentManager) 27298bf80f4bSopenharmony_ci{ 27308bf80f4bSopenharmony_ci if (EntityUtil::IsValid(target)) { 27318bf80f4bSopenharmony_ci if (auto handle = meshComponentManager->Write(target)) { 27328bf80f4bSopenharmony_ci for (auto&& submesh : handle->submeshes) { 27338bf80f4bSopenharmony_ci if (in.size() > 0) { 27348bf80f4bSopenharmony_ci submesh.material = in.front(); 27358bf80f4bSopenharmony_ci in.erase(in.begin()); 27368bf80f4bSopenharmony_ci } 27378bf80f4bSopenharmony_ci } 27388bf80f4bSopenharmony_ci } 27398bf80f4bSopenharmony_ci } 27408bf80f4bSopenharmony_ci} 27418bf80f4bSopenharmony_ci 27428bf80f4bSopenharmony_ci// Set override material to multi-mesh 27438bf80f4bSopenharmony_ciBASE_NS::vector<CORE_NS::Entity> SceneHolder::SetOverrideMaterialMultimeshArray( 27448bf80f4bSopenharmony_ci CORE_NS::Entity target, CORE_NS::Entity material) 27458bf80f4bSopenharmony_ci{ 27468bf80f4bSopenharmony_ci BASE_NS::vector<CORE_NS::Entity> ret; 27478bf80f4bSopenharmony_ci if (ecs_) { 27488bf80f4bSopenharmony_ci // if we contain render mesh handle, use it to set material 27498bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(target)) { 27508bf80f4bSopenharmony_ci auto mesh = data->mesh; 27518bf80f4bSopenharmony_ci SetAll(mesh, material, ret, meshComponentManager_); 27528bf80f4bSopenharmony_ci } 27538bf80f4bSopenharmony_ci 27548bf80f4bSopenharmony_ci // if our child contain meshes, update material on those 27558bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 27568bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 27578bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 27588bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 27598bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(entity)) { 27608bf80f4bSopenharmony_ci auto mesh = data->mesh; 27618bf80f4bSopenharmony_ci SetAll(mesh, material, ret, meshComponentManager_); 27628bf80f4bSopenharmony_ci } 27638bf80f4bSopenharmony_ci } 27648bf80f4bSopenharmony_ci } 27658bf80f4bSopenharmony_ci } 27668bf80f4bSopenharmony_ci } 27678bf80f4bSopenharmony_ci return ret; 27688bf80f4bSopenharmony_ci} 27698bf80f4bSopenharmony_ci 27708bf80f4bSopenharmony_ci// reset override material from multi-mesh 27718bf80f4bSopenharmony_civoid SceneHolder::ResetOverrideMaterialMultimeshArray(CORE_NS::Entity target, BASE_NS::vector<CORE_NS::Entity>& in) 27728bf80f4bSopenharmony_ci{ 27738bf80f4bSopenharmony_ci if (ecs_) { 27748bf80f4bSopenharmony_ci BASE_NS::vector<CORE_NS::Entity> ret; 27758bf80f4bSopenharmony_ci 27768bf80f4bSopenharmony_ci // if we contain render mesh handle, use it to set material 27778bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(target)) { 27788bf80f4bSopenharmony_ci auto mesh = data->mesh; 27798bf80f4bSopenharmony_ci ResetAll(mesh, in, meshComponentManager_); 27808bf80f4bSopenharmony_ci } 27818bf80f4bSopenharmony_ci 27828bf80f4bSopenharmony_ci // if our child contain meshes, update material on those 27838bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 27848bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 27858bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 27868bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 27878bf80f4bSopenharmony_ci if (auto data = renderMeshComponentManager_->Read(entity)) { 27888bf80f4bSopenharmony_ci auto mesh = data->mesh; 27898bf80f4bSopenharmony_ci ResetAll(mesh, in, meshComponentManager_); 27908bf80f4bSopenharmony_ci } 27918bf80f4bSopenharmony_ci } 27928bf80f4bSopenharmony_ci } 27938bf80f4bSopenharmony_ci } 27948bf80f4bSopenharmony_ci } 27958bf80f4bSopenharmony_ci in.clear(); 27968bf80f4bSopenharmony_ci} 27978bf80f4bSopenharmony_ci 27988bf80f4bSopenharmony_ci// Set instance count to multi-mesh 27998bf80f4bSopenharmony_civoid SceneHolder::SetInstanceCountMultimeshArray(CORE_NS::Entity target, size_t count) 28008bf80f4bSopenharmony_ci{ 28018bf80f4bSopenharmony_ci if (ecs_) { 28028bf80f4bSopenharmony_ci if (auto parent = nodeSystem_->GetNode(target)) { 28038bf80f4bSopenharmony_ci // this is kind of sub-optimization. If we have instances available, the mesh component is stored only 28048bf80f4bSopenharmony_ci // in instances 28058bf80f4bSopenharmony_ci CORE_NS::Entity firstBorn; 28068bf80f4bSopenharmony_ci auto children = parent->GetChildren(); 28078bf80f4bSopenharmony_ci 28088bf80f4bSopenharmony_ci for (auto& child : children) { 28098bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 28108bf80f4bSopenharmony_ci firstBorn = child->GetEntity(); 28118bf80f4bSopenharmony_ci break; 28128bf80f4bSopenharmony_ci } 28138bf80f4bSopenharmony_ci } 28148bf80f4bSopenharmony_ci 28158bf80f4bSopenharmony_ci CORE3D_NS::MeshComponent meshData; 28168bf80f4bSopenharmony_ci 28178bf80f4bSopenharmony_ci // when the instance count goes back to zero, we need to restore the data on parent 28188bf80f4bSopenharmony_ci if (count == 0) { 28198bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(firstBorn)) { 28208bf80f4bSopenharmony_ci renderMeshComponentManager_->Create(target); 28218bf80f4bSopenharmony_ci if (auto renderMeshData = renderMeshComponentManager_->Write(target)) { 28228bf80f4bSopenharmony_ci if (auto instancingData = renderMeshComponentManager_->Read(firstBorn)) { 28238bf80f4bSopenharmony_ci *renderMeshData = *instancingData; 28248bf80f4bSopenharmony_ci } 28258bf80f4bSopenharmony_ci } 28268bf80f4bSopenharmony_ci } 28278bf80f4bSopenharmony_ci // now, when we move the templated item back to root, it will become visible by default 28288bf80f4bSopenharmony_ci } else { 28298bf80f4bSopenharmony_ci // if we have mesh, set things up using mesh 28308bf80f4bSopenharmony_ci if (auto data = meshComponentManager_->Read(target)) { 28318bf80f4bSopenharmony_ci meshData = *data; 28328bf80f4bSopenharmony_ci } else if (auto instanceData = renderMeshComponentManager_->Read(firstBorn)) { 28338bf80f4bSopenharmony_ci // otherwise we prefer the instanced data 28348bf80f4bSopenharmony_ci if (auto data = meshComponentManager_->Read(instanceData->mesh)) { 28358bf80f4bSopenharmony_ci // use instance data 28368bf80f4bSopenharmony_ci meshData = *data; 28378bf80f4bSopenharmony_ci // and switch target 28388bf80f4bSopenharmony_ci target = firstBorn; 28398bf80f4bSopenharmony_ci } 28408bf80f4bSopenharmony_ci } else if (auto renderMeshData = renderMeshComponentManager_->Read(target)) { 28418bf80f4bSopenharmony_ci // and fallback to existing render mesh data if it exists 28428bf80f4bSopenharmony_ci if (auto data = meshComponentManager_->Read(renderMeshData->mesh)) { 28438bf80f4bSopenharmony_ci meshData = *data; 28448bf80f4bSopenharmony_ci } 28458bf80f4bSopenharmony_ci } 28468bf80f4bSopenharmony_ci } 28478bf80f4bSopenharmony_ci 28488bf80f4bSopenharmony_ci size_t mmcount = 0; 28498bf80f4bSopenharmony_ci for (auto& child : children) { 28508bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 28518bf80f4bSopenharmony_ci if (mmcount == count) { 28528bf80f4bSopenharmony_ci parent->RemoveChild(*child); 28538bf80f4bSopenharmony_ci } else { 28548bf80f4bSopenharmony_ci mmcount++; 28558bf80f4bSopenharmony_ci } 28568bf80f4bSopenharmony_ci } 28578bf80f4bSopenharmony_ci } 28588bf80f4bSopenharmony_ci 28598bf80f4bSopenharmony_ci BASE_NS::vector<CORE_NS::Entity> clones; 28608bf80f4bSopenharmony_ci while (mmcount < count) { 28618bf80f4bSopenharmony_ci clones.push_back(ecs_->CloneEntity(target)); 28628bf80f4bSopenharmony_ci mmcount++; 28638bf80f4bSopenharmony_ci } 28648bf80f4bSopenharmony_ci 28658bf80f4bSopenharmony_ci for (auto clone : clones) { 28668bf80f4bSopenharmony_ci // set up node system 28678bf80f4bSopenharmony_ci auto node = nodeSystem_->GetNode(clone); 28688bf80f4bSopenharmony_ci node->SetParent(*parent); 28698bf80f4bSopenharmony_ci node->SetEnabled(true); 28708bf80f4bSopenharmony_ci nameComponentManager_->Create(clone); 28718bf80f4bSopenharmony_ci 28728bf80f4bSopenharmony_ci // set up name so we can identify cloned instances afterwards 28738bf80f4bSopenharmony_ci if (auto nameHandle = nameComponentManager_->Write(clone)) { 28748bf80f4bSopenharmony_ci BASE_NS::string postFixed(MULTI_MESH_CHILD_PREFIX.data(), MULTI_MESH_CHILD_PREFIX.size()); 28758bf80f4bSopenharmony_ci postFixed.append(BASE_NS::to_string(mmcount)); 28768bf80f4bSopenharmony_ci nameHandle->name = postFixed; 28778bf80f4bSopenharmony_ci } 28788bf80f4bSopenharmony_ci 28798bf80f4bSopenharmony_ci // and finally mesh specifics 28808bf80f4bSopenharmony_ci if (auto rmcHandle = renderMeshComponentManager_->Write(clone)) { 28818bf80f4bSopenharmony_ci // during the first clone, switch from template to first instance 28828bf80f4bSopenharmony_ci if (mmcount == 0) { 28838bf80f4bSopenharmony_ci renderMeshComponentManager_->Destroy(target); 28848bf80f4bSopenharmony_ci target = clone; 28858bf80f4bSopenharmony_ci } 28868bf80f4bSopenharmony_ci // Set batch 28878bf80f4bSopenharmony_ci rmcHandle->renderMeshBatch = target; 28888bf80f4bSopenharmony_ci // create new entity for mesh 28898bf80f4bSopenharmony_ci const CORE_NS::Entity entity = ecs_->GetEntityManager().Create(); 28908bf80f4bSopenharmony_ci meshComponentManager_->Create(entity); 28918bf80f4bSopenharmony_ci // copy the data of the original 28928bf80f4bSopenharmony_ci *meshComponentManager_->Write(entity) = meshData; 28938bf80f4bSopenharmony_ci // and set the mesh to a new instance 28948bf80f4bSopenharmony_ci rmcHandle->mesh = entity; 28958bf80f4bSopenharmony_ci } 28968bf80f4bSopenharmony_ci mmcount++; 28978bf80f4bSopenharmony_ci } 28988bf80f4bSopenharmony_ci // Set up a batch 28998bf80f4bSopenharmony_ci auto renderMeshBatchComponentManager = 29008bf80f4bSopenharmony_ci CORE_NS::GetManager<CORE3D_NS::IRenderMeshBatchComponentManager>(*ecs_); 29018bf80f4bSopenharmony_ci if (!renderMeshBatchComponentManager->HasComponent(firstBorn)) { 29028bf80f4bSopenharmony_ci renderMeshBatchComponentManager->Create(firstBorn); 29038bf80f4bSopenharmony_ci } 29048bf80f4bSopenharmony_ci if (auto batchHandle = renderMeshBatchComponentManager->Write(firstBorn)) { 29058bf80f4bSopenharmony_ci batchHandle->batchType = CORE3D_NS::RenderMeshBatchComponent::BatchType::GPU_INSTANCING; 29068bf80f4bSopenharmony_ci } 29078bf80f4bSopenharmony_ci } 29088bf80f4bSopenharmony_ci } 29098bf80f4bSopenharmony_ci} 29108bf80f4bSopenharmony_ci 29118bf80f4bSopenharmony_ci// Set visible count to multi-mesh 29128bf80f4bSopenharmony_civoid SceneHolder::SetVisibleCountMultimeshArray(CORE_NS::Entity target, size_t count) 29138bf80f4bSopenharmony_ci{ 29148bf80f4bSopenharmony_ci if (ecs_) { 29158bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 29168bf80f4bSopenharmony_ci size_t ix = 0; 29178bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 29188bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 29198bf80f4bSopenharmony_ci child->SetEnabled(ix < count); 29208bf80f4bSopenharmony_ci ix++; 29218bf80f4bSopenharmony_ci } 29228bf80f4bSopenharmony_ci } 29238bf80f4bSopenharmony_ci } 29248bf80f4bSopenharmony_ci } 29258bf80f4bSopenharmony_ci} 29268bf80f4bSopenharmony_ci 29278bf80f4bSopenharmony_ci// Set custom data to multi-mesh index 29288bf80f4bSopenharmony_civoid SceneHolder::SetCustomData(CORE_NS::Entity target, size_t index, const BASE_NS::Math::Vec4& data) 29298bf80f4bSopenharmony_ci{ 29308bf80f4bSopenharmony_ci if (ecs_) { 29318bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 29328bf80f4bSopenharmony_ci size_t ix = 0; 29338bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 29348bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 29358bf80f4bSopenharmony_ci if (ix == index) { 29368bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 29378bf80f4bSopenharmony_ci if (auto handle = renderMeshComponentManager_->Write(entity)) { 29388bf80f4bSopenharmony_ci *static_cast<float*>(static_cast<void*>(&handle->customData[0].x)) = data.x; 29398bf80f4bSopenharmony_ci *static_cast<float*>(static_cast<void*>(&handle->customData[0].y)) = data.y; 29408bf80f4bSopenharmony_ci *static_cast<float*>(static_cast<void*>(&handle->customData[0].z)) = data.z; 29418bf80f4bSopenharmony_ci *static_cast<float*>(static_cast<void*>(&handle->customData[0].w)) = data.w; 29428bf80f4bSopenharmony_ci } 29438bf80f4bSopenharmony_ci return; 29448bf80f4bSopenharmony_ci } 29458bf80f4bSopenharmony_ci ix++; 29468bf80f4bSopenharmony_ci } 29478bf80f4bSopenharmony_ci } 29488bf80f4bSopenharmony_ci } 29498bf80f4bSopenharmony_ci } 29508bf80f4bSopenharmony_ci} 29518bf80f4bSopenharmony_ci 29528bf80f4bSopenharmony_ci// Set transformation to multi-mesh index 29538bf80f4bSopenharmony_civoid SceneHolder::SetTransformation(CORE_NS::Entity target, size_t index, const BASE_NS::Math::Mat4X4& transform) 29548bf80f4bSopenharmony_ci{ 29558bf80f4bSopenharmony_ci if (ecs_) { 29568bf80f4bSopenharmony_ci if (const CORE3D_NS::ISceneNode* parent = nodeSystem_->GetNode(target)) { 29578bf80f4bSopenharmony_ci size_t ix = 0; 29588bf80f4bSopenharmony_ci for (auto& child : parent->GetChildren()) { 29598bf80f4bSopenharmony_ci if (IsMultiMeshChild(child)) { 29608bf80f4bSopenharmony_ci if (ix == index) { 29618bf80f4bSopenharmony_ci auto entity = child->GetEntity(); 29628bf80f4bSopenharmony_ci if (auto handle = transformComponentManager_->Write(entity)) { 29638bf80f4bSopenharmony_ci BASE_NS::Math::Quat rotation; 29648bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 scale; 29658bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 position; 29668bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 skew; 29678bf80f4bSopenharmony_ci BASE_NS::Math::Vec4 persp; 29688bf80f4bSopenharmony_ci if (BASE_NS::Math::Decompose(transform, scale, rotation, position, skew, persp)) { 29698bf80f4bSopenharmony_ci handle->scale = scale; 29708bf80f4bSopenharmony_ci handle->rotation = rotation; 29718bf80f4bSopenharmony_ci handle->position = position; 29728bf80f4bSopenharmony_ci } 29738bf80f4bSopenharmony_ci return; 29748bf80f4bSopenharmony_ci } 29758bf80f4bSopenharmony_ci } 29768bf80f4bSopenharmony_ci ix++; 29778bf80f4bSopenharmony_ci } 29788bf80f4bSopenharmony_ci } 29798bf80f4bSopenharmony_ci } 29808bf80f4bSopenharmony_ci } 29818bf80f4bSopenharmony_ci} 29828bf80f4bSopenharmony_ci 29838bf80f4bSopenharmony_cibool SceneHolder::GetWorldMatrixComponentAABB( 29848bf80f4bSopenharmony_ci SCENE_NS::IPickingResult::Ptr ret, CORE_NS::Entity entity, bool isRecursive) 29858bf80f4bSopenharmony_ci{ 29868bf80f4bSopenharmony_ci if (picking_ && ecs_) { 29878bf80f4bSopenharmony_ci auto result = picking_->GetWorldMatrixComponentAABB(entity, isRecursive, *ecs_); 29888bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 29898bf80f4bSopenharmony_ci writable->Add(result.minAABB); 29908bf80f4bSopenharmony_ci writable->Add(result.maxAABB); 29918bf80f4bSopenharmony_ci return true; 29928bf80f4bSopenharmony_ci } 29938bf80f4bSopenharmony_ci } 29948bf80f4bSopenharmony_ci return false; 29958bf80f4bSopenharmony_ci} 29968bf80f4bSopenharmony_ci 29978bf80f4bSopenharmony_cibool SceneHolder::GetTransformComponentAABB(SCENE_NS::IPickingResult::Ptr ret, CORE_NS::Entity entity, bool isRecursive) 29988bf80f4bSopenharmony_ci{ 29998bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30008bf80f4bSopenharmony_ci auto result = picking_->GetTransformComponentAABB(entity, isRecursive, *ecs_); 30018bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 30028bf80f4bSopenharmony_ci writable->Add(result.minAABB); 30038bf80f4bSopenharmony_ci writable->Add(result.maxAABB); 30048bf80f4bSopenharmony_ci return true; 30058bf80f4bSopenharmony_ci } 30068bf80f4bSopenharmony_ci } 30078bf80f4bSopenharmony_ci return false; 30088bf80f4bSopenharmony_ci} 30098bf80f4bSopenharmony_ci 30108bf80f4bSopenharmony_cibool SceneHolder::GetWorldAABB(SCENE_NS::IPickingResult::Ptr ret, const BASE_NS::Math::Mat4X4& world, 30118bf80f4bSopenharmony_ci const BASE_NS::Math::Vec3& aabbMin, const BASE_NS::Math::Vec3& aabbMax) 30128bf80f4bSopenharmony_ci{ 30138bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30148bf80f4bSopenharmony_ci auto result = picking_->GetWorldAABB(world, aabbMin, aabbMax); 30158bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 30168bf80f4bSopenharmony_ci writable->Add(result.minAABB); 30178bf80f4bSopenharmony_ci writable->Add(result.maxAABB); 30188bf80f4bSopenharmony_ci return true; 30198bf80f4bSopenharmony_ci } 30208bf80f4bSopenharmony_ci } 30218bf80f4bSopenharmony_ci return false; 30228bf80f4bSopenharmony_ci} 30238bf80f4bSopenharmony_ci 30248bf80f4bSopenharmony_cibool ConvertToToolkit(const BASE_NS::vector<CORE3D_NS::RayCastResult>& result, SCENE_NS::IRayCastResult::Ptr ret) 30258bf80f4bSopenharmony_ci{ 30268bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<SCENE_NS::NodeDistance>>(ret)) { 30278bf80f4bSopenharmony_ci for (auto& value : result) { 30288bf80f4bSopenharmony_ci BASE_NS::string path; 30298bf80f4bSopenharmony_ci if (ResolveNodeFullPath(value.node, path)) { 30308bf80f4bSopenharmony_ci writable->Add({ {}, value.distance }); 30318bf80f4bSopenharmony_ci writable->MetaData().push_back(path); 30328bf80f4bSopenharmony_ci } 30338bf80f4bSopenharmony_ci } 30348bf80f4bSopenharmony_ci return true; 30358bf80f4bSopenharmony_ci } 30368bf80f4bSopenharmony_ci return false; 30378bf80f4bSopenharmony_ci} 30388bf80f4bSopenharmony_ci 30398bf80f4bSopenharmony_cibool SceneHolder::RayCast( 30408bf80f4bSopenharmony_ci SCENE_NS::IRayCastResult::Ptr ret, const BASE_NS::Math::Vec3& start, const BASE_NS::Math::Vec3& direction) 30418bf80f4bSopenharmony_ci{ 30428bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30438bf80f4bSopenharmony_ci auto result = picking_->RayCast(*ecs_, start, direction); 30448bf80f4bSopenharmony_ci return ConvertToToolkit(result, ret); 30458bf80f4bSopenharmony_ci } 30468bf80f4bSopenharmony_ci return false; 30478bf80f4bSopenharmony_ci} 30488bf80f4bSopenharmony_ci 30498bf80f4bSopenharmony_cibool SceneHolder::RayCast(SCENE_NS::IRayCastResult::Ptr ret, const BASE_NS::Math::Vec3& start, 30508bf80f4bSopenharmony_ci const BASE_NS::Math::Vec3& direction, uint64_t layerMask) 30518bf80f4bSopenharmony_ci{ 30528bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30538bf80f4bSopenharmony_ci auto result = picking_->RayCast(*ecs_, start, direction, layerMask); 30548bf80f4bSopenharmony_ci return ConvertToToolkit(result, ret); 30558bf80f4bSopenharmony_ci } 30568bf80f4bSopenharmony_ci return false; 30578bf80f4bSopenharmony_ci} 30588bf80f4bSopenharmony_ci 30598bf80f4bSopenharmony_cibool SceneHolder::ScreenToWorld( 30608bf80f4bSopenharmony_ci SCENE_NS::IPickingResult::Ptr ret, CORE_NS::Entity camera, BASE_NS::Math::Vec3 screenCoordinate) 30618bf80f4bSopenharmony_ci{ 30628bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30638bf80f4bSopenharmony_ci auto result = picking_->ScreenToWorld(*ecs_, camera, screenCoordinate); 30648bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 30658bf80f4bSopenharmony_ci writable->Add(result); 30668bf80f4bSopenharmony_ci return true; 30678bf80f4bSopenharmony_ci } 30688bf80f4bSopenharmony_ci } 30698bf80f4bSopenharmony_ci return false; 30708bf80f4bSopenharmony_ci} 30718bf80f4bSopenharmony_ci 30728bf80f4bSopenharmony_cibool SceneHolder::WorldToScreen( 30738bf80f4bSopenharmony_ci SCENE_NS::IPickingResult::Ptr ret, CORE_NS::Entity camera, BASE_NS::Math::Vec3 worldCoordinate) 30748bf80f4bSopenharmony_ci 30758bf80f4bSopenharmony_ci{ 30768bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30778bf80f4bSopenharmony_ci auto result = picking_->WorldToScreen(*ecs_, camera, worldCoordinate); 30788bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 30798bf80f4bSopenharmony_ci writable->Add(result); 30808bf80f4bSopenharmony_ci return true; 30818bf80f4bSopenharmony_ci } 30828bf80f4bSopenharmony_ci } 30838bf80f4bSopenharmony_ci return false; 30848bf80f4bSopenharmony_ci} 30858bf80f4bSopenharmony_ci 30868bf80f4bSopenharmony_cibool SceneHolder::RayCastFromCamera( 30878bf80f4bSopenharmony_ci SCENE_NS::IRayCastResult::Ptr ret, CORE_NS::Entity camera, const BASE_NS::Math::Vec2& screenPos) 30888bf80f4bSopenharmony_ci{ 30898bf80f4bSopenharmony_ci if (picking_ && ecs_) { 30908bf80f4bSopenharmony_ci auto result = picking_->RayCastFromCamera(*ecs_, camera, screenPos); 30918bf80f4bSopenharmony_ci return ConvertToToolkit(result, ret); 30928bf80f4bSopenharmony_ci } 30938bf80f4bSopenharmony_ci return false; 30948bf80f4bSopenharmony_ci} 30958bf80f4bSopenharmony_ci 30968bf80f4bSopenharmony_cibool SceneHolder::RayCastFromCamera( 30978bf80f4bSopenharmony_ci SCENE_NS::IRayCastResult::Ptr ret, CORE_NS::Entity camera, const BASE_NS::Math::Vec2& screenPos, uint64_t layerMask) 30988bf80f4bSopenharmony_ci{ 30998bf80f4bSopenharmony_ci if (picking_ && ecs_) { 31008bf80f4bSopenharmony_ci auto result = picking_->RayCastFromCamera(*ecs_, camera, screenPos, layerMask); 31018bf80f4bSopenharmony_ci return ConvertToToolkit(result, ret); 31028bf80f4bSopenharmony_ci } 31038bf80f4bSopenharmony_ci return false; 31048bf80f4bSopenharmony_ci} 31058bf80f4bSopenharmony_ci 31068bf80f4bSopenharmony_cibool SceneHolder::RayFromCamera( 31078bf80f4bSopenharmony_ci SCENE_NS::IPickingResult::Ptr ret, CORE_NS::Entity camera, BASE_NS::Math::Vec2 screenCoordinate) 31088bf80f4bSopenharmony_ci{ 31098bf80f4bSopenharmony_ci if (auto cameraComponent = cameraComponentManager_->Read(camera)) { 31108bf80f4bSopenharmony_ci if (auto worldMatrixManager = GetManager<CORE3D_NS::IWorldMatrixComponentManager>(*ecs_)) { 31118bf80f4bSopenharmony_ci if (auto cameraWorldMatrixComponent = worldMatrixManager->Read(camera)) { 31128bf80f4bSopenharmony_ci if (cameraComponent->projection == CORE3D_NS::CameraComponent::Projection::ORTHOGRAPHIC) { 31138bf80f4bSopenharmony_ci const auto worldPos = picking_->ScreenToWorld( 31148bf80f4bSopenharmony_ci *ecs_, camera, BASE_NS::Math::Vec3(screenCoordinate.x, screenCoordinate.y, 0.0f)); 31158bf80f4bSopenharmony_ci const auto direction = 31168bf80f4bSopenharmony_ci cameraWorldMatrixComponent->matrix * BASE_NS::Math::Vec4(0.0f, 0.0f, -1.0f, 0.0f); 31178bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 31188bf80f4bSopenharmony_ci writable->Add(worldPos); 31198bf80f4bSopenharmony_ci writable->Add(direction); 31208bf80f4bSopenharmony_ci return true; 31218bf80f4bSopenharmony_ci } 31228bf80f4bSopenharmony_ci } else { 31238bf80f4bSopenharmony_ci // Ray origin is the camera world position. 31248bf80f4bSopenharmony_ci const auto rayOrigin = BASE_NS::Math::Vec3(cameraWorldMatrixComponent->matrix.w); 31258bf80f4bSopenharmony_ci const auto targetPos = picking_->ScreenToWorld( 31268bf80f4bSopenharmony_ci *ecs_, camera, BASE_NS::Math::Vec3(screenCoordinate.x, screenCoordinate.y, 1.0f)); 31278bf80f4bSopenharmony_ci const auto direction = BASE_NS::Math::Normalize(targetPos - rayOrigin); 31288bf80f4bSopenharmony_ci if (auto writable = interface_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>(ret)) { 31298bf80f4bSopenharmony_ci writable->Add(rayOrigin); 31308bf80f4bSopenharmony_ci writable->Add(direction); 31318bf80f4bSopenharmony_ci return true; 31328bf80f4bSopenharmony_ci } 31338bf80f4bSopenharmony_ci } 31348bf80f4bSopenharmony_ci } 31358bf80f4bSopenharmony_ci } 31368bf80f4bSopenharmony_ci } 31378bf80f4bSopenharmony_ci return false; 31388bf80f4bSopenharmony_ci} 3139