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#include "node_impl.h" 168bf80f4bSopenharmony_ci 178bf80f4bSopenharmony_ci#include "task_utils.h" 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask; 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <scene_plugin/api/material_uid.h> 228bf80f4bSopenharmony_ci#include <scene_plugin/api/mesh_uid.h> 238bf80f4bSopenharmony_ci#include <scene_plugin/api/scene_uid.h> 248bf80f4bSopenharmony_ci 258bf80f4bSopenharmony_ci#include "intf_multi_mesh_initialization.h" 268bf80f4bSopenharmony_ci 278bf80f4bSopenharmony_cibool HasChangedProperties(META_NS::IMetadata& meta) 288bf80f4bSopenharmony_ci{ 298bf80f4bSopenharmony_ci for (auto& property : meta.GetAllProperties()) { 308bf80f4bSopenharmony_ci bool isInternal = META_NS::IsFlagSet(property, META_NS::ObjectFlagBits::INTERNAL); 318bf80f4bSopenharmony_ci if (isInternal) { 328bf80f4bSopenharmony_ci continue; 338bf80f4bSopenharmony_ci } 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ci bool isSerializable = META_NS::IsFlagSet(property, META_NS::ObjectFlagBits::SERIALIZE); 368bf80f4bSopenharmony_ci if (isSerializable && property->IsValueSet()) { 378bf80f4bSopenharmony_ci return true; 388bf80f4bSopenharmony_ci } 398bf80f4bSopenharmony_ci } 408bf80f4bSopenharmony_ci 418bf80f4bSopenharmony_ci return false; 428bf80f4bSopenharmony_ci} 438bf80f4bSopenharmony_ci 448bf80f4bSopenharmony_cinamespace { 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_cisize_t GetChildIndex(SCENE_NS::INode& parent, SCENE_NS::INode& child) 478bf80f4bSopenharmony_ci{ 488bf80f4bSopenharmony_ci auto object = interface_cast<META_NS::IObject>(&child); 498bf80f4bSopenharmony_ci 508bf80f4bSopenharmony_ci auto container = interface_cast<META_NS::IContainer>(&parent); 518bf80f4bSopenharmony_ci if (container) { 528bf80f4bSopenharmony_ci for (auto i = 0; i < container->GetSize(); ++i) { 538bf80f4bSopenharmony_ci if (container->GetAt(i).get() == object) { 548bf80f4bSopenharmony_ci return i; 558bf80f4bSopenharmony_ci } 568bf80f4bSopenharmony_ci } 578bf80f4bSopenharmony_ci } 588bf80f4bSopenharmony_ci 598bf80f4bSopenharmony_ci return SIZE_MAX; 608bf80f4bSopenharmony_ci} 618bf80f4bSopenharmony_ci 628bf80f4bSopenharmony_ci} // namespace 638bf80f4bSopenharmony_ci 648bf80f4bSopenharmony_ci#include "bind_templates.inl" 658bf80f4bSopenharmony_ci 668bf80f4bSopenharmony_ci// implements CORE_NS::IInterface 678bf80f4bSopenharmony_ciconst CORE_NS::IInterface* NodeImpl::GetInterface(const BASE_NS::Uid& uid) const 688bf80f4bSopenharmony_ci{ 698bf80f4bSopenharmony_ci if (META_NS::TypeId(uid) == SCENE_NS::InterfaceId::IEnvironment.Id()) { 708bf80f4bSopenharmony_ci return environment_.get(); 718bf80f4bSopenharmony_ci } else { 728bf80f4bSopenharmony_ci return Fwd::GetInterface(uid); 738bf80f4bSopenharmony_ci } 748bf80f4bSopenharmony_ci} 758bf80f4bSopenharmony_ci 768bf80f4bSopenharmony_ciCORE_NS::IInterface* NodeImpl::GetInterface(const BASE_NS::Uid& uid) 778bf80f4bSopenharmony_ci{ 788bf80f4bSopenharmony_ci if (META_NS::TypeId(uid) == SCENE_NS::InterfaceId::IEnvironment.Id()) { 798bf80f4bSopenharmony_ci return environment_.get(); 808bf80f4bSopenharmony_ci } else { 818bf80f4bSopenharmony_ci return Fwd::GetInterface(uid); 828bf80f4bSopenharmony_ci } 838bf80f4bSopenharmony_ci} 848bf80f4bSopenharmony_ci 858bf80f4bSopenharmony_ciSCENE_NS::NodeState NodeImpl::GetAttachedState() const 868bf80f4bSopenharmony_ci{ 878bf80f4bSopenharmony_ci return attachedState_; 888bf80f4bSopenharmony_ci} 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_cibool NodeImpl::IsConnected() 918bf80f4bSopenharmony_ci{ 928bf80f4bSopenharmony_ci if (Status()->GetValue() == SCENE_NS::INode::NODE_STATUS_CONNECTED || 938bf80f4bSopenharmony_ci Status()->GetValue() == SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED) 948bf80f4bSopenharmony_ci return true; 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ci return false; 978bf80f4bSopenharmony_ci} 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_civoid NodeImpl::DisableInputHandling() 1008bf80f4bSopenharmony_ci{ 1018bf80f4bSopenharmony_ci /*auto inputMode = META_ACCESS_PROPERTY(InputMode); 1028bf80f4bSopenharmony_ci if (auto i = interface_cast<META_NS::IMetaPropertyInternal>(inputMode)) { 1038bf80f4bSopenharmony_ci auto flags = inputMode->Flags(); 1048bf80f4bSopenharmony_ci flags &= ~META_NS::IMetaProperty::PropertyFlagsValue(META_NS::IMetaProperty::PropertyFlagBits::SERIALIZABLE); 1058bf80f4bSopenharmony_ci flags |= META_NS::IMetaProperty::PropertyFlagsValue(META_NS::IMetaProperty::PropertyFlagBits::INTERNAL); 1068bf80f4bSopenharmony_ci i->SetFlags(flags); 1078bf80f4bSopenharmony_ci }*/ 1088bf80f4bSopenharmony_ci} 1098bf80f4bSopenharmony_ci 1108bf80f4bSopenharmony_cibool NodeImpl::Connect(const INode::Ptr& parent) 1118bf80f4bSopenharmony_ci{ 1128bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Node::Connect called for: '%s' (%s)", GetName().c_str(), Path()->Get().c_str()); 1138bf80f4bSopenharmony_ci if (parent) { 1148bf80f4bSopenharmony_ci auto sceneObject = interface_pointer_cast<IObject>(parent->GetScene()); 1158bf80f4bSopenharmony_ci if (sceneObject) { 1168bf80f4bSopenharmony_ci if (auto sceneInterface = interface_pointer_cast<SCENE_NS::IEcsScene>(sceneObject)) { 1178bf80f4bSopenharmony_ci CORE_ASSERT(sceneInterface); 1188bf80f4bSopenharmony_ci 1198bf80f4bSopenharmony_ci BASE_NS::string path = "/"; 1208bf80f4bSopenharmony_ci if (parent) { 1218bf80f4bSopenharmony_ci path = parent->Path()->GetValue() + parent->Name()->GetValue() + "/"; 1228bf80f4bSopenharmony_ci } 1238bf80f4bSopenharmony_ci 1248bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Path)->SetValue(path); 1258bf80f4bSopenharmony_ci 1268bf80f4bSopenharmony_ci if (!ecsObject_) { 1278bf80f4bSopenharmony_ci EnsureEcsBinding(sceneInterface); 1288bf80f4bSopenharmony_ci } 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_ci return true; 1318bf80f4bSopenharmony_ci } 1328bf80f4bSopenharmony_ci } 1338bf80f4bSopenharmony_ci } 1348bf80f4bSopenharmony_ci 1358bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Node::Connect - NO PARENT - '%s'", GetName().c_str()); 1368bf80f4bSopenharmony_ci return false; 1378bf80f4bSopenharmony_ci} 1388bf80f4bSopenharmony_ci 1398bf80f4bSopenharmony_civoid NodeImpl::Activate() 1408bf80f4bSopenharmony_ci{ 1418bf80f4bSopenharmony_ci auto parent = interface_pointer_cast<INode>(GetParent()); 1428bf80f4bSopenharmony_ci 1438bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 1448bf80f4bSopenharmony_ci size_t index = SIZE_MAX; 1458bf80f4bSopenharmony_ci BASE_NS::string path = "/"; 1468bf80f4bSopenharmony_ci if (parent) { 1478bf80f4bSopenharmony_ci path = parent->Path()->GetValue() + parent->Name()->GetValue() + "/"; 1488bf80f4bSopenharmony_ci index = GetChildIndex(*parent, *this); 1498bf80f4bSopenharmony_ci } 1508bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask( 1518bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::ITaskQueueTask>( 1528bf80f4bSopenharmony_ci [path, index, e = ecsObject_->GetEntity(), weak_sh = BASE_NS::weak_ptr(sceneHolder)] { 1538bf80f4bSopenharmony_ci auto sh = weak_sh.lock(); 1548bf80f4bSopenharmony_ci if (sh) { 1558bf80f4bSopenharmony_ci sh->SetEntityActive(e, true); 1568bf80f4bSopenharmony_ci sh->ReparentEntity(e, path, index); 1578bf80f4bSopenharmony_ci } 1588bf80f4bSopenharmony_ci return false; 1598bf80f4bSopenharmony_ci }), 1608bf80f4bSopenharmony_ci false); 1618bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Path)->SetValue(path); 1628bf80f4bSopenharmony_ci UpdateChildrenPath(); 1638bf80f4bSopenharmony_ci RecursivelyEnableCache(true); 1648bf80f4bSopenharmony_ci } 1658bf80f4bSopenharmony_ci} 1668bf80f4bSopenharmony_ci 1678bf80f4bSopenharmony_civoid NodeImpl::Deactivate() 1688bf80f4bSopenharmony_ci{ 1698bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 1708bf80f4bSopenharmony_ci // TODO: Check if we can set parent to "invalid entity". 1718bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>( 1728bf80f4bSopenharmony_ci [e = ecsObject_->GetEntity(), weak_sh = BASE_NS::weak_ptr(sceneHolder)] { 1738bf80f4bSopenharmony_ci auto sh = weak_sh.lock(); 1748bf80f4bSopenharmony_ci if (sh) { 1758bf80f4bSopenharmony_ci sh->SetEntityActive(e, false); 1768bf80f4bSopenharmony_ci } 1778bf80f4bSopenharmony_ci return false; 1788bf80f4bSopenharmony_ci }), 1798bf80f4bSopenharmony_ci false); 1808bf80f4bSopenharmony_ci 1818bf80f4bSopenharmony_ci RecursivelyEnableCache(false); 1828bf80f4bSopenharmony_ci } 1838bf80f4bSopenharmony_ci} 1848bf80f4bSopenharmony_ci 1858bf80f4bSopenharmony_civoid NodeImpl::AttachToHierarchy() 1868bf80f4bSopenharmony_ci{ 1878bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG( 1888bf80f4bSopenharmony_ci "Node::AttachToHierarchy called for: '%s' (%s)", GetName().c_str(), Path()->GetValue().c_str()); 1898bf80f4bSopenharmony_ci 1908bf80f4bSopenharmony_ci // If we have an entity, that we simply need to activate. 1918bf80f4bSopenharmony_ci // If we are unbound, we need to try to bind this node to scene graph. 1928bf80f4bSopenharmony_ci if (IsConnected()) { 1938bf80f4bSopenharmony_ci Activate(); 1948bf80f4bSopenharmony_ci } else { 1958bf80f4bSopenharmony_ci Connect(interface_pointer_cast<INode>(GetParent())); 1968bf80f4bSopenharmony_ci } 1978bf80f4bSopenharmony_ci 1988bf80f4bSopenharmony_ci attachedState_ = SCENE_NS::NodeState::ATTACHED; 1998bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Node::AttachToHierarchy path is: '%s'", Path()->GetValue().c_str()); 2008bf80f4bSopenharmony_ci} 2018bf80f4bSopenharmony_ci 2028bf80f4bSopenharmony_civoid NodeImpl::DetachFromHierarchy() 2038bf80f4bSopenharmony_ci{ 2048bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG( 2058bf80f4bSopenharmony_ci "Node::DetachFromHierarchy called for: '%s' (%s)", GetName().c_str(), Path()->GetValue().c_str()); 2068bf80f4bSopenharmony_ci 2078bf80f4bSopenharmony_ci // We are being detachad from the scene graph. 2088bf80f4bSopenharmony_ci if (IsConnected()) { 2098bf80f4bSopenharmony_ci // We simply need to deactivate. 2108bf80f4bSopenharmony_ci Deactivate(); 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci 2138bf80f4bSopenharmony_ci // TODO: Is there something we need to do here? 2148bf80f4bSopenharmony_ci attachedState_ = SCENE_NS::NodeState::DETACHED; 2158bf80f4bSopenharmony_ci 2168bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Node::DetachFromHierarchy path is: '%s'", Path()->GetValue().c_str()); 2178bf80f4bSopenharmony_ci} 2188bf80f4bSopenharmony_ci 2198bf80f4bSopenharmony_civoid NodeImpl::SubscribeToNameChanges() 2208bf80f4bSopenharmony_ci{ 2218bf80f4bSopenharmony_ci if (!nameChangedToken_) { 2228bf80f4bSopenharmony_ci nameChangedToken_ = Name()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this] { 2238bf80f4bSopenharmony_ci if (IsResourceClassType() || ownsEntity_) { 2248bf80f4bSopenharmony_ci RenameEntity(META_ACCESS_PROPERTY(Name)->GetValue()); 2258bf80f4bSopenharmony_ci } 2268bf80f4bSopenharmony_ci })); 2278bf80f4bSopenharmony_ci } 2288bf80f4bSopenharmony_ci} 2298bf80f4bSopenharmony_ci 2308bf80f4bSopenharmony_civoid NodeImpl::UnsubscribeFromNameChanges() 2318bf80f4bSopenharmony_ci{ 2328bf80f4bSopenharmony_ci if (nameChangedToken_) { 2338bf80f4bSopenharmony_ci Name()->OnChanged()->RemoveHandler(nameChangedToken_); 2348bf80f4bSopenharmony_ci nameChangedToken_ = { 0 }; 2358bf80f4bSopenharmony_ci } 2368bf80f4bSopenharmony_ci} 2378bf80f4bSopenharmony_ci 2388bf80f4bSopenharmony_cibool NodeImpl::IsResourceClassType() 2398bf80f4bSopenharmony_ci{ 2408bf80f4bSopenharmony_ci auto classUid = GetClassId(); 2418bf80f4bSopenharmony_ci bool isResourceClassType = (classUid == SCENE_NS::ClassId::Material) || // Material 2428bf80f4bSopenharmony_ci (classUid == SCENE_NS::ClassId::Mesh) || // Mesh 2438bf80f4bSopenharmony_ci (classUid == SCENE_NS::ClassId::Animation); // Animation 2448bf80f4bSopenharmony_ci 2458bf80f4bSopenharmony_ci return isResourceClassType; 2468bf80f4bSopenharmony_ci} 2478bf80f4bSopenharmony_ci/* 2488bf80f4bSopenharmony_cibool NodeImpl::Import( 2498bf80f4bSopenharmony_ci META_NS::Serialization::IImportContext& context, const META_NS::Serialization::ClassPrimitive& value) 2508bf80f4bSopenharmony_ci{ 2518bf80f4bSopenharmony_ci if (!Fwd::Import(context, value)) { 2528bf80f4bSopenharmony_ci return false; 2538bf80f4bSopenharmony_ci } 2548bf80f4bSopenharmony_ci 2558bf80f4bSopenharmony_ci // Backwards compatibility. 2568bf80f4bSopenharmony_ci auto prop = GetPropertyByName("SceneUid"); 2578bf80f4bSopenharmony_ci if (prop) { 2588bf80f4bSopenharmony_ci RemoveProperty(prop); 2598bf80f4bSopenharmony_ci } 2608bf80f4bSopenharmony_ci 2618bf80f4bSopenharmony_ci prop = GetPropertyByName("Path"); 2628bf80f4bSopenharmony_ci if (auto path = META_NS::property_cast<BASE_NS::string>(prop)) { 2638bf80f4bSopenharmony_ci path->Reset(); 2648bf80f4bSopenharmony_ci } 2658bf80f4bSopenharmony_ci 2668bf80f4bSopenharmony_ci return true; 2678bf80f4bSopenharmony_ci} 2688bf80f4bSopenharmony_ci*/ 2698bf80f4bSopenharmony_cibool NodeImpl::Build(const IMetadata::Ptr& data) 2708bf80f4bSopenharmony_ci{ 2718bf80f4bSopenharmony_ci ClaimOwnershipOfEntity(false); 2728bf80f4bSopenharmony_ci 2738bf80f4bSopenharmony_ci OnMoved()->AddHandler(META_NS::MakeCallback<META_NS::IOnChildMoved>([](const META_NS::ChildMovedInfo& info) { 2748bf80f4bSopenharmony_ci auto parent = interface_cast<IObject>(info.parent.lock())->GetName(); 2758bf80f4bSopenharmony_ci auto object = info.object->GetName(); 2768bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Child '%s' moved in '%s'", object.c_str(), parent.c_str()); 2778bf80f4bSopenharmony_ci })); 2788bf80f4bSopenharmony_ci 2798bf80f4bSopenharmony_ci PropertyNameMask().clear(); 2808bf80f4bSopenharmony_ci PropertyNameMask()[TRANSFORM_COMPONENT_NAME] = { TRANSFORM_POSITION.substr(TRANSFORM_COMPONENT_NAME_LEN), 2818bf80f4bSopenharmony_ci TRANSFORM_SCALE.substr(TRANSFORM_COMPONENT_NAME_LEN), TRANSFORM_ROTATION.substr(TRANSFORM_COMPONENT_NAME_LEN) }; 2828bf80f4bSopenharmony_ci PropertyNameMask()[NODE_COMPONENT_NAME] = { NODE_ENABLED.substr(NODE_COMPONENT_NAME_LEN) }; 2838bf80f4bSopenharmony_ci PropertyNameMask()[LAYER_COMPONENT_NAME] = { LAYER_MASK.substr(LAYER_COMPONENT_NAME_LEN) }; 2848bf80f4bSopenharmony_ci PropertyNameMask()[LMATRIX_COMPONENT_NAME] = { LMATRIX_MATRIX.substr(LMATRIX_COMPONENT_NAME_LEN) }; 2858bf80f4bSopenharmony_ci PropertyNameMask()[RM_COMPONENT_NAME] = { RM_HANDLE.substr(RM_COMPONENT_NAME_LEN) }; 2868bf80f4bSopenharmony_ci PropertyNameMask()[ENVIRONMENT_COMPONENT_NAME] = {}; // read everything if it happens to be present 2878bf80f4bSopenharmony_ci 2888bf80f4bSopenharmony_ci objectRegistry_ = &META_NS::GetObjectRegistry(); 2898bf80f4bSopenharmony_ci return true; 2908bf80f4bSopenharmony_ci} 2918bf80f4bSopenharmony_ci 2928bf80f4bSopenharmony_ciBASE_NS::string NodeImpl::GetName() const 2938bf80f4bSopenharmony_ci{ 2948bf80f4bSopenharmony_ci return META_NS::GetValue(Name()); 2958bf80f4bSopenharmony_ci} 2968bf80f4bSopenharmony_ci 2978bf80f4bSopenharmony_ciCORE_NS::IEcs::Ptr NodeImpl::GetEcs() const 2988bf80f4bSopenharmony_ci{ 2998bf80f4bSopenharmony_ci if (ecsObject_) { 3008bf80f4bSopenharmony_ci return ecsObject_->GetEcs(); 3018bf80f4bSopenharmony_ci } 3028bf80f4bSopenharmony_ci return CORE_NS::IEcs::Ptr {}; 3038bf80f4bSopenharmony_ci} 3048bf80f4bSopenharmony_ci 3058bf80f4bSopenharmony_civoid NodeImpl::SetEntity(CORE_NS::IEcs::Ptr ecs, CORE_NS::Entity entity) 3068bf80f4bSopenharmony_ci{ 3078bf80f4bSopenharmony_ci if (ecsObject_) { 3088bf80f4bSopenharmony_ci return ecsObject_->SetEntity(ecs, entity); 3098bf80f4bSopenharmony_ci } 3108bf80f4bSopenharmony_ci} 3118bf80f4bSopenharmony_ci 3128bf80f4bSopenharmony_ciCORE_NS::Entity NodeImpl::GetEntity() const 3138bf80f4bSopenharmony_ci{ 3148bf80f4bSopenharmony_ci if (ecsObject_) { 3158bf80f4bSopenharmony_ci return ecsObject_->GetEntity(); 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci return CORE_NS::Entity {}; 3188bf80f4bSopenharmony_ci} 3198bf80f4bSopenharmony_ci 3208bf80f4bSopenharmony_civoid NodeImpl::BindObject(CORE_NS::IEcs::Ptr ecsInstance, CORE_NS::Entity entity) 3218bf80f4bSopenharmony_ci{ 3228bf80f4bSopenharmony_ci if (ecsObject_) { 3238bf80f4bSopenharmony_ci ecsObject_->BindObject(ecsInstance, entity); 3248bf80f4bSopenharmony_ci } 3258bf80f4bSopenharmony_ci} 3268bf80f4bSopenharmony_ci 3278bf80f4bSopenharmony_civoid NodeImpl::DefineTargetProperties( 3288bf80f4bSopenharmony_ci BASE_NS::unordered_map<BASE_NS::string_view, BASE_NS::vector<BASE_NS::string_view>> names) 3298bf80f4bSopenharmony_ci{ 3308bf80f4bSopenharmony_ci if (ecsObject_) { 3318bf80f4bSopenharmony_ci ecsObject_->DefineTargetProperties(names); 3328bf80f4bSopenharmony_ci } 3338bf80f4bSopenharmony_ci} 3348bf80f4bSopenharmony_ci 3358bf80f4bSopenharmony_ciBASE_NS::vector<CORE_NS::Entity> NodeImpl::GetAttachments() 3368bf80f4bSopenharmony_ci{ 3378bf80f4bSopenharmony_ci if (ecsObject_) { 3388bf80f4bSopenharmony_ci return ecsObject_->GetAttachments(); 3398bf80f4bSopenharmony_ci } 3408bf80f4bSopenharmony_ci return BASE_NS::vector<CORE_NS::Entity> {}; 3418bf80f4bSopenharmony_ci} 3428bf80f4bSopenharmony_ci 3438bf80f4bSopenharmony_civoid NodeImpl::AddAttachment(CORE_NS::Entity entity) 3448bf80f4bSopenharmony_ci{ 3458bf80f4bSopenharmony_ci if (ecsObject_) { 3468bf80f4bSopenharmony_ci ecsObject_->AddAttachment(entity); 3478bf80f4bSopenharmony_ci } 3488bf80f4bSopenharmony_ci} 3498bf80f4bSopenharmony_ci 3508bf80f4bSopenharmony_civoid NodeImpl::RemoveAttachment(CORE_NS::Entity entity) 3518bf80f4bSopenharmony_ci{ 3528bf80f4bSopenharmony_ci if (ecsObject_) { 3538bf80f4bSopenharmony_ci ecsObject_->RemoveAttachment(entity); 3548bf80f4bSopenharmony_ci } 3558bf80f4bSopenharmony_ci} 3568bf80f4bSopenharmony_ci 3578bf80f4bSopenharmony_civoid NodeImpl::CloneEcs(const BASE_NS::string& name, META_NS::IObject::Ptr target) const 3588bf80f4bSopenharmony_ci{ 3598bf80f4bSopenharmony_ci EcsScene()->AddEngineTask( 3608bf80f4bSopenharmony_ci MakeTask( 3618bf80f4bSopenharmony_ci [name, other = BASE_NS::weak_ptr(target)](auto self) { 3628bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 3638bf80f4bSopenharmony_ci // We have set the name unique, so for simplicity use it without padding 3648bf80f4bSopenharmony_ci auto clone = sceneHolder->CloneEntity(self->EcsObject()->GetEntity(), name, false); 3658bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(clone)) { 3668bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask(MakeTask( 3678bf80f4bSopenharmony_ci [name](auto self, auto other) { 3688bf80f4bSopenharmony_ci if (auto ret = static_pointer_cast<NodeImpl>(other)) { 3698bf80f4bSopenharmony_ci META_NS::Property<uint32_t>(ret->GetLifecycleInfo())->SetValue(NODE_LC_CLONED); 3708bf80f4bSopenharmony_ci ret->EnsureEcsBinding(self->EcsScene(), true); 3718bf80f4bSopenharmony_ci } 3728bf80f4bSopenharmony_ci return false; 3738bf80f4bSopenharmony_ci }, 3748bf80f4bSopenharmony_ci self, other), 3758bf80f4bSopenharmony_ci false); 3768bf80f4bSopenharmony_ci } 3778bf80f4bSopenharmony_ci } 3788bf80f4bSopenharmony_ci return false; 3798bf80f4bSopenharmony_ci }, 3808bf80f4bSopenharmony_ci static_pointer_cast<NodeImpl>(GetSelf())), 3818bf80f4bSopenharmony_ci false); 3828bf80f4bSopenharmony_ci} 3838bf80f4bSopenharmony_ci 3848bf80f4bSopenharmony_ci/*META_NS::IObject::Ptr NodeImpl::GetClone(META_NS::ICloneableObject::CloneBehaviorFlags flags) const 3858bf80f4bSopenharmony_ci{ 3868bf80f4bSopenharmony_ci META_NS::IObject::Ptr ret = Super::GetClone(flags); 3878bf80f4bSopenharmony_ci auto namebuf = BASE_NS::to_string(interface_cast<META_NS::IObjectInstance>(ret)->GetInstanceId()); 3888bf80f4bSopenharmony_ci BASE_NS::string name(namebuf.data(), namebuf.size()); 3898bf80f4bSopenharmony_ci META_NS::SetValue(interface_pointer_cast<META_NS::INamed>(ret)->Name(), name); 3908bf80f4bSopenharmony_ci if (flags | META_NS::ICloneableObject::DEEP_CLONE_W_VALUES) { 3918bf80f4bSopenharmony_ci // clone also entity 3928bf80f4bSopenharmony_ci CloneEcs(name, ret); 3938bf80f4bSopenharmony_ci } else { 3948bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Cloned %s", name.c_str()); 3958bf80f4bSopenharmony_ci } 3968bf80f4bSopenharmony_ci 3978bf80f4bSopenharmony_ci // ensure ecs bindings w/ new object 3988bf80f4bSopenharmony_ci return ret; 3998bf80f4bSopenharmony_ci}*/ 4008bf80f4bSopenharmony_ci 4018bf80f4bSopenharmony_ciSCENE_NS::IEcsScene::Ptr NodeImpl::EcsScene() const 4028bf80f4bSopenharmony_ci{ 4038bf80f4bSopenharmony_ci return ecsScene_.lock(); 4048bf80f4bSopenharmony_ci} 4058bf80f4bSopenharmony_ci 4068bf80f4bSopenharmony_ciSCENE_NS::IEcsObject::Ptr NodeImpl::EcsObject() const 4078bf80f4bSopenharmony_ci{ 4088bf80f4bSopenharmony_ci return ecsObject_; 4098bf80f4bSopenharmony_ci} 4108bf80f4bSopenharmony_ci 4118bf80f4bSopenharmony_ciSceneHolder::Ptr NodeImpl::SceneHolder() const 4128bf80f4bSopenharmony_ci{ 4138bf80f4bSopenharmony_ci return sceneHolder_.lock(); 4148bf80f4bSopenharmony_ci} 4158bf80f4bSopenharmony_ci 4168bf80f4bSopenharmony_civoid NodeImpl::ClaimOwnershipOfEntity(bool ownsEntity) 4178bf80f4bSopenharmony_ci{ 4188bf80f4bSopenharmony_ci ownsEntity_ = ownsEntity; 4198bf80f4bSopenharmony_ci /* 4208bf80f4bSopenharmony_ci if (!IsResourceClassType()) { 4218bf80f4bSopenharmony_ci // If we do not own the target entity, the name property will be in read-only mode. 4228bf80f4bSopenharmony_ci auto nameInternal = interface_pointer_cast<META_NS::IMetaPropertyInternal>(Name()); 4238bf80f4bSopenharmony_ci if (nameInternal) { 4248bf80f4bSopenharmony_ci auto flags = Name()->Flags(); 4258bf80f4bSopenharmony_ci 4268bf80f4bSopenharmony_ci if (ownsEntity_) { 4278bf80f4bSopenharmony_ci flags = META_NS::SetFlag(flags, META_NS::IMetaProperty::PropertyFlagBits::WRITE); 4288bf80f4bSopenharmony_ci } else { 4298bf80f4bSopenharmony_ci flags = META_NS::ResetFlag(flags, META_NS::IMetaProperty::PropertyFlagBits::WRITE); 4308bf80f4bSopenharmony_ci } 4318bf80f4bSopenharmony_ci nameInternal->SetFlags(flags); 4328bf80f4bSopenharmony_ci } 4338bf80f4bSopenharmony_ci } 4348bf80f4bSopenharmony_ci */ 4358bf80f4bSopenharmony_ci} 4368bf80f4bSopenharmony_ci 4378bf80f4bSopenharmony_civoid NodeImpl::RemoveIndex(size_t index) 4388bf80f4bSopenharmony_ci{ 4398bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("remove node from %zu", index); 4408bf80f4bSopenharmony_ci removeIndex_ = index; 4418bf80f4bSopenharmony_ci} 4428bf80f4bSopenharmony_ci 4438bf80f4bSopenharmony_civoid NodeImpl::SetIndex(size_t index) 4448bf80f4bSopenharmony_ci{ 4458bf80f4bSopenharmony_ci if (removeIndex_ == index) { 4468bf80f4bSopenharmony_ci return; 4478bf80f4bSopenharmony_ci } 4488bf80f4bSopenharmony_ci 4498bf80f4bSopenharmony_ci if (removeIndex_ != SIZE_MAX && removeIndex_ < index) { 4508bf80f4bSopenharmony_ci index--; 4518bf80f4bSopenharmony_ci } 4528bf80f4bSopenharmony_ci 4538bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 4548bf80f4bSopenharmony_ci scene->AddEngineTask(MakeTask( 4558bf80f4bSopenharmony_ci [index](auto self) { 4568bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 4578bf80f4bSopenharmony_ci sceneHolder->ReindexEntity(self->EcsObject()->GetEntity(), index); 4588bf80f4bSopenharmony_ci } 4598bf80f4bSopenharmony_ci return false; 4608bf80f4bSopenharmony_ci }, 4618bf80f4bSopenharmony_ci static_pointer_cast<NodeImpl>(GetSelf())), 4628bf80f4bSopenharmony_ci false); 4638bf80f4bSopenharmony_ci } 4648bf80f4bSopenharmony_ci removeIndex_ = SIZE_MAX; // reset, this is not very convenient with subsequent async calls 4658bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("move node to %zu", index); 4668bf80f4bSopenharmony_ci} 4678bf80f4bSopenharmony_ci 4688bf80f4bSopenharmony_ciSCENE_NS::IScene::Ptr NodeImpl::GetScene() const 4698bf80f4bSopenharmony_ci{ 4708bf80f4bSopenharmony_ci return interface_pointer_cast<SCENE_NS::IScene>(ecsScene_); 4718bf80f4bSopenharmony_ci} 4728bf80f4bSopenharmony_ci 4738bf80f4bSopenharmony_civoid NodeImpl::RenameEntity(const BASE_NS::string& name) 4748bf80f4bSopenharmony_ci{ 4758bf80f4bSopenharmony_ci auto ecsScene = EcsScene(); 4768bf80f4bSopenharmony_ci if (!ecsScene) { 4778bf80f4bSopenharmony_ci return; 4788bf80f4bSopenharmony_ci } 4798bf80f4bSopenharmony_ci 4808bf80f4bSopenharmony_ci ecsScene->AddEngineTask(MakeTask( 4818bf80f4bSopenharmony_ci [name](auto self) { 4828bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 4838bf80f4bSopenharmony_ci sceneHolder->RenameEntity(self->EcsObject()->GetEntity(), name); 4848bf80f4bSopenharmony_ci } 4858bf80f4bSopenharmony_ci return false; 4868bf80f4bSopenharmony_ci }, 4878bf80f4bSopenharmony_ci static_pointer_cast<NodeImpl>(GetSelf())), 4888bf80f4bSopenharmony_ci false); 4898bf80f4bSopenharmony_ci UpdateChildrenPath(); 4908bf80f4bSopenharmony_ci} 4918bf80f4bSopenharmony_ci 4928bf80f4bSopenharmony_ci// Todo, this is assuming moderate size of hierarchy, may have to rethink the recursion if that is not the case 4938bf80f4bSopenharmony_civoid NodeImpl::RecursivelyEnableCache(bool isActive) 4948bf80f4bSopenharmony_ci{ 4958bf80f4bSopenharmony_ci if (auto scene = GetScene()) { 4968bf80f4bSopenharmony_ci scene->SetCacheEnabled(GetSelf<SCENE_NS::INode>(), isActive); 4978bf80f4bSopenharmony_ci } 4988bf80f4bSopenharmony_ci 4998bf80f4bSopenharmony_ci if (auto container = GetSelf<META_NS::IContainer>()) { 5008bf80f4bSopenharmony_ci for (auto& object : container->GetAll()) { 5018bf80f4bSopenharmony_ci auto child = static_cast<NodeImpl*>(object.get()); 5028bf80f4bSopenharmony_ci 5038bf80f4bSopenharmony_ci child->RecursivelyEnableCache(isActive); 5048bf80f4bSopenharmony_ci } 5058bf80f4bSopenharmony_ci } 5068bf80f4bSopenharmony_ci} 5078bf80f4bSopenharmony_ci 5088bf80f4bSopenharmony_ci// Todo, this is assuming moderate size of hierarchy, may have to rethink the recursion if that is not the case 5098bf80f4bSopenharmony_civoid NodeImpl::UpdateChildrenPath() 5108bf80f4bSopenharmony_ci{ 5118bf80f4bSopenharmony_ci if (auto scene=GetScene()) { 5128bf80f4bSopenharmony_ci scene->UpdateCachedNodePath(GetSelf<SCENE_NS::INode>()); 5138bf80f4bSopenharmony_ci } 5148bf80f4bSopenharmony_ci 5158bf80f4bSopenharmony_ci if (auto container = GetSelf<META_NS::IContainer>()) { 5168bf80f4bSopenharmony_ci auto cachedPath = META_ACCESS_PROPERTY(Path)->GetValue(); 5178bf80f4bSopenharmony_ci cachedPath.append(Name()->GetValue()); 5188bf80f4bSopenharmony_ci cachedPath.append("/"); 5198bf80f4bSopenharmony_ci for (auto& object : container->GetAll()) { 5208bf80f4bSopenharmony_ci auto child = dynamic_cast<NodeImpl*>(object.get()); 5218bf80f4bSopenharmony_ci if (child) { 5228bf80f4bSopenharmony_ci child->META_ACCESS_PROPERTY(Path)->SetValue(cachedPath); 5238bf80f4bSopenharmony_ci child->UpdateChildrenPath(); 5248bf80f4bSopenharmony_ci } 5258bf80f4bSopenharmony_ci } 5268bf80f4bSopenharmony_ci } 5278bf80f4bSopenharmony_ci} 5288bf80f4bSopenharmony_ci 5298bf80f4bSopenharmony_cibool NodeImpl::ShouldExport() const 5308bf80f4bSopenharmony_ci{ 5318bf80f4bSopenharmony_ci bool isProxyNode = false; 5328bf80f4bSopenharmony_ci auto priv = interface_cast<INodeEcsInterfacePrivate>(GetSelf()); 5338bf80f4bSopenharmony_ci if (META_NS::Property<uint32_t> lifeCycleInfo = priv->GetLifecycleInfo(false)) { 5348bf80f4bSopenharmony_ci if (lifeCycleInfo->GetValue() == NODE_LC_MIRROR_EXISTING) { 5358bf80f4bSopenharmony_ci isProxyNode = true; 5368bf80f4bSopenharmony_ci } 5378bf80f4bSopenharmony_ci } 5388bf80f4bSopenharmony_ci 5398bf80f4bSopenharmony_ci if (!isProxyNode) { 5408bf80f4bSopenharmony_ci isProxyNode = !ownsEntity_; 5418bf80f4bSopenharmony_ci } 5428bf80f4bSopenharmony_ci 5438bf80f4bSopenharmony_ci // If we have mesh that needs to be exported, then serialize self. 5448bf80f4bSopenharmony_ci auto mesh = GetMesh(); 5458bf80f4bSopenharmony_ci if (auto privateInterface = interface_cast<INodeEcsInterfacePrivate>(mesh)) { 5468bf80f4bSopenharmony_ci if (privateInterface->ShouldExport()) { 5478bf80f4bSopenharmony_ci return true; 5488bf80f4bSopenharmony_ci } 5498bf80f4bSopenharmony_ci } 5508bf80f4bSopenharmony_ci 5518bf80f4bSopenharmony_ci // Proxy node is exported if .. 5528bf80f4bSopenharmony_ci if (isProxyNode) { 5538bf80f4bSopenharmony_ci // It has changed properties. 5548bf80f4bSopenharmony_ci if (HasChangedProperties(*GetSelf<META_NS::IMetadata>())) { 5558bf80f4bSopenharmony_ci return true; 5568bf80f4bSopenharmony_ci } 5578bf80f4bSopenharmony_ci 5588bf80f4bSopenharmony_ci // It has attachments. 5598bf80f4bSopenharmony_ci if (auto attach = GetSelf<META_NS::IAttach>()) { 5608bf80f4bSopenharmony_ci if (attach->GetAttachments({}, false).size() > 0) { 5618bf80f4bSopenharmony_ci return true; 5628bf80f4bSopenharmony_ci } 5638bf80f4bSopenharmony_ci } 5648bf80f4bSopenharmony_ci 5658bf80f4bSopenharmony_ci // Any of its child needs to be exported. 5668bf80f4bSopenharmony_ci if (auto container = GetSelf<META_NS::IContainer>()) { 5678bf80f4bSopenharmony_ci for (auto& childNode : container->GetAll<INode>()) { 5688bf80f4bSopenharmony_ci if (auto privateInterface = interface_cast<INodeEcsInterfacePrivate>(childNode)) { 5698bf80f4bSopenharmony_ci if (privateInterface->ShouldExport()) { 5708bf80f4bSopenharmony_ci return true; 5718bf80f4bSopenharmony_ci } 5728bf80f4bSopenharmony_ci } 5738bf80f4bSopenharmony_ci } 5748bf80f4bSopenharmony_ci } 5758bf80f4bSopenharmony_ci 5768bf80f4bSopenharmony_ci return false; 5778bf80f4bSopenharmony_ci } 5788bf80f4bSopenharmony_ci 5798bf80f4bSopenharmony_ci return true; 5808bf80f4bSopenharmony_ci} 5818bf80f4bSopenharmony_ci 5828bf80f4bSopenharmony_cibool NodeImpl::Initialize(SCENE_NS::IEcsScene::Ptr& scene, SCENE_NS::IEcsObject::Ptr& ecsObject, 5838bf80f4bSopenharmony_ci SCENE_NS::INode::Ptr parent, const BASE_NS::string& path, const BASE_NS::string& name, 5848bf80f4bSopenharmony_ci SceneHolder::WeakPtr sceneHolder, CORE_NS::Entity entity) 5858bf80f4bSopenharmony_ci{ 5868bf80f4bSopenharmony_ci if (!ecsObject || !scene) { 5878bf80f4bSopenharmony_ci return false; 5888bf80f4bSopenharmony_ci } 5898bf80f4bSopenharmony_ci 5908bf80f4bSopenharmony_ci ecsScene_ = scene; 5918bf80f4bSopenharmony_ci ecsObject_ = ecsObject; 5928bf80f4bSopenharmony_ci sceneHolder_ = sceneHolder; 5938bf80f4bSopenharmony_ci 5948bf80f4bSopenharmony_ci auto currentParent = GetParent(); 5958bf80f4bSopenharmony_ci if (!currentParent && parent) { 5968bf80f4bSopenharmony_ci interface_cast<IContainer>(parent)->Add(GetSelf()); 5978bf80f4bSopenharmony_ci } 5988bf80f4bSopenharmony_ci 5998bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(ConnectionStatus)->SetBind(ecsObject->ConnectionStatus()); 6008bf80f4bSopenharmony_ci 6018bf80f4bSopenharmony_ci // Need to set a path before ECS instantiation to enable IContainer to share a proxy beforehand 6028bf80f4bSopenharmony_ci SetPath(path, name, entity); 6038bf80f4bSopenharmony_ci if (!ecsObject->GetEcs()) { 6048bf80f4bSopenharmony_ci // We will not proceed further with construction until we have esc object bound 6058bf80f4bSopenharmony_ci return false; 6068bf80f4bSopenharmony_ci } 6078bf80f4bSopenharmony_ci 6088bf80f4bSopenharmony_ci return true; // CompleteInitialization(path); 6098bf80f4bSopenharmony_ci} 6108bf80f4bSopenharmony_ci 6118bf80f4bSopenharmony_civoid NodeImpl::BindObject(SCENE_NS::INode::Ptr node) 6128bf80f4bSopenharmony_ci{ 6138bf80f4bSopenharmony_ci auto priv = interface_cast<INodeEcsInterfacePrivate>(node); 6148bf80f4bSopenharmony_ci if (!priv) { 6158bf80f4bSopenharmony_ci return; 6168bf80f4bSopenharmony_ci } 6178bf80f4bSopenharmony_ci 6188bf80f4bSopenharmony_ci if (priv->EcsObject()) { 6198bf80f4bSopenharmony_ci return; 6208bf80f4bSopenharmony_ci } 6218bf80f4bSopenharmony_ci 6228bf80f4bSopenharmony_ci bool create = false; 6238bf80f4bSopenharmony_ci 6248bf80f4bSopenharmony_ci if (META_NS::Property<uint32_t> creationPolicy = priv->GetLifecycleInfo()) { 6258bf80f4bSopenharmony_ci create = (creationPolicy->GetValue() == NODE_LC_CREATED); 6268bf80f4bSopenharmony_ci } 6278bf80f4bSopenharmony_ci 6288bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG( 6298bf80f4bSopenharmony_ci "Connecting object from property: %s", (GetValue(node->Path()) + GetValue(node->Name())).c_str()); 6308bf80f4bSopenharmony_ci EcsScene()->BindNodeToEcs(node, GetValue(node->Path()) + GetValue(node->Name()), create); 6318bf80f4bSopenharmony_ci} 6328bf80f4bSopenharmony_ci 6338bf80f4bSopenharmony_cibool NodeImpl::CompleteInitialization(const BASE_NS::string& path) 6348bf80f4bSopenharmony_ci{ 6358bf80f4bSopenharmony_ci initializeTaskToken_ = {}; 6368bf80f4bSopenharmony_ci 6378bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 6388bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 6398bf80f4bSopenharmony_ci 6408bf80f4bSopenharmony_ci if (auto name = Name()->GetValue(); name != path) { 6418bf80f4bSopenharmony_ci RenameEntity(name); 6428bf80f4bSopenharmony_ci } 6438bf80f4bSopenharmony_ci 6448bf80f4bSopenharmony_ci // Ensure that our cache path is correct now that we have entity connected. 6458bf80f4bSopenharmony_ci interface_cast<SCENE_NS::IScene>(scene)->UpdateCachedNodePath(GetSelf<SCENE_NS::INode>()); 6468bf80f4bSopenharmony_ci 6478bf80f4bSopenharmony_ci propHandler_.Reset(); 6488bf80f4bSopenharmony_ci propHandler_.SetSceneHolder(SceneHolder()); 6498bf80f4bSopenharmony_ci 6508bf80f4bSopenharmony_ci // Use node properties as default, in case we have created the entity to ECS. 6518bf80f4bSopenharmony_ci propHandler_.SetUseEcsDefaults(!ownsEntity_); 6528bf80f4bSopenharmony_ci 6538bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Quat>(propHandler_, META_ACCESS_PROPERTY(Rotation), meta, TRANSFORM_ROTATION); 6548bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec3>(propHandler_, META_ACCESS_PROPERTY(Position), meta, TRANSFORM_POSITION); 6558bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec3>(propHandler_, META_ACCESS_PROPERTY(Scale), meta, TRANSFORM_SCALE); 6568bf80f4bSopenharmony_ci BindChanges<bool>(propHandler_, META_ACCESS_PROPERTY(Visible), meta, NODE_ENABLED); 6578bf80f4bSopenharmony_ci BindChanges<uint64_t>(propHandler_, META_ACCESS_PROPERTY(LayerMask), meta, LAYER_MASK); 6588bf80f4bSopenharmony_ci 6598bf80f4bSopenharmony_ci // Restore default behavior. 6608bf80f4bSopenharmony_ci propHandler_.SetUseEcsDefaults(true); 6618bf80f4bSopenharmony_ci 6628bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Mat4X4>(propHandler_, META_ACCESS_PROPERTY(LocalMatrix), meta, LMATRIX_MATRIX); 6638bf80f4bSopenharmony_ci 6648bf80f4bSopenharmony_ci auto rh = meta->GetPropertyByName(RM_HANDLE); 6658bf80f4bSopenharmony_ci 6668bf80f4bSopenharmony_ci auto mesh = META_NS::GetValue(Mesh()); 6678bf80f4bSopenharmony_ci if (mesh) { 6688bf80f4bSopenharmony_ci // if se have a mesh set, initialize it 6698bf80f4bSopenharmony_ci InitializeMesh(mesh, GetSelf<IEcsObject>()); 6708bf80f4bSopenharmony_ci } else if (rh) { 6718bf80f4bSopenharmony_ci // otherwise get mesh from engine only if the component has render mesh present 6728bf80f4bSopenharmony_ci GetMeshFromEngine(); 6738bf80f4bSopenharmony_ci } 6748bf80f4bSopenharmony_ci 6758bf80f4bSopenharmony_ci // if the node has render mesh component, subscribe changes from engin 6768bf80f4bSopenharmony_ci if (rh) { 6778bf80f4bSopenharmony_ci rh->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this]() { GetMeshFromEngine(); }), 6788bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 6798bf80f4bSopenharmony_ci } 6808bf80f4bSopenharmony_ci 6818bf80f4bSopenharmony_ci // and set the proxy if user wants to change the mesh through the property 6828bf80f4bSopenharmony_ci Mesh()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this]() { 6838bf80f4bSopenharmony_ci if (auto node = interface_pointer_cast<SCENE_NS::INode>(META_NS::GetValue(Mesh()))) { 6848bf80f4bSopenharmony_ci node->Status()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>( 6858bf80f4bSopenharmony_ci [](const auto& self, const auto& status) { 6868bf80f4bSopenharmony_ci if (self && status && status->GetValue() == SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED) { 6878bf80f4bSopenharmony_ci static_cast<NodeImpl*>(self.get())->SetMeshToEngine(); 6888bf80f4bSopenharmony_ci } 6898bf80f4bSopenharmony_ci }, 6908bf80f4bSopenharmony_ci GetSelf(), node->Status())); 6918bf80f4bSopenharmony_ci if (auto status = META_NS::GetValue(node->Status()); 6928bf80f4bSopenharmony_ci status == SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED || 6938bf80f4bSopenharmony_ci status == SCENE_NS::INode::NODE_STATUS_CONNECTED) { 6948bf80f4bSopenharmony_ci SetMeshToEngine(); 6958bf80f4bSopenharmony_ci } 6968bf80f4bSopenharmony_ci } 6978bf80f4bSopenharmony_ci }), 6988bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 6998bf80f4bSopenharmony_ci 7008bf80f4bSopenharmony_ci if (buildBehavior_ == NODE_BUILD_CHILDREN_GRADUAL) { 7018bf80f4bSopenharmony_ci // We are assumingly on the correct thread already, but have deriving classes a slot to complete 7028bf80f4bSopenharmony_ci // initialization Before notifying the client 7038bf80f4bSopenharmony_ci scene->AddApplicationTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>( 7048bf80f4bSopenharmony_ci [buildBehavior = buildBehavior_](const auto& node) { 7058bf80f4bSopenharmony_ci if (node) { 7068bf80f4bSopenharmony_ci node->BuildChildren(buildBehavior); 7078bf80f4bSopenharmony_ci } 7088bf80f4bSopenharmony_ci return false; 7098bf80f4bSopenharmony_ci }, 7108bf80f4bSopenharmony_ci GetSelf<SCENE_NS::INode>()), 7118bf80f4bSopenharmony_ci true); 7128bf80f4bSopenharmony_ci } 7138bf80f4bSopenharmony_ci 7148bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 7158bf80f4bSopenharmony_ci for (auto& attachment : ecsObject_->GetAttachments()) { 7168bf80f4bSopenharmony_ci if (auto animation = sceneHolder->GetAnimation(attachment)) { 7178bf80f4bSopenharmony_ci // Make flat animation array based on name-property + entity id separated by ':' 7188bf80f4bSopenharmony_ci // This is identical to meshes and materials, but the implementation is tad different 7198bf80f4bSopenharmony_ci auto name = META_NS::GetValue(interface_cast<META_NS::INamed>(animation)->Name()); 7208bf80f4bSopenharmony_ci name.append(":"); 7218bf80f4bSopenharmony_ci name.append(BASE_NS::to_hex(attachment.id)); 7228bf80f4bSopenharmony_ci if (auto attachment = GetScene()->GetAnimation(name)) { 7238bf80f4bSopenharmony_ci if (auto typed = interface_cast<META_NS::IAttachment>(attachment)) { 7248bf80f4bSopenharmony_ci Attach(interface_pointer_cast<IObject>(attachment), GetSelf()); 7258bf80f4bSopenharmony_ci } 7268bf80f4bSopenharmony_ci } 7278bf80f4bSopenharmony_ci } 7288bf80f4bSopenharmony_ci } 7298bf80f4bSopenharmony_ci } 7308bf80f4bSopenharmony_ci 7318bf80f4bSopenharmony_ci SubscribeToNameChanges(); 7328bf80f4bSopenharmony_ci 7338bf80f4bSopenharmony_ci return true; 7348bf80f4bSopenharmony_ci } 7358bf80f4bSopenharmony_ci return false; 7368bf80f4bSopenharmony_ci} 7378bf80f4bSopenharmony_ci 7388bf80f4bSopenharmony_civoid NodeImpl::SetPathWithEcsNode(const BASE_NS::shared_ptr<NodeImpl>& self, const BASE_NS::string& name, 7398bf80f4bSopenharmony_ci SceneHolder::Ptr sceneHolder, const CORE3D_NS::ISceneNode* ecsNode) 7408bf80f4bSopenharmony_ci{ 7418bf80f4bSopenharmony_ci BASE_NS::weak_ptr<IObject> me = static_pointer_cast<IObject>(self); 7428bf80f4bSopenharmony_ci if (!self->EcsObject()->GetEcs()) { 7438bf80f4bSopenharmony_ci // Initialize ECS Object 7448bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("binding node: %s", name.c_str()); 7458bf80f4bSopenharmony_ci // We enable layer component just to have it handled consistently across 7468bf80f4bSopenharmony_ci // the other properties, this may not be desired 7478bf80f4bSopenharmony_ci auto entity = ecsNode->GetEntity(); 7488bf80f4bSopenharmony_ci sceneHolder->EnableLayerComponent(entity); 7498bf80f4bSopenharmony_ci 7508bf80f4bSopenharmony_ci auto ecsObject = self->EcsObject(); 7518bf80f4bSopenharmony_ci // Introspect the engine components 7528bf80f4bSopenharmony_ci if (auto proxyIf = interface_cast<SCENE_NS::IEcsProxyObject>(ecsObject)) { 7538bf80f4bSopenharmony_ci proxyIf->SetCommonListener(sceneHolder->GetCommonEcsListener()); 7548bf80f4bSopenharmony_ci } 7558bf80f4bSopenharmony_ci ecsObject->DefineTargetProperties(self->PropertyNameMask()); 7568bf80f4bSopenharmony_ci ecsObject->SetEntity(sceneHolder->GetEcs(), entity); 7578bf80f4bSopenharmony_ci sceneHolder->UpdateAttachments(ecsObject); 7588bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 7598bf80f4bSopenharmony_ci MakeTask( 7608bf80f4bSopenharmony_ci [name](auto selfObject) { 7618bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 7628bf80f4bSopenharmony_ci self->CompleteInitialization(name); 7638bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTED); 7648bf80f4bSopenharmony_ci if (auto node = interface_cast<SCENE_NS::INode>(selfObject)) { 7658bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(node->OnLoaded()); 7668bf80f4bSopenharmony_ci } 7678bf80f4bSopenharmony_ci } 7688bf80f4bSopenharmony_ci return false; 7698bf80f4bSopenharmony_ci }, 7708bf80f4bSopenharmony_ci me), 7718bf80f4bSopenharmony_ci false); 7728bf80f4bSopenharmony_ci } else { 7738bf80f4bSopenharmony_ci // ECS was already initialized, presumably we were just re-parented, update index 7748bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask(MakeTask( 7758bf80f4bSopenharmony_ci [](auto selfObject) { 7768bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 7778bf80f4bSopenharmony_ci self->UpdateChildrenPath(); 7788bf80f4bSopenharmony_ci } 7798bf80f4bSopenharmony_ci return false; 7808bf80f4bSopenharmony_ci }, 7818bf80f4bSopenharmony_ci me), 7828bf80f4bSopenharmony_ci false); 7838bf80f4bSopenharmony_ci } 7848bf80f4bSopenharmony_ci} 7858bf80f4bSopenharmony_ci 7868bf80f4bSopenharmony_cibool NodeImpl::SetPathWithoutNode(const BASE_NS::shared_ptr<NodeImpl>& self, const BASE_NS::string& name, 7878bf80f4bSopenharmony_ci const BASE_NS::string& fullPath, SceneHolder::Ptr sceneHolder) 7888bf80f4bSopenharmony_ci{ 7898bf80f4bSopenharmony_ci CORE_NS::Entity entity; 7908bf80f4bSopenharmony_ci BASE_NS::weak_ptr<IObject> me = static_pointer_cast<IObject>(self); 7918bf80f4bSopenharmony_ci if (sceneHolder->FindResource(name, fullPath, entity)) { 7928bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("binding resource: %s", name.c_str()); 7938bf80f4bSopenharmony_ci if (auto proxyIf = interface_cast<SCENE_NS::IEcsProxyObject>(self->EcsObject())) { 7948bf80f4bSopenharmony_ci proxyIf->SetCommonListener(sceneHolder->GetCommonEcsListener()); 7958bf80f4bSopenharmony_ci } 7968bf80f4bSopenharmony_ci self->EcsObject()->DefineTargetProperties(self->PropertyNameMask()); 7978bf80f4bSopenharmony_ci self->EcsObject()->SetEntity(sceneHolder->GetEcs(), entity); 7988bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask(MakeTask( 7998bf80f4bSopenharmony_ci [name](auto selfObject) { 8008bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 8018bf80f4bSopenharmony_ci // There is not much to bind inside node, could presumably 8028bf80f4bSopenharmony_ci // fork this as own instance 8038bf80f4bSopenharmony_ci self->CompleteInitialization(name); 8048bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTED); 8058bf80f4bSopenharmony_ci if (self->buildBehavior_ == NODE_BUILD_CHILDREN_ALL) { 8068bf80f4bSopenharmony_ci self->BuildChildren(self->buildBehavior_); 8078bf80f4bSopenharmony_ci } 8088bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(self->OnLoaded()); 8098bf80f4bSopenharmony_ci } 8108bf80f4bSopenharmony_ci return false; 8118bf80f4bSopenharmony_ci }, 8128bf80f4bSopenharmony_ci me), 8138bf80f4bSopenharmony_ci false); 8148bf80f4bSopenharmony_ci } else if (META_NS::GetValue(self->GetScene()->Asynchronous()) && self->shouldRetry_) { 8158bf80f4bSopenharmony_ci // When nodes are deserialized, it is possible that the construction order 8168bf80f4bSopenharmony_ci // prepares children before their parent, just letting the task spin once more 8178bf80f4bSopenharmony_ci // fixes the problem. ToDo: Get more elegant solution for this 8188bf80f4bSopenharmony_ci self->shouldRetry_ = false; 8198bf80f4bSopenharmony_ci return true; 8208bf80f4bSopenharmony_ci } else { 8218bf80f4bSopenharmony_ci // Giving in. If the node arrives later, it may be re-attempted due e.g. parent 8228bf80f4bSopenharmony_ci // or name changes, otherwise we are done with it. 8238bf80f4bSopenharmony_ci self->shouldRetry_ = true; 8248bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask(MakeTask( 8258bf80f4bSopenharmony_ci [name](auto selfObject) { 8268bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 8278bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_DISCONNECTED); 8288bf80f4bSopenharmony_ci } 8298bf80f4bSopenharmony_ci return false; 8308bf80f4bSopenharmony_ci }, 8318bf80f4bSopenharmony_ci me), 8328bf80f4bSopenharmony_ci false); 8338bf80f4bSopenharmony_ci } 8348bf80f4bSopenharmony_ci return false; 8358bf80f4bSopenharmony_ci} 8368bf80f4bSopenharmony_ci 8378bf80f4bSopenharmony_ci// It is turning out that the path is pretty much the only thing that we can rely when operating asynchronously 8388bf80f4bSopenharmony_ci// from application thread to engine thread. Still this can go wrong if subsequent events are not recorded in 8398bf80f4bSopenharmony_ci// order. 8408bf80f4bSopenharmony_civoid NodeImpl::SetPath(const BASE_NS::string& path, const BASE_NS::string& name, CORE_NS::Entity entity) 8418bf80f4bSopenharmony_ci{ 8428bf80f4bSopenharmony_ci // BASE_NS::string name; 8438bf80f4bSopenharmony_ci 8448bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Path)->SetValue(path); 8458bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Name)->SetValue(name); 8468bf80f4bSopenharmony_ci 8478bf80f4bSopenharmony_ci // SCENE_PLUGIN_VERBOSE_LOG("asking engine to make sure that: '%s' is child of '%s'", name.c_str(), 8488bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 8498bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTING); 8508bf80f4bSopenharmony_ci if (auto iscene = interface_cast<SCENE_NS::IScene>(scene)) { 8518bf80f4bSopenharmony_ci iscene->UpdateCachedNodePath(GetSelf<SCENE_NS::INode>()); 8528bf80f4bSopenharmony_ci } 8538bf80f4bSopenharmony_ci 8548bf80f4bSopenharmony_ci initializeTaskToken_ = scene->AddEngineTask( 8558bf80f4bSopenharmony_ci MakeTask( 8568bf80f4bSopenharmony_ci [name, fullpath = path + name](auto selfObject) { 8578bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 8588bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 8598bf80f4bSopenharmony_ci auto parentPath = self->META_ACCESS_PROPERTY(Path) 8608bf80f4bSopenharmony_ci ->GetValue(); // should also this be snapshot from App thread? 8618bf80f4bSopenharmony_ci 8628bf80f4bSopenharmony_ci auto ecsNode = sceneHolder->ReparentEntity(parentPath, name); 8638bf80f4bSopenharmony_ci 8648bf80f4bSopenharmony_ci if (ecsNode) { 8658bf80f4bSopenharmony_ci SetPathWithEcsNode(self, name, sceneHolder, ecsNode); 8668bf80f4bSopenharmony_ci } else { 8678bf80f4bSopenharmony_ci // The entity might be valid even if there is no node attached 8688bf80f4bSopenharmony_ci return SetPathWithoutNode(self, name, fullpath, sceneHolder); 8698bf80f4bSopenharmony_ci } 8708bf80f4bSopenharmony_ci } 8718bf80f4bSopenharmony_ci } 8728bf80f4bSopenharmony_ci return false; 8738bf80f4bSopenharmony_ci }, 8748bf80f4bSopenharmony_ci GetSelf()), 8758bf80f4bSopenharmony_ci false); 8768bf80f4bSopenharmony_ci } 8778bf80f4bSopenharmony_ci} 8788bf80f4bSopenharmony_ci 8798bf80f4bSopenharmony_ci// static constexpr BASE_NS::string_view LIFECYCLE_PROPERTY_NAME = "NodeLifeCycle"; 8808bf80f4bSopenharmony_ci 8818bf80f4bSopenharmony_cibool NodeImpl::HasLifecycleInfo() 8828bf80f4bSopenharmony_ci{ 8838bf80f4bSopenharmony_ci return GetLifecycleInfo(false) != nullptr; 8848bf80f4bSopenharmony_ci} 8858bf80f4bSopenharmony_ci 8868bf80f4bSopenharmony_ci// Different scenarios currently to be considered 8878bf80f4bSopenharmony_ci// 1) Create and bind a new prefab instance 8888bf80f4bSopenharmony_ci// -> create and assign ecs node 8898bf80f4bSopenharmony_ci// -> create new prefab instance 8908bf80f4bSopenharmony_ci// -> bind (read data from prefab) 8918bf80f4bSopenharmony_ci// prefab and its children need to know they were generated by prefab 8928bf80f4bSopenharmony_ci// 8938bf80f4bSopenharmony_ci// 2) Bind a new node to an existing entity: 8948bf80f4bSopenharmony_ci// this can take place throud two different routes, either the node is explicitly requested from the scene or 8958bf80f4bSopenharmony_ci// restored by de-serialization/import/clone 8968bf80f4bSopenharmony_ci// -> just prepare and assign ecs object 8978bf80f4bSopenharmony_ci// -> system will try find and sync the state later (potentially bidirectional sync) 8988bf80f4bSopenharmony_ci// values that are modified should have set-bits on properties 8998bf80f4bSopenharmony_ci// 9008bf80f4bSopenharmony_ci// 3) Create new proxy with entity and component with default values: 9018bf80f4bSopenharmony_ci// this is either through de-serialization or c++ api 9028bf80f4bSopenharmony_ci// -> sync the proxy state to ecs 9038bf80f4bSopenharmony_ci// information on entity creation needs to be preserved 9048bf80f4bSopenharmony_ci 9058bf80f4bSopenharmony_ciMETA_NS::IProperty::Ptr NodeImpl::GetLifecycleInfo(bool create) 9068bf80f4bSopenharmony_ci{ 9078bf80f4bSopenharmony_ci META_NS::IProperty::Ptr creationPolicy; 9088bf80f4bSopenharmony_ci if (auto meta = GetSelf<META_NS::IMetadata>()) { 9098bf80f4bSopenharmony_ci META_NS::IProperty::Ptr lifeCycle; 9108bf80f4bSopenharmony_ci if (lifeCycle = meta->GetPropertyByName(LIFECYCLE_PROPERTY_NAME); !lifeCycle && create) { 9118bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<uint32_t>(LIFECYCLE_PROPERTY_NAME, 0, META_NS::DEFAULT_PROPERTY_FLAGS | META_NS::ObjectFlagBits::INTERNAL); 9128bf80f4bSopenharmony_ci meta->AddProperty(p); 9138bf80f4bSopenharmony_ci lifeCycle = p; 9148bf80f4bSopenharmony_ci } 9158bf80f4bSopenharmony_ci 9168bf80f4bSopenharmony_ci if (creationPolicy = META_NS::Property<uint32_t>(lifeCycle); !creationPolicy && create) { 9178bf80f4bSopenharmony_ci CORE_LOG_E("%s: inconsistent system state. Can not store creation info for node", __func__); 9188bf80f4bSopenharmony_ci } 9198bf80f4bSopenharmony_ci } 9208bf80f4bSopenharmony_ci return creationPolicy; 9218bf80f4bSopenharmony_ci} 9228bf80f4bSopenharmony_ci 9238bf80f4bSopenharmony_civoid NodeImpl::EnsureEcsBinding(SCENE_NS::IEcsScene::Ptr scene, bool force) 9248bf80f4bSopenharmony_ci{ 9258bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("Node::EnsureEcsBinding called for %s (%s)", GetName().c_str(), Path()->Get().c_str()); 9268bf80f4bSopenharmony_ci if (scene && (force || !EcsScene())) { 9278bf80f4bSopenharmony_ci BASE_NS::string fullPath = META_NS::GetValue(META_ACCESS_PROPERTY(Path)); 9288bf80f4bSopenharmony_ci fullPath.append(META_NS::GetValue(Name())); 9298bf80f4bSopenharmony_ci auto self = GetSelf<SCENE_NS::INode>(); 9308bf80f4bSopenharmony_ci 9318bf80f4bSopenharmony_ci INodeEcsInterfacePrivate* privateParts { nullptr }; 9328bf80f4bSopenharmony_ci 9338bf80f4bSopenharmony_ci bool shouldCreate = true; 9348bf80f4bSopenharmony_ci privateParts = interface_cast<INodeEcsInterfacePrivate>(self); 9358bf80f4bSopenharmony_ci if (auto lifeCycleInfo = privateParts->GetLifecycleInfo(false)) { 9368bf80f4bSopenharmony_ci if (auto value = META_NS::Property<uint32_t>(lifeCycleInfo)->GetValue()) { 9378bf80f4bSopenharmony_ci shouldCreate = (value & NODE_LC_CLONED) || (value & NODE_LC_CREATED); 9388bf80f4bSopenharmony_ci } 9398bf80f4bSopenharmony_ci } 9408bf80f4bSopenharmony_ci scene->BindNodeToEcs(self, fullPath, shouldCreate); 9418bf80f4bSopenharmony_ci } 9428bf80f4bSopenharmony_ci} 9438bf80f4bSopenharmony_ci 9448bf80f4bSopenharmony_ciBASE_NS::vector<SCENE_NS::IProxyObject::PropertyPair> NodeImpl::ListBoundProperties() const 9458bf80f4bSopenharmony_ci{ 9468bf80f4bSopenharmony_ci return propHandler_.GetBoundProperties(); 9478bf80f4bSopenharmony_ci} 9488bf80f4bSopenharmony_ci 9498bf80f4bSopenharmony_civoid NodeImpl::BuildChildrenIterateOver(const BASE_NS::shared_ptr<NodeImpl>& self, const SCENE_NS::IEcsScene::Ptr& ecs, 9508bf80f4bSopenharmony_ci const BASE_NS::string& fullPath, BASE_NS::array_view<CORE3D_NS::ISceneNode* const> children) 9518bf80f4bSopenharmony_ci{ 9528bf80f4bSopenharmony_ci BASE_NS::weak_ptr<IObject> me = static_pointer_cast<IObject>(self); 9538bf80f4bSopenharmony_ci for (const auto& child : children) { 9548bf80f4bSopenharmony_ci auto childPath = fullPath; 9558bf80f4bSopenharmony_ci auto childName = child->GetName(); 9568bf80f4bSopenharmony_ci if (!childName.empty() && childName.find("/") == BASE_NS::string_view::npos && 9578bf80f4bSopenharmony_ci !childName.starts_with(MULTI_MESH_CHILD_PREFIX)) { 9588bf80f4bSopenharmony_ci childPath.append("/"); 9598bf80f4bSopenharmony_ci childPath.append(childName); 9608bf80f4bSopenharmony_ci 9618bf80f4bSopenharmony_ci ecs->AddApplicationTask( 9628bf80f4bSopenharmony_ci MakeTask( 9638bf80f4bSopenharmony_ci [childPath, childName](auto selfObject) { 9648bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 9658bf80f4bSopenharmony_ci if (auto scene = self->GetScene()) { 9668bf80f4bSopenharmony_ci if (auto child = interface_pointer_cast<SCENE_NS::INode>(self->FindByName(childName))) { 9678bf80f4bSopenharmony_ci self->MonitorChild(child); 9688bf80f4bSopenharmony_ci // The call is pretty much costless when the ecs object has been already set, not 9698bf80f4bSopenharmony_ci // sure if there is a code path that needs this, though 9708bf80f4bSopenharmony_ci static_pointer_cast<NodeImpl>(child)->EnsureEcsBinding(self->EcsScene()); 9718bf80f4bSopenharmony_ci } else { 9728bf80f4bSopenharmony_ci auto node = scene->GetNode(childPath, META_NS::IObject::UID, self->buildBehavior_); 9738bf80f4bSopenharmony_ci self->MonitorChild(node); 9748bf80f4bSopenharmony_ci node->BuildChildren(self->buildBehavior_); 9758bf80f4bSopenharmony_ci } 9768bf80f4bSopenharmony_ci } 9778bf80f4bSopenharmony_ci } 9788bf80f4bSopenharmony_ci return false; 9798bf80f4bSopenharmony_ci }, 9808bf80f4bSopenharmony_ci me), 9818bf80f4bSopenharmony_ci false); 9828bf80f4bSopenharmony_ci } 9838bf80f4bSopenharmony_ci } 9848bf80f4bSopenharmony_ci} 9858bf80f4bSopenharmony_ci 9868bf80f4bSopenharmony_cibool NodeImpl::BuildChildren(SCENE_NS::INode::BuildBehavior options) 9878bf80f4bSopenharmony_ci{ 9888bf80f4bSopenharmony_ci buildBehavior_ = options; 9898bf80f4bSopenharmony_ci 9908bf80f4bSopenharmony_ci if (options == SCENE_NS::INode::NODE_BUILD_CHILDREN_NO_BUILD || !GetScene()) { 9918bf80f4bSopenharmony_ci return true; 9928bf80f4bSopenharmony_ci } 9938bf80f4bSopenharmony_ci 9948bf80f4bSopenharmony_ci if (!ecsObject_ || !ecsObject_->GetEcs()) { 9958bf80f4bSopenharmony_ci if (!META_NS::GetValue(GetScene()->Asynchronous())) { 9968bf80f4bSopenharmony_ci CORE_LOG_W("%s: no ecs available, cannot inspect children", __func__); 9978bf80f4bSopenharmony_ci } 9988bf80f4bSopenharmony_ci return false; 9998bf80f4bSopenharmony_ci } 10008bf80f4bSopenharmony_ci 10018bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 10028bf80f4bSopenharmony_ci BASE_NS::string fullPath = META_ACCESS_PROPERTY(Path)->GetValue(); 10038bf80f4bSopenharmony_ci fullPath.append(Name()->GetValue()); 10048bf80f4bSopenharmony_ci 10058bf80f4bSopenharmony_ci if (fullPath.starts_with("/")) { 10068bf80f4bSopenharmony_ci fullPath.erase(0, 1); 10078bf80f4bSopenharmony_ci } 10088bf80f4bSopenharmony_ci if (options == SCENE_NS::INode::NODE_BUILD_ONLY_DIRECT_CHILDREN) { 10098bf80f4bSopenharmony_ci // yeah, for now.. let's just do this. 10108bf80f4bSopenharmony_ci options = SCENE_NS::INode::NODE_BUILD_CHILDREN_GRADUAL; 10118bf80f4bSopenharmony_ci } 10128bf80f4bSopenharmony_ci 10138bf80f4bSopenharmony_ci scene->AddEngineTask(MakeTask([me = BASE_NS::weak_ptr(GetSelf()), fullPath]() { 10148bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(me.lock())) { 10158bf80f4bSopenharmony_ci if (auto ecs = self->EcsScene()) { 10168bf80f4bSopenharmony_ci CORE3D_NS::INodeSystem* nodeSystem = 10178bf80f4bSopenharmony_ci static_cast<CORE3D_NS::INodeSystem*>(ecs->GetEcs()->GetSystem(CORE3D_NS::INodeSystem::UID)); 10188bf80f4bSopenharmony_ci const auto& root = nodeSystem->GetRootNode(); 10198bf80f4bSopenharmony_ci const auto& node = root.LookupNodeByPath(fullPath); 10208bf80f4bSopenharmony_ci if (!node) { 10218bf80f4bSopenharmony_ci CORE_LOG_W("%s: cannot find '%s'", __func__, fullPath.c_str()); 10228bf80f4bSopenharmony_ci } else { 10238bf80f4bSopenharmony_ci // 1) on engine queue introspect children nodes 10248bf80f4bSopenharmony_ci const auto& children = node->GetChildren(); 10258bf80f4bSopenharmony_ci if (children.size() == 0 && 10268bf80f4bSopenharmony_ci META_NS::GetValue(self->Status()) != SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED) { 10278bf80f4bSopenharmony_ci ecs->AddApplicationTask(MakeTask( 10288bf80f4bSopenharmony_ci [](auto selfObject) { 10298bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 10308bf80f4bSopenharmony_ci self->SetStatus( 10318bf80f4bSopenharmony_ci SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED); 10328bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(self->OnBound()); 10338bf80f4bSopenharmony_ci self->bound_ = true; 10348bf80f4bSopenharmony_ci } 10358bf80f4bSopenharmony_ci return false; 10368bf80f4bSopenharmony_ci }, 10378bf80f4bSopenharmony_ci me), 10388bf80f4bSopenharmony_ci false); 10398bf80f4bSopenharmony_ci } else { 10408bf80f4bSopenharmony_ci // 2) on app queue instantiate nodes 10418bf80f4bSopenharmony_ci BuildChildrenIterateOver(self, ecs, fullPath, children); 10428bf80f4bSopenharmony_ci 10438bf80f4bSopenharmony_ci // once we have iterated through children, check status once 10448bf80f4bSopenharmony_ci ecs->AddApplicationTask(MakeTask( 10458bf80f4bSopenharmony_ci [](auto selfObject) { 10468bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 10478bf80f4bSopenharmony_ci self->CheckChildrenStatus(); 10488bf80f4bSopenharmony_ci } 10498bf80f4bSopenharmony_ci return false; 10508bf80f4bSopenharmony_ci }, 10518bf80f4bSopenharmony_ci me), 10528bf80f4bSopenharmony_ci false); 10538bf80f4bSopenharmony_ci } 10548bf80f4bSopenharmony_ci } 10558bf80f4bSopenharmony_ci } 10568bf80f4bSopenharmony_ci } 10578bf80f4bSopenharmony_ci return false; 10588bf80f4bSopenharmony_ci }), 10598bf80f4bSopenharmony_ci false); 10608bf80f4bSopenharmony_ci } 10618bf80f4bSopenharmony_ci return true; 10628bf80f4bSopenharmony_ci} 10638bf80f4bSopenharmony_ci 10648bf80f4bSopenharmony_civoid NodeImpl::CheckChildrenStatus() 10658bf80f4bSopenharmony_ci{ 10668bf80f4bSopenharmony_ci for (const auto& child : monitored_) { 10678bf80f4bSopenharmony_ci if (!child->Ready()) { 10688bf80f4bSopenharmony_ci return; 10698bf80f4bSopenharmony_ci } 10708bf80f4bSopenharmony_ci } 10718bf80f4bSopenharmony_ci size_t ix = 0; 10728bf80f4bSopenharmony_ci while (ix < monitored_.size()) { 10738bf80f4bSopenharmony_ci if (monitored_[ix]->Valid()) { 10748bf80f4bSopenharmony_ci ix++; 10758bf80f4bSopenharmony_ci } else { 10768bf80f4bSopenharmony_ci monitored_.erase(monitored_.begin() + ix); 10778bf80f4bSopenharmony_ci } 10788bf80f4bSopenharmony_ci } 10798bf80f4bSopenharmony_ci 10808bf80f4bSopenharmony_ci if (META_NS::GetValue(Status()) != SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED) { 10818bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED); 10828bf80f4bSopenharmony_ci } 10838bf80f4bSopenharmony_ci 10848bf80f4bSopenharmony_ci if (!bound_) { 10858bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("%s: all children completed", META_NS::GetValue(Name()).c_str()); 10868bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(OnBound()); 10878bf80f4bSopenharmony_ci } 10888bf80f4bSopenharmony_ci 10898bf80f4bSopenharmony_ci bound_ = true; 10908bf80f4bSopenharmony_ci} 10918bf80f4bSopenharmony_ci 10928bf80f4bSopenharmony_ciBASE_NS::Math::Mat4X4 NodeImpl::GetGlobalTransform() const 10938bf80f4bSopenharmony_ci{ 10948bf80f4bSopenharmony_ci auto ret = BASE_NS::Math::IDENTITY_4X4; 10958bf80f4bSopenharmony_ci BASE_NS::vector<META_NS::IContainable::Ptr> nodes; 10968bf80f4bSopenharmony_ci nodes.push_back(GetSelf<META_NS::IContainable>()); 10978bf80f4bSopenharmony_ci auto current = nodes.back()->GetParent(); 10988bf80f4bSopenharmony_ci while (auto containable = interface_pointer_cast<META_NS::IContainable>(current)) { 10998bf80f4bSopenharmony_ci nodes.push_back(containable); 11008bf80f4bSopenharmony_ci current = nodes.back()->GetParent(); 11018bf80f4bSopenharmony_ci } 11028bf80f4bSopenharmony_ci 11038bf80f4bSopenharmony_ci for (size_t ix = nodes.size(); ix != 0; ix--) { 11048bf80f4bSopenharmony_ci ret = ret * META_NS::GetValue(interface_pointer_cast<INode>(nodes[ix - 1])->LocalMatrix()); 11058bf80f4bSopenharmony_ci } 11068bf80f4bSopenharmony_ci 11078bf80f4bSopenharmony_ci return ret; 11088bf80f4bSopenharmony_ci} 11098bf80f4bSopenharmony_ci 11108bf80f4bSopenharmony_civoid NodeImpl::SetGlobalTransform(const BASE_NS::Math::Mat4X4& mat) 11118bf80f4bSopenharmony_ci{ 11128bf80f4bSopenharmony_ci auto global = BASE_NS::Math::IDENTITY_4X4; 11138bf80f4bSopenharmony_ci BASE_NS::vector<META_NS::IContainable::Ptr> nodes; 11148bf80f4bSopenharmony_ci nodes.push_back(GetSelf<META_NS::IContainable>()); 11158bf80f4bSopenharmony_ci 11168bf80f4bSopenharmony_ci auto current = nodes.back()->GetParent(); 11178bf80f4bSopenharmony_ci while (auto containable = interface_pointer_cast<META_NS::IContainable>(current)) { 11188bf80f4bSopenharmony_ci nodes.push_back(containable); 11198bf80f4bSopenharmony_ci current = nodes.back()->GetParent(); 11208bf80f4bSopenharmony_ci } 11218bf80f4bSopenharmony_ci 11228bf80f4bSopenharmony_ci for (size_t ix = nodes.size(); ix != 1; ix--) { 11238bf80f4bSopenharmony_ci global = global * META_NS::GetValue(interface_pointer_cast<INode>(nodes[ix - 1])->LocalMatrix()); 11248bf80f4bSopenharmony_ci } 11258bf80f4bSopenharmony_ci 11268bf80f4bSopenharmony_ci // META_NS::SetValue(LocalMatrix(), mat / global); 11278bf80f4bSopenharmony_ci auto newLocal = BASE_NS::Math::Inverse(global) * mat; 11288bf80f4bSopenharmony_ci BASE_NS::Math::Quat rotation; 11298bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 scale; 11308bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 translate; 11318bf80f4bSopenharmony_ci BASE_NS::Math::Vec3 skew; 11328bf80f4bSopenharmony_ci BASE_NS::Math::Vec4 persp; 11338bf80f4bSopenharmony_ci if (BASE_NS::Math::Decompose(newLocal, scale, rotation, translate, skew, persp)) { 11348bf80f4bSopenharmony_ci META_NS::SetValue(Scale(), scale); 11358bf80f4bSopenharmony_ci META_NS::SetValue(Rotation(), rotation); 11368bf80f4bSopenharmony_ci META_NS::SetValue(Position(), translate); 11378bf80f4bSopenharmony_ci } 11388bf80f4bSopenharmony_ci} 11398bf80f4bSopenharmony_ci 11408bf80f4bSopenharmony_civoid NodeImpl::MonitorChild(SCENE_NS::INode::Ptr node) 11418bf80f4bSopenharmony_ci{ 11428bf80f4bSopenharmony_ci for (auto& child : monitored_) { 11438bf80f4bSopenharmony_ci if (*child == node) { 11448bf80f4bSopenharmony_ci return; 11458bf80f4bSopenharmony_ci } 11468bf80f4bSopenharmony_ci } 11478bf80f4bSopenharmony_ci 11488bf80f4bSopenharmony_ci monitored_.emplace_back(NodeMonitor::Create(node, *this)); 11498bf80f4bSopenharmony_ci bound_ = false; 11508bf80f4bSopenharmony_ci} 11518bf80f4bSopenharmony_ci 11528bf80f4bSopenharmony_civoid NodeImpl::SetMeshToEngine() 11538bf80f4bSopenharmony_ci{ 11548bf80f4bSopenharmony_ci if (auto mesh = META_NS::GetValue(Mesh())) { 11558bf80f4bSopenharmony_ci if (auto ecsObject = interface_pointer_cast<SCENE_NS::IEcsObject>(mesh)) { 11568bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 11578bf80f4bSopenharmony_ci scene->AddEngineTask( 11588bf80f4bSopenharmony_ci MakeTask( 11598bf80f4bSopenharmony_ci [](const auto self, const auto meshObject) { 11608bf80f4bSopenharmony_ci if (auto sceneHolder = static_cast<NodeImpl*>(self.get())->SceneHolder()) { 11618bf80f4bSopenharmony_ci sceneHolder->SetMesh(self->GetEntity(), meshObject->GetEntity()); 11628bf80f4bSopenharmony_ci } 11638bf80f4bSopenharmony_ci return false; 11648bf80f4bSopenharmony_ci }, 11658bf80f4bSopenharmony_ci GetSelf<SCENE_NS::IEcsObject>(), interface_pointer_cast<SCENE_NS::IEcsObject>(mesh)), 11668bf80f4bSopenharmony_ci false); 11678bf80f4bSopenharmony_ci } 11688bf80f4bSopenharmony_ci } 11698bf80f4bSopenharmony_ci } 11708bf80f4bSopenharmony_ci} 11718bf80f4bSopenharmony_ci 11728bf80f4bSopenharmony_civoid NodeImpl::SetMesh(SCENE_NS::IMesh::Ptr mesh) 11738bf80f4bSopenharmony_ci{ 11748bf80f4bSopenharmony_ci if (mesh == META_NS::GetValue(Mesh())) { 11758bf80f4bSopenharmony_ci return; // the matching mesh is already set 11768bf80f4bSopenharmony_ci } 11778bf80f4bSopenharmony_ci 11788bf80f4bSopenharmony_ci META_NS::SetValue(Mesh(), mesh); 11798bf80f4bSopenharmony_ci} 11808bf80f4bSopenharmony_ci 11818bf80f4bSopenharmony_ciSCENE_NS::IMultiMeshProxy::Ptr NodeImpl::CreateMeshProxy(size_t count, SCENE_NS::IMesh::Ptr mesh) 11828bf80f4bSopenharmony_ci{ 11838bf80f4bSopenharmony_ci // SCENE_NS::IMultiMeshProxy::Ptr ret { SCENE_NS::MultiMeshProxy() }; 11848bf80f4bSopenharmony_ci SCENE_NS::IMultiMeshProxy::Ptr ret = 11858bf80f4bSopenharmony_ci GetObjectRegistry().Create<SCENE_NS::IMultiMeshProxy>(SCENE_NS::ClassId::MultiMeshProxy); 11868bf80f4bSopenharmony_ci 11878bf80f4bSopenharmony_ci interface_cast<IMultimeshInitilization>(ret)->Initialize(SceneHolder(), count, EcsObject()->GetEntity()); 11888bf80f4bSopenharmony_ci 11898bf80f4bSopenharmony_ci if (mesh) { 11908bf80f4bSopenharmony_ci ret->Mesh()->SetValue(mesh); 11918bf80f4bSopenharmony_ci } 11928bf80f4bSopenharmony_ci 11938bf80f4bSopenharmony_ci // return 11948bf80f4bSopenharmony_ci SetMultiMeshProxy(ret); 11958bf80f4bSopenharmony_ci return ret; 11968bf80f4bSopenharmony_ci} 11978bf80f4bSopenharmony_ci 11988bf80f4bSopenharmony_civoid NodeImpl::SetMultiMeshProxy(SCENE_NS::IMultiMeshProxy::Ptr multimesh) 11998bf80f4bSopenharmony_ci{ 12008bf80f4bSopenharmony_ci multimesh_ = multimesh; 12018bf80f4bSopenharmony_ci} 12028bf80f4bSopenharmony_ci 12038bf80f4bSopenharmony_ciSCENE_NS::IMultiMeshProxy::Ptr NodeImpl::GetMultiMeshProxy() const 12048bf80f4bSopenharmony_ci{ 12058bf80f4bSopenharmony_ci return multimesh_; 12068bf80f4bSopenharmony_ci} 12078bf80f4bSopenharmony_ci 12088bf80f4bSopenharmony_civoid NodeImpl::ReleaseEntityOwnership() 12098bf80f4bSopenharmony_ci{ 12108bf80f4bSopenharmony_ci if (!ecsObject_) { 12118bf80f4bSopenharmony_ci return; 12128bf80f4bSopenharmony_ci } 12138bf80f4bSopenharmony_ci 12148bf80f4bSopenharmony_ci auto entity = ecsObject_->GetEntity(); 12158bf80f4bSopenharmony_ci if (!CORE_NS::EntityUtil::IsValid(entity)) { 12168bf80f4bSopenharmony_ci return; 12178bf80f4bSopenharmony_ci } 12188bf80f4bSopenharmony_ci 12198bf80f4bSopenharmony_ci auto sh = SceneHolder(); 12208bf80f4bSopenharmony_ci if (sh) { 12218bf80f4bSopenharmony_ci auto attachments = ecsObject_->GetAttachments(); 12228bf80f4bSopenharmony_ci for (auto attachment : attachments) { 12238bf80f4bSopenharmony_ci ecsObject_->RemoveAttachment(attachment); 12248bf80f4bSopenharmony_ci } 12258bf80f4bSopenharmony_ci } 12268bf80f4bSopenharmony_ci 12278bf80f4bSopenharmony_ci if (sh) { 12288bf80f4bSopenharmony_ci sh->SetEntityActive(entity, true); 12298bf80f4bSopenharmony_ci 12308bf80f4bSopenharmony_ci if (ownsEntity_) { 12318bf80f4bSopenharmony_ci sh->DestroyEntity(entity); 12328bf80f4bSopenharmony_ci } 12338bf80f4bSopenharmony_ci 12348bf80f4bSopenharmony_ci SetEntity(ecsObject_->GetEcs(), {}); 12358bf80f4bSopenharmony_ci } 12368bf80f4bSopenharmony_ci} 12378bf80f4bSopenharmony_ci 12388bf80f4bSopenharmony_civoid NodeImpl::Destroy() 12398bf80f4bSopenharmony_ci{ 12408bf80f4bSopenharmony_ci UnsubscribeFromNameChanges(); 12418bf80f4bSopenharmony_ci 12428bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().Purge(); 12438bf80f4bSopenharmony_ci 12448bf80f4bSopenharmony_ci if (Name()) { 12458bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG( 12468bf80f4bSopenharmony_ci "Tearing down: %s%s", META_NS::GetValue(Path()).c_str(), META_NS::GetValue(Name()).c_str()); 12478bf80f4bSopenharmony_ci if (auto ecss = ecsScene_.lock()) { 12488bf80f4bSopenharmony_ci ecss->CancelEngineTask(initializeTaskToken_); 12498bf80f4bSopenharmony_ci } 12508bf80f4bSopenharmony_ci } 12518bf80f4bSopenharmony_ci 12528bf80f4bSopenharmony_ci ReleaseEntityOwnership(); 12538bf80f4bSopenharmony_ci Fwd::Destroy(); 12548bf80f4bSopenharmony_ci} 12558bf80f4bSopenharmony_ci 12568bf80f4bSopenharmony_ciSCENE_NS::IPickingResult::Ptr NodeImpl::GetWorldMatrixComponentAABB(bool isRecursive) const 12578bf80f4bSopenharmony_ci{ 12588bf80f4bSopenharmony_ci auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request); 12598bf80f4bSopenharmony_ci if (ret && SceneHolder()) { 12608bf80f4bSopenharmony_ci SceneHolder()->QueueEngineTask( 12618bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::ITaskQueueTask>([isRecursive, weakRet = BASE_NS::weak_ptr(ret), 12628bf80f4bSopenharmony_ci weakSh = sceneHolder_, 12638bf80f4bSopenharmony_ci weakSelf = BASE_NS::weak_ptr(ecsObject_)]() { 12648bf80f4bSopenharmony_ci if (auto sh = weakSh.lock()) { 12658bf80f4bSopenharmony_ci if (auto ret = weakRet.lock()) { 12668bf80f4bSopenharmony_ci if (auto self = weakSelf.lock()) { 12678bf80f4bSopenharmony_ci if (sh->GetWorldMatrixComponentAABB(ret, self->GetEntity(), isRecursive)) { 12688bf80f4bSopenharmony_ci sh->QueueApplicationTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() { 12698bf80f4bSopenharmony_ci if (auto writable = 12708bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>( 12718bf80f4bSopenharmony_ci weakRet)) { 12728bf80f4bSopenharmony_ci writable->MarkReady(); 12738bf80f4bSopenharmony_ci } 12748bf80f4bSopenharmony_ci return false; 12758bf80f4bSopenharmony_ci }), 12768bf80f4bSopenharmony_ci false); 12778bf80f4bSopenharmony_ci } 12788bf80f4bSopenharmony_ci } 12798bf80f4bSopenharmony_ci } 12808bf80f4bSopenharmony_ci } 12818bf80f4bSopenharmony_ci return false; 12828bf80f4bSopenharmony_ci }), 12838bf80f4bSopenharmony_ci false); 12848bf80f4bSopenharmony_ci return ret; 12858bf80f4bSopenharmony_ci } 12868bf80f4bSopenharmony_ci return SCENE_NS::IPickingResult::Ptr(); 12878bf80f4bSopenharmony_ci} 12888bf80f4bSopenharmony_ci 12898bf80f4bSopenharmony_ciSCENE_NS::IPickingResult::Ptr NodeImpl::GetTransformComponentAABB(bool isRecursive) const 12908bf80f4bSopenharmony_ci{ 12918bf80f4bSopenharmony_ci auto ret = objectRegistry_->Create<SCENE_NS::IPickingResult>(SCENE_NS::ClassId::PendingVec3Request); 12928bf80f4bSopenharmony_ci if (ret && SceneHolder()) { 12938bf80f4bSopenharmony_ci SceneHolder()->QueueEngineTask( 12948bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::ITaskQueueTask>([isRecursive, weakRet = BASE_NS::weak_ptr(ret), 12958bf80f4bSopenharmony_ci weakSh = sceneHolder_, 12968bf80f4bSopenharmony_ci weakSelf = BASE_NS::weak_ptr(ecsObject_)]() { 12978bf80f4bSopenharmony_ci if (auto sh = weakSh.lock()) { 12988bf80f4bSopenharmony_ci if (auto ret = weakRet.lock()) { 12998bf80f4bSopenharmony_ci if (auto self = weakSelf.lock()) { 13008bf80f4bSopenharmony_ci if (sh->GetTransformComponentAABB(ret, self->GetEntity(), isRecursive)) { 13018bf80f4bSopenharmony_ci sh->QueueApplicationTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>([weakRet]() { 13028bf80f4bSopenharmony_ci if (auto writable = 13038bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::IPendingRequestData<BASE_NS::Math::Vec3>>( 13048bf80f4bSopenharmony_ci weakRet)) { 13058bf80f4bSopenharmony_ci writable->MarkReady(); 13068bf80f4bSopenharmony_ci } 13078bf80f4bSopenharmony_ci return false; 13088bf80f4bSopenharmony_ci }), 13098bf80f4bSopenharmony_ci false); 13108bf80f4bSopenharmony_ci } 13118bf80f4bSopenharmony_ci } 13128bf80f4bSopenharmony_ci } 13138bf80f4bSopenharmony_ci } 13148bf80f4bSopenharmony_ci return false; 13158bf80f4bSopenharmony_ci }), 13168bf80f4bSopenharmony_ci false); 13178bf80f4bSopenharmony_ci return ret; 13188bf80f4bSopenharmony_ci } 13198bf80f4bSopenharmony_ci return SCENE_NS::IPickingResult::Ptr(); 13208bf80f4bSopenharmony_ci} 13218bf80f4bSopenharmony_ci 13228bf80f4bSopenharmony_civoid NodeImpl::SetStatus(SCENE_NS::INode::NodeStatus status) 13238bf80f4bSopenharmony_ci{ 13248bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Status)->SetValue(status); 13258bf80f4bSopenharmony_ci} 13268bf80f4bSopenharmony_ci/* 13278bf80f4bSopenharmony_cibool NodeImpl::Export( 13288bf80f4bSopenharmony_ci META_NS::Serialization::IExportContext& context, META_NS::Serialization::ClassPrimitive& value) const 13298bf80f4bSopenharmony_ci{ 13308bf80f4bSopenharmony_ci if (!ShouldExport()) { 13318bf80f4bSopenharmony_ci return false; 13328bf80f4bSopenharmony_ci } 13338bf80f4bSopenharmony_ci 13348bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("NodeImpl::%s %s", __func__, Name()->Get().c_str()); 13358bf80f4bSopenharmony_ci return Fwd::Export(context, value); 13368bf80f4bSopenharmony_ci} 13378bf80f4bSopenharmony_ci*/ 13388bf80f4bSopenharmony_civoid NodeImpl::SetSuperInstance(const IObject::Ptr& aggr, const IObject::Ptr& super) 13398bf80f4bSopenharmony_ci{ 13408bf80f4bSopenharmony_ci Fwd::SetSuperInstance(aggr, super); 13418bf80f4bSopenharmony_ci containable_ = interface_cast<IContainable>(super); 13428bf80f4bSopenharmony_ci mutableContainable_ = interface_cast<IMutableContainable>(super); 13438bf80f4bSopenharmony_ci} 13448bf80f4bSopenharmony_ci 13458bf80f4bSopenharmony_civoid NodeImpl::SetParent(const IObject::Ptr& parent) 13468bf80f4bSopenharmony_ci{ 13478bf80f4bSopenharmony_ci if (mutableContainable_) { 13488bf80f4bSopenharmony_ci mutableContainable_->SetParent(parent); 13498bf80f4bSopenharmony_ci } else { 13508bf80f4bSopenharmony_ci parent_ = parent; 13518bf80f4bSopenharmony_ci } 13528bf80f4bSopenharmony_ci} 13538bf80f4bSopenharmony_ci 13548bf80f4bSopenharmony_ciMETA_NS::IObject::Ptr NodeImpl::GetParent() const 13558bf80f4bSopenharmony_ci{ 13568bf80f4bSopenharmony_ci if (containable_) { 13578bf80f4bSopenharmony_ci return containable_->GetParent(); 13588bf80f4bSopenharmony_ci } 13598bf80f4bSopenharmony_ci 13608bf80f4bSopenharmony_ci auto parent = parent_.lock(); 13618bf80f4bSopenharmony_ci if (parent) { 13628bf80f4bSopenharmony_ci return parent; 13638bf80f4bSopenharmony_ci } 13648bf80f4bSopenharmony_ci 13658bf80f4bSopenharmony_ci return {}; 13668bf80f4bSopenharmony_ci} 13678bf80f4bSopenharmony_ci 13688bf80f4bSopenharmony_ciSCENE_NS::IMesh::Ptr NodeImpl::GetMesh() const 13698bf80f4bSopenharmony_ci{ 13708bf80f4bSopenharmony_ci return META_NS::GetValue(Mesh()); 13718bf80f4bSopenharmony_ci} 13728bf80f4bSopenharmony_ci 13738bf80f4bSopenharmony_civoid NodeImpl::InitializeMesh( 13748bf80f4bSopenharmony_ci const SCENE_NS::IMesh::Ptr& mesh, const BASE_NS::shared_ptr<NodeImpl>& node, const BASE_NS::string_view entityName) 13758bf80f4bSopenharmony_ci{ 13768bf80f4bSopenharmony_ci auto scene = node->EcsScene(); 13778bf80f4bSopenharmony_ci if (auto ecsObject = META_NS::GetObjectRegistry().Create<SCENE_NS::IEcsObject>(SCENE_NS::ClassId::EcsObject)) { 13788bf80f4bSopenharmony_ci if (auto privateInit = interface_cast<INodeEcsInterfacePrivate>(mesh)) { 13798bf80f4bSopenharmony_ci privateInit->Initialize(scene, ecsObject, {}, "", BASE_NS::string(entityName), node->SceneHolder(), {}); 13808bf80f4bSopenharmony_ci } 13818bf80f4bSopenharmony_ci } 13828bf80f4bSopenharmony_ci} 13838bf80f4bSopenharmony_ci 13848bf80f4bSopenharmony_civoid NodeImpl::InitializeMesh(const SCENE_NS::IMesh::Ptr& mesh, const BASE_NS::shared_ptr<SCENE_NS::IEcsObject>& self) 13858bf80f4bSopenharmony_ci{ 13868bf80f4bSopenharmony_ci auto strongMe = interface_pointer_cast<IObject>(self); 13878bf80f4bSopenharmony_ci if (auto node = static_pointer_cast<NodeImpl>(strongMe)) { 13888bf80f4bSopenharmony_ci if (auto sceneHolder = node->SceneHolder()) { 13898bf80f4bSopenharmony_ci auto entityName = sceneHolder->GetMeshName(self->GetEntity()); 13908bf80f4bSopenharmony_ci if (!entityName.empty()) { 13918bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask(MakeTask( 13928bf80f4bSopenharmony_ci [entityName, mesh](auto selfObject) { 13938bf80f4bSopenharmony_ci if (auto node = static_pointer_cast<NodeImpl>(selfObject)) { 13948bf80f4bSopenharmony_ci InitializeMesh(mesh, node, entityName); 13958bf80f4bSopenharmony_ci } 13968bf80f4bSopenharmony_ci return false; 13978bf80f4bSopenharmony_ci }, 13988bf80f4bSopenharmony_ci strongMe), 13998bf80f4bSopenharmony_ci false); 14008bf80f4bSopenharmony_ci } 14018bf80f4bSopenharmony_ci } 14028bf80f4bSopenharmony_ci } 14038bf80f4bSopenharmony_ci} 14048bf80f4bSopenharmony_ci 14058bf80f4bSopenharmony_ciSCENE_NS::IMesh::Ptr NodeImpl::GetMeshFromEngine() 14068bf80f4bSopenharmony_ci{ 14078bf80f4bSopenharmony_ci SCENE_NS::IMesh::Ptr ret {}; 14088bf80f4bSopenharmony_ci if (auto iscene = GetScene()) { 14098bf80f4bSopenharmony_ci if (META_NS::GetValue(iscene->Asynchronous()) == false) { 14108bf80f4bSopenharmony_ci auto entityName = SceneHolder()->GetMeshName(EcsObject()->GetEntity()); 14118bf80f4bSopenharmony_ci if (!entityName.empty()) { 14128bf80f4bSopenharmony_ci ret = iscene->GetMesh(entityName); 14138bf80f4bSopenharmony_ci } 14148bf80f4bSopenharmony_ci } 14158bf80f4bSopenharmony_ci } 14168bf80f4bSopenharmony_ci 14178bf80f4bSopenharmony_ci if (!ret) { 14188bf80f4bSopenharmony_ci ret = GetObjectRegistry().Create<SCENE_NS::IMesh>(SCENE_NS::ClassId::Mesh); 14198bf80f4bSopenharmony_ci 14208bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 14218bf80f4bSopenharmony_ci scene->AddEngineTask(MakeTask( 14228bf80f4bSopenharmony_ci [ret](auto selfObject) { 14238bf80f4bSopenharmony_ci if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfObject)) { 14248bf80f4bSopenharmony_ci InitializeMesh(ret, self); 14258bf80f4bSopenharmony_ci } 14268bf80f4bSopenharmony_ci return false; 14278bf80f4bSopenharmony_ci }, 14288bf80f4bSopenharmony_ci GetSelf()), 14298bf80f4bSopenharmony_ci false); 14308bf80f4bSopenharmony_ci } 14318bf80f4bSopenharmony_ci } 14328bf80f4bSopenharmony_ci if (auto node = interface_cast<SCENE_NS::INode>(ret)) { 14338bf80f4bSopenharmony_ci if (META_NS::GetValue(node->Status()) != SCENE_NS::INode::NODE_STATUS_DISCONNECTED) { 14348bf80f4bSopenharmony_ci META_NS::SetValue(Mesh(), ret); 14358bf80f4bSopenharmony_ci } 14368bf80f4bSopenharmony_ci } 14378bf80f4bSopenharmony_ci 14388bf80f4bSopenharmony_ci return ret; 14398bf80f4bSopenharmony_ci} 14408bf80f4bSopenharmony_ci 14418bf80f4bSopenharmony_ciusing PropertyNameCriteria = BASE_NS::unordered_map<BASE_NS::string_view, BASE_NS::vector<BASE_NS::string_view>>; 14428bf80f4bSopenharmony_ciPropertyNameCriteria& NodeImpl::PropertyNameMask() 14438bf80f4bSopenharmony_ci{ 14448bf80f4bSopenharmony_ci return ecs_property_names_; 14458bf80f4bSopenharmony_ci} 14468bf80f4bSopenharmony_ci 14478bf80f4bSopenharmony_ciMETA_NS::IObject::Ptr NodeImpl::Resolve(const META_NS::RefUri& uri) const 14488bf80f4bSopenharmony_ci{ 14498bf80f4bSopenharmony_ci auto p = Super::Resolve(uri); 14508bf80f4bSopenharmony_ci if (p) { 14518bf80f4bSopenharmony_ci return p; 14528bf80f4bSopenharmony_ci } 14538bf80f4bSopenharmony_ci 14548bf80f4bSopenharmony_ci INode::Ptr current = GetSelf<INode>(); 14558bf80f4bSopenharmony_ci 14568bf80f4bSopenharmony_ci META_NS::RefUri ref { uri.RelativeUri() }; 14578bf80f4bSopenharmony_ci if (ref.IsEmpty()) { 14588bf80f4bSopenharmony_ci return interface_pointer_cast<META_NS::IObject>(current); 14598bf80f4bSopenharmony_ci } 14608bf80f4bSopenharmony_ci 14618bf80f4bSopenharmony_ci if (ref.StartsFromRoot()) { 14628bf80f4bSopenharmony_ci ref.SetStartsFromRoot(false); 14638bf80f4bSopenharmony_ci auto obj = interface_pointer_cast<META_NS::IObject>(GetScene()->RootNode()->GetValue()); 14648bf80f4bSopenharmony_ci return obj ? obj->Resolve(BASE_NS::move(ref)) : nullptr; 14658bf80f4bSopenharmony_ci } 14668bf80f4bSopenharmony_ci 14678bf80f4bSopenharmony_ci return {}; // ResolveSegment(current, BASE_NS::move(ref)); 14688bf80f4bSopenharmony_ci} 14698bf80f4bSopenharmony_ci 14708bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 14718bf80f4bSopenharmony_civoid RegisterNodeImpl() 14728bf80f4bSopenharmony_ci{ 14738bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().RegisterObjectType<NodeImpl>(); 14748bf80f4bSopenharmony_ci} 14758bf80f4bSopenharmony_civoid UnregisterNodeImpl() 14768bf80f4bSopenharmony_ci{ 14778bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().UnregisterObjectType<NodeImpl>(); 14788bf80f4bSopenharmony_ci} 14798bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 1480