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 <scene_plugin/api/material_uid.h> 168bf80f4bSopenharmony_ci#include <scene_plugin/api/mesh_uid.h> 178bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_material.h> 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <meta/ext/concrete_base_object.h> 208bf80f4bSopenharmony_ci#include <meta/ext/implementation_macros.h> 218bf80f4bSopenharmony_ci 228bf80f4bSopenharmony_ci#include "bind_templates.inl" 238bf80f4bSopenharmony_ci#include "intf_submesh_bridge.h" 248bf80f4bSopenharmony_ci#include "node_impl.h" 258bf80f4bSopenharmony_ci#include "submesh_handler_uid.h" 268bf80f4bSopenharmony_ci#include "task_utils.h" 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask; 298bf80f4bSopenharmony_ci#include "intf_submesh_bridge.h" 308bf80f4bSopenharmony_ci 318bf80f4bSopenharmony_cinamespace { 328bf80f4bSopenharmony_ciclass MeshImpl 338bf80f4bSopenharmony_ci : public META_NS::ConcreteBaseMetaObjectFwd<MeshImpl, NodeImpl, SCENE_NS::ClassId::Mesh, SCENE_NS::IMesh> { 348bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view MESH_COMPONENT_NAME = "MeshComponent"; 358bf80f4bSopenharmony_ci static constexpr size_t MESH_COMPONENT_NAME_LEN = MESH_COMPONENT_NAME.size() + 1; 368bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view MESH_AABBMIN = "MeshComponent.aabbMin"; 378bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view MESH_AABBMAX = "MeshComponent.aabbMax"; 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ci bool Build(const IMetadata::Ptr& data) override 408bf80f4bSopenharmony_ci { 418bf80f4bSopenharmony_ci bool ret = false; 428bf80f4bSopenharmony_ci if (ret = NodeImpl::Build(data); ret) { 438bf80f4bSopenharmony_ci PropertyNameMask()[MESH_COMPONENT_NAME] = { MESH_AABBMIN.substr(MESH_COMPONENT_NAME_LEN), 448bf80f4bSopenharmony_ci MESH_AABBMAX.substr(MESH_COMPONENT_NAME_LEN) }; 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_ci // subscribe material changes 478bf80f4bSopenharmony_ci MaterialOverride()->OnChanged()->AddHandler( 488bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::IOnChanged>([this]() { SyncMaterialOverrideToSubmeshes(); })); 498bf80f4bSopenharmony_ci } 508bf80f4bSopenharmony_ci return ret; 518bf80f4bSopenharmony_ci } 528bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY( 538bf80f4bSopenharmony_ci SCENE_NS::IMesh, SCENE_NS::IMaterial::Ptr, MaterialOverride, {}, ) 548bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(SCENE_NS::IMesh, BASE_NS::string, MaterialOverrideUri, {}, 558bf80f4bSopenharmony_ci META_NS::DEFAULT_PROPERTY_FLAGS | META_NS::ObjectFlagBits::INTERNAL) 568bf80f4bSopenharmony_ci 578bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_ARRAY_PROPERTY( 588bf80f4bSopenharmony_ci SCENE_NS::IMesh, SCENE_NS::ISubMesh::Ptr, SubMeshes, {}, ) 598bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(SCENE_NS::IMesh, BASE_NS::Math::Vec3, AABBMin, 608bf80f4bSopenharmony_ci BASE_NS::Math::Vec3(0.f, 0.f, 0.f), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER) 618bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(SCENE_NS::IMesh, BASE_NS::Math::Vec3, AABBMax, 628bf80f4bSopenharmony_ci BASE_NS::Math::Vec3(0.f, 0.f, 0.f), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER) 638bf80f4bSopenharmony_ci 648bf80f4bSopenharmony_ci void SyncMaterialOverrideToSubmeshes() 658bf80f4bSopenharmony_ci { 668bf80f4bSopenharmony_ci auto material = MaterialOverride()->GetValue(); 678bf80f4bSopenharmony_ci if (material) { 688bf80f4bSopenharmony_ci 698bf80f4bSopenharmony_ci for (auto& submesh : SubMeshes()->GetValue()) { 708bf80f4bSopenharmony_ci auto submeshPrivate = interface_cast<SCENE_NS::ISubMeshPrivate>(submesh); 718bf80f4bSopenharmony_ci if (submeshPrivate) { 728bf80f4bSopenharmony_ci submeshPrivate->SetOverrideMaterial(material); 738bf80f4bSopenharmony_ci } 748bf80f4bSopenharmony_ci } 758bf80f4bSopenharmony_ci } else { 768bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(MaterialOverrideUri)->SetValue({}); 778bf80f4bSopenharmony_ci // Reset submeshes back to original value. 788bf80f4bSopenharmony_ci for (auto& submesh : SubMeshes()->GetValue()) { 798bf80f4bSopenharmony_ci auto submeshPrivate = interface_cast<SCENE_NS::ISubMeshPrivate>(submesh); 808bf80f4bSopenharmony_ci if (submeshPrivate) { 818bf80f4bSopenharmony_ci submeshPrivate->SetOverrideMaterial({}); 828bf80f4bSopenharmony_ci } 838bf80f4bSopenharmony_ci } 848bf80f4bSopenharmony_ci } 858bf80f4bSopenharmony_ci } 868bf80f4bSopenharmony_ci 878bf80f4bSopenharmony_ci bool CompleteInitialization(const BASE_NS::string& path) override 888bf80f4bSopenharmony_ci { 898bf80f4bSopenharmony_ci if (!NodeImpl::CompleteInitialization(path)) { 908bf80f4bSopenharmony_ci return false; 918bf80f4bSopenharmony_ci } 928bf80f4bSopenharmony_ci 938bf80f4bSopenharmony_ci // Ensure override material is connected to ecs. 948bf80f4bSopenharmony_ci auto overrideMaterial = GetValue(MaterialOverride()); 958bf80f4bSopenharmony_ci if (overrideMaterial) { 968bf80f4bSopenharmony_ci BindObject(interface_pointer_cast<INode>(overrideMaterial)); 978bf80f4bSopenharmony_ci } 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_ci // Ensure submesh materials are connected to ecs. 1008bf80f4bSopenharmony_ci auto submeshes = META_ACCESS_PROPERTY(SubMeshes)->GetValue(); 1018bf80f4bSopenharmony_ci for (auto i = 0; i < submeshes.size(); ++i) { 1028bf80f4bSopenharmony_ci auto submesh = submeshes.at(i); 1038bf80f4bSopenharmony_ci auto material = META_NS::GetValue(submesh->Material()); 1048bf80f4bSopenharmony_ci if (material) { 1058bf80f4bSopenharmony_ci BindObject(interface_pointer_cast<INode>(material)); 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci } 1088bf80f4bSopenharmony_ci 1098bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 1108bf80f4bSopenharmony_ci BindChanges(propHandler_, META_ACCESS_PROPERTY(AABBMin), meta, MESH_AABBMIN); 1118bf80f4bSopenharmony_ci BindChanges(propHandler_, META_ACCESS_PROPERTY(AABBMax), meta, MESH_AABBMAX); 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ci if (auto ecs = EcsScene()->GetEcs()) { 1148bf80f4bSopenharmony_ci submeshHandler_ = GetObjectRegistry().Create<SCENE_NS::ISubMeshBridge>(SCENE_NS::ClassId::SubMeshHandler); 1158bf80f4bSopenharmony_ci submeshHandler_->Initialize(CORE_NS::GetManager<CORE3D_NS::IMeshComponentManager>(*ecs), 1168bf80f4bSopenharmony_ci EcsObject()->GetEntity(), META_ACCESS_PROPERTY(SubMeshes), GetSelf<INodeEcsInterfacePrivate>()); 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci 1198bf80f4bSopenharmony_ci // Ok, the initialization has reached the point where we have a scene and ecs initialized 1208bf80f4bSopenharmony_ci // check if we have material URIs that should be progressed before we sync the status with ecs 1218bf80f4bSopenharmony_ci auto materialOverrideUri = MaterialOverrideUri()->GetValue(); 1228bf80f4bSopenharmony_ci if (!materialOverrideUri.empty()) { 1238bf80f4bSopenharmony_ci SCENE_NS::IMaterial::Ptr material = GetScene()->GetMaterial(materialOverrideUri); 1248bf80f4bSopenharmony_ci if (material) { 1258bf80f4bSopenharmony_ci MaterialOverride()->SetValue(material); 1268bf80f4bSopenharmony_ci } 1278bf80f4bSopenharmony_ci } 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci // Update material override. 1308bf80f4bSopenharmony_ci SyncMaterialOverrideToSubmeshes(); 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_ci // Also restore submesh materials. 1338bf80f4bSopenharmony_ci for (auto i = 0; i < submeshes.size(); ++i) { 1348bf80f4bSopenharmony_ci auto submesh = submeshes.at(i); 1358bf80f4bSopenharmony_ci auto materialUri = META_NS::GetValue(submesh->MaterialUri()); 1368bf80f4bSopenharmony_ci if (!materialUri.empty()) { 1378bf80f4bSopenharmony_ci submesh->Material()->SetValue(GetScene()->GetMaterial(materialUri)); 1388bf80f4bSopenharmony_ci } 1398bf80f4bSopenharmony_ci } 1408bf80f4bSopenharmony_ci return true; 1418bf80f4bSopenharmony_ci } 1428bf80f4bSopenharmony_ci 1438bf80f4bSopenharmony_ci void SetPath(const BASE_NS::string& path, const BASE_NS::string& name, CORE_NS::Entity entity) override 1448bf80f4bSopenharmony_ci { 1458bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Path)->SetValue(path); 1468bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Name)->SetValue(name); 1478bf80f4bSopenharmony_ci 1488bf80f4bSopenharmony_ci if (auto iscene = GetScene()) { 1498bf80f4bSopenharmony_ci iscene->UpdateCachedReference(GetSelf<SCENE_NS::INode>()); 1508bf80f4bSopenharmony_ci } 1518bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 1528bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTING); 1538bf80f4bSopenharmony_ci initializeTaskToken_ = scene->AddEngineTask( 1548bf80f4bSopenharmony_ci MakeTask( 1558bf80f4bSopenharmony_ci [name, fullpath = path + name](auto selfObject) { 1568bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 1578bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 1588bf80f4bSopenharmony_ci CORE_NS::Entity meshEntinty {}; 1598bf80f4bSopenharmony_ci if (sceneHolder->FindMesh(name, fullpath, meshEntinty)) { 1608bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("binding mesh: %s", name.c_str()); 1618bf80f4bSopenharmony_ci if (auto proxyIf = 1628bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::IEcsProxyObject>(self->EcsObject())) { 1638bf80f4bSopenharmony_ci proxyIf->SetCommonListener(sceneHolder->GetCommonEcsListener()); 1648bf80f4bSopenharmony_ci } 1658bf80f4bSopenharmony_ci self->EcsObject()->DefineTargetProperties(self->PropertyNameMask()); 1668bf80f4bSopenharmony_ci self->EcsObject()->SetEntity(sceneHolder->GetEcs(), meshEntinty); 1678bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 1688bf80f4bSopenharmony_ci MakeTask( 1698bf80f4bSopenharmony_ci [name](auto selfObject) { 1708bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 1718bf80f4bSopenharmony_ci self->CompleteInitialization(name); 1728bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTED); 1738bf80f4bSopenharmony_ci if (auto node = 1748bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::INode>(selfObject)) { 1758bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(node->OnLoaded()); 1768bf80f4bSopenharmony_ci } 1778bf80f4bSopenharmony_ci } 1788bf80f4bSopenharmony_ci return false; 1798bf80f4bSopenharmony_ci }, 1808bf80f4bSopenharmony_ci selfObject), 1818bf80f4bSopenharmony_ci false); 1828bf80f4bSopenharmony_ci } else { 1838bf80f4bSopenharmony_ci CORE_LOG_D("Could not find '%s' mesh", name.c_str()); 1848bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 1858bf80f4bSopenharmony_ci MakeTask( 1868bf80f4bSopenharmony_ci [](auto selfObject) { 1878bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 1888bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_DISCONNECTED); 1898bf80f4bSopenharmony_ci } 1908bf80f4bSopenharmony_ci return false; 1918bf80f4bSopenharmony_ci }, 1928bf80f4bSopenharmony_ci selfObject), 1938bf80f4bSopenharmony_ci false); 1948bf80f4bSopenharmony_ci } 1958bf80f4bSopenharmony_ci } 1968bf80f4bSopenharmony_ci } 1978bf80f4bSopenharmony_ci return false; 1988bf80f4bSopenharmony_ci }, 1998bf80f4bSopenharmony_ci GetSelf()), 2008bf80f4bSopenharmony_ci false); 2018bf80f4bSopenharmony_ci } 2028bf80f4bSopenharmony_ci } 2038bf80f4bSopenharmony_ci 2048bf80f4bSopenharmony_ci bool BuildChildren(SCENE_NS::INode::BuildBehavior) override 2058bf80f4bSopenharmony_ci { 2068bf80f4bSopenharmony_ci // in typical cases we should not have children 2078bf80f4bSopenharmony_ci if (META_NS::GetValue(META_ACCESS_PROPERTY(Status)) == SCENE_NS::INode::NODE_STATUS_CONNECTED) { 2088bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED); 2098bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(OnBound()); 2108bf80f4bSopenharmony_ci bound_ = true; 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci return true; 2138bf80f4bSopenharmony_ci } 2148bf80f4bSopenharmony_ci 2158bf80f4bSopenharmony_ci bool ShouldExport() const override 2168bf80f4bSopenharmony_ci { 2178bf80f4bSopenharmony_ci for (auto& submesh : SubMeshes()->GetValue()) { 2188bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(submesh); 2198bf80f4bSopenharmony_ci if (HasChangedProperties(*meta)) { 2208bf80f4bSopenharmony_ci return true; 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci } 2238bf80f4bSopenharmony_ci return false; 2248bf80f4bSopenharmony_ci } 2258bf80f4bSopenharmony_ci //todo 2268bf80f4bSopenharmony_ci /* 2278bf80f4bSopenharmony_ci bool Export( 2288bf80f4bSopenharmony_ci META_NS::Serialization::IExportContext& context, META_NS::Serialization::ClassPrimitive& value) const override 2298bf80f4bSopenharmony_ci { 2308bf80f4bSopenharmony_ci BASE_NS::vector<SCENE_NS::IMaterial::Ptr> nonSerializedMaterials; 2318bf80f4bSopenharmony_ci 2328bf80f4bSopenharmony_ci auto hasOverrideMaterialUri = !GetValue(MaterialOverrideUri()).empty(); 2338bf80f4bSopenharmony_ci auto overrideMaterial = GetValue(MaterialOverride()); 2348bf80f4bSopenharmony_ci if (overrideMaterial && hasOverrideMaterialUri) { 2358bf80f4bSopenharmony_ci if (interface_pointer_cast<META_NS::IObjectFlags>(overrideMaterial)->GetObjectFlags() & 2368bf80f4bSopenharmony_ci META_NS::ObjectFlagBits::SERIALIZE) { 2378bf80f4bSopenharmony_ci nonSerializedMaterials.push_back(overrideMaterial); 2388bf80f4bSopenharmony_ci } 2398bf80f4bSopenharmony_ci } 2408bf80f4bSopenharmony_ci 2418bf80f4bSopenharmony_ci for (auto& submesh : SubMeshes()->ToVector()) { 2428bf80f4bSopenharmony_ci auto hasSubmeshMaterialUri = !GetValue(submesh->MaterialUri()).empty(); 2438bf80f4bSopenharmony_ci auto submeshMaterial = GetValue(submesh->Material()); 2448bf80f4bSopenharmony_ci if (submeshMaterial && hasSubmeshMaterialUri) { 2458bf80f4bSopenharmony_ci if (interface_pointer_cast<META_NS::IObjectFlags>(submeshMaterial)->GetObjectFlags() & 2468bf80f4bSopenharmony_ci META_NS::ObjectFlagBits::SERIALIZE) { 2478bf80f4bSopenharmony_ci nonSerializedMaterials.push_back(submeshMaterial); 2488bf80f4bSopenharmony_ci } 2498bf80f4bSopenharmony_ci } 2508bf80f4bSopenharmony_ci } 2518bf80f4bSopenharmony_ci 2528bf80f4bSopenharmony_ci // Do not export these materials. 2538bf80f4bSopenharmony_ci for (auto& material : nonSerializedMaterials) { 2548bf80f4bSopenharmony_ci META_NS::SetObjectFlags(material, META_NS::ObjectFlagBits::SERIALIZE, false); 2558bf80f4bSopenharmony_ci } 2568bf80f4bSopenharmony_ci 2578bf80f4bSopenharmony_ci bool result = Fwd::Export(context, value); 2588bf80f4bSopenharmony_ci 2598bf80f4bSopenharmony_ci // Put back material serialization info. 2608bf80f4bSopenharmony_ci for (auto& material : nonSerializedMaterials) { 2618bf80f4bSopenharmony_ci META_NS::SetObjectFlags(material, META_NS::ObjectFlagBits::SERIALIZE, true); 2628bf80f4bSopenharmony_ci } 2638bf80f4bSopenharmony_ci 2648bf80f4bSopenharmony_ci return result; 2658bf80f4bSopenharmony_ci } 2668bf80f4bSopenharmony_ci */ 2678bf80f4bSopenharmony_ci // Set given material for all the submeshes. 2688bf80f4bSopenharmony_ci void SetMaterial(const SCENE_NS::IMaterial::Ptr material) override 2698bf80f4bSopenharmony_ci { 2708bf80f4bSopenharmony_ci MaterialOverride()->SetValue(material); 2718bf80f4bSopenharmony_ci } 2728bf80f4bSopenharmony_ci 2738bf80f4bSopenharmony_ci // Set material for the spesific submesh. 2748bf80f4bSopenharmony_ci void SetMaterial(size_t index, const SCENE_NS::IMaterial::Ptr& material) override 2758bf80f4bSopenharmony_ci { 2768bf80f4bSopenharmony_ci if (auto node = interface_pointer_cast<SCENE_NS::INode>(material)) { 2778bf80f4bSopenharmony_ci node->Status()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>( 2788bf80f4bSopenharmony_ci [mat = BASE_NS::weak_ptr(material)](const auto& self, const auto& status, const auto& index) { 2798bf80f4bSopenharmony_ci if (self && status && status->GetValue() == SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED) { 2808bf80f4bSopenharmony_ci static_cast<MeshImpl*>(self.get())->SetMaterialToScene((int32_t)index, mat.lock()); 2818bf80f4bSopenharmony_ci } 2828bf80f4bSopenharmony_ci }, 2838bf80f4bSopenharmony_ci GetSelf(), node->Status(), index)); 2848bf80f4bSopenharmony_ci if (auto status = META_NS::GetValue(node->Status()); 2858bf80f4bSopenharmony_ci status == SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED || 2868bf80f4bSopenharmony_ci status == SCENE_NS::INode::NODE_STATUS_CONNECTED) { 2878bf80f4bSopenharmony_ci SetMaterialToScene(static_cast<int64_t>(index), material); 2888bf80f4bSopenharmony_ci } 2898bf80f4bSopenharmony_ci } 2908bf80f4bSopenharmony_ci } 2918bf80f4bSopenharmony_ci 2928bf80f4bSopenharmony_ci void SetMaterialToScene(int64_t index, const SCENE_NS::IMaterial::Ptr& material) 2938bf80f4bSopenharmony_ci { 2948bf80f4bSopenharmony_ci auto count = SubMeshes()->GetSize(); 2958bf80f4bSopenharmony_ci if (index == -1) { 2968bf80f4bSopenharmony_ci for (auto i = 0; i < count; ++i) { 2978bf80f4bSopenharmony_ci SubMeshes()->GetValueAt(i)->SetMaterial(material); 2988bf80f4bSopenharmony_ci } 2998bf80f4bSopenharmony_ci } else if (index < count) { 3008bf80f4bSopenharmony_ci SubMeshes()->GetValueAt(index)->SetMaterial(material); 3018bf80f4bSopenharmony_ci } 3028bf80f4bSopenharmony_ci } 3038bf80f4bSopenharmony_ci 3048bf80f4bSopenharmony_ci SCENE_NS::IMaterial::Ptr GetMaterial(size_t index) override 3058bf80f4bSopenharmony_ci { 3068bf80f4bSopenharmony_ci if (index < META_ACCESS_PROPERTY(SubMeshes)->GetSize()) { 3078bf80f4bSopenharmony_ci return META_ACCESS_PROPERTY(SubMeshes)->GetValueAt(index)->Material()->GetValue(); 3088bf80f4bSopenharmony_ci } 3098bf80f4bSopenharmony_ci 3108bf80f4bSopenharmony_ci SCENE_NS::IMaterial::Ptr ret {}; 3118bf80f4bSopenharmony_ci if (auto iscene = GetScene()) { 3128bf80f4bSopenharmony_ci if (META_NS::GetValue(iscene->Asynchronous()) == false) { 3138bf80f4bSopenharmony_ci auto entityName = SceneHolder()->GetMaterialName(EcsObject()->GetEntity(), index); 3148bf80f4bSopenharmony_ci if (!entityName.empty()) { 3158bf80f4bSopenharmony_ci ret = iscene->GetMaterial(entityName); 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci } 3188bf80f4bSopenharmony_ci } 3198bf80f4bSopenharmony_ci 3208bf80f4bSopenharmony_ci // This path is not needed if material exists, in async mode it could still save the day, though 3218bf80f4bSopenharmony_ci if (!ret) { 3228bf80f4bSopenharmony_ci ret = GetObjectRegistry().Create<SCENE_NS::IMaterial>(SCENE_NS::ClassId::Material); 3238bf80f4bSopenharmony_ci 3248bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 3258bf80f4bSopenharmony_ci scene->AddEngineTask( 3268bf80f4bSopenharmony_ci MakeTask( 3278bf80f4bSopenharmony_ci [ret, index](auto selfObject) { 3288bf80f4bSopenharmony_ci if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfObject)) { 3298bf80f4bSopenharmony_ci if (auto node = static_pointer_cast<NodeImpl>(selfObject)) { 3308bf80f4bSopenharmony_ci if (auto sceneHolder = node->SceneHolder()) { 3318bf80f4bSopenharmony_ci auto entityName = sceneHolder->GetMaterialName(self->GetEntity(), index); 3328bf80f4bSopenharmony_ci if (!entityName.empty()) { 3338bf80f4bSopenharmony_ci BASE_NS::string name(entityName.data(), entityName.size()); 3348bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 3358bf80f4bSopenharmony_ci MakeTask( 3368bf80f4bSopenharmony_ci [name, ret](auto selfObject) { 3378bf80f4bSopenharmony_ci if (auto node = static_pointer_cast<NodeImpl>(selfObject)) { 3388bf80f4bSopenharmony_ci auto scene = node->EcsScene(); 3398bf80f4bSopenharmony_ci auto object = META_NS::GetObjectRegistry().Create( 3408bf80f4bSopenharmony_ci SCENE_NS::ClassId::EcsObject); 3418bf80f4bSopenharmony_ci if (auto ecsObject = 3428bf80f4bSopenharmony_ci interface_pointer_cast<SCENE_NS::IEcsObject>( 3438bf80f4bSopenharmony_ci object)) { 3448bf80f4bSopenharmony_ci if (auto privateInit = interface_pointer_cast< 3458bf80f4bSopenharmony_ci INodeEcsInterfacePrivate>(ret)) { 3468bf80f4bSopenharmony_ci privateInit->Initialize(scene, ecsObject, {}, "", 3478bf80f4bSopenharmony_ci name, node->SceneHolder(), {}); 3488bf80f4bSopenharmony_ci } 3498bf80f4bSopenharmony_ci } 3508bf80f4bSopenharmony_ci } 3518bf80f4bSopenharmony_ci return false; 3528bf80f4bSopenharmony_ci }, 3538bf80f4bSopenharmony_ci selfObject), 3548bf80f4bSopenharmony_ci false); 3558bf80f4bSopenharmony_ci } 3568bf80f4bSopenharmony_ci } 3578bf80f4bSopenharmony_ci } 3588bf80f4bSopenharmony_ci } 3598bf80f4bSopenharmony_ci return false; 3608bf80f4bSopenharmony_ci }, 3618bf80f4bSopenharmony_ci GetSelf()), 3628bf80f4bSopenharmony_ci false); 3638bf80f4bSopenharmony_ci } 3648bf80f4bSopenharmony_ci } 3658bf80f4bSopenharmony_ci return ret; 3668bf80f4bSopenharmony_ci } 3678bf80f4bSopenharmony_ci 3688bf80f4bSopenharmony_ci void SetRenderSortLayerOrder(size_t index, uint8_t value) override 3698bf80f4bSopenharmony_ci { 3708bf80f4bSopenharmony_ci if (submeshHandler_) { 3718bf80f4bSopenharmony_ci submeshHandler_->SetRenderSortLayerOrder(index, value); 3728bf80f4bSopenharmony_ci } else { 3738bf80f4bSopenharmony_ci CORE_LOG_W("%s: mesh is not ready yet, call has no effect", __func__); 3748bf80f4bSopenharmony_ci } 3758bf80f4bSopenharmony_ci } 3768bf80f4bSopenharmony_ci 3778bf80f4bSopenharmony_ci uint8_t GetRenderSortLayerOrder(size_t index) const override 3788bf80f4bSopenharmony_ci { 3798bf80f4bSopenharmony_ci if (index < SubMeshes()->GetSize()) { 3808bf80f4bSopenharmony_ci return META_NS::GetValue(SubMeshes()->GetValueAt(index)->RenderSortLayerOrder()); 3818bf80f4bSopenharmony_ci } 3828bf80f4bSopenharmony_ci return 0u; // default in mesh component 3838bf80f4bSopenharmony_ci } 3848bf80f4bSopenharmony_ci 3858bf80f4bSopenharmony_ci template<typename INDEX_TYPE> 3868bf80f4bSopenharmony_ci void UpdateMeshFromArrays( 3878bf80f4bSopenharmony_ci SCENE_NS::MeshGeometryArrayPtr<INDEX_TYPE> arrays, const RENDER_NS::IndexType& indexType, bool append = false) 3888bf80f4bSopenharmony_ci { 3898bf80f4bSopenharmony_ci if (auto sh = SceneHolder()) { 3908bf80f4bSopenharmony_ci if (!append) { 3918bf80f4bSopenharmony_ci // Need to invalidate materials up front 3928bf80f4bSopenharmony_ci SetMaterial(SCENE_NS::IMaterial::Ptr {}); 3938bf80f4bSopenharmony_ci } 3948bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTING); 3958bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask( 3968bf80f4bSopenharmony_ci [arrays, indexType, append](auto privateIntf) { 3978bf80f4bSopenharmony_ci // create new mesh entity 3988bf80f4bSopenharmony_ci if (auto sh = privateIntf->SceneHolder()) { 3998bf80f4bSopenharmony_ci auto existingEntity = privateIntf->EcsObject()->GetEntity(); 4008bf80f4bSopenharmony_ci auto newEntity = sh->template CreateMeshFromArrays<INDEX_TYPE>( 4018bf80f4bSopenharmony_ci "TempMesh", arrays, indexType, existingEntity, append); 4028bf80f4bSopenharmony_ci sh->QueueApplicationTask( 4038bf80f4bSopenharmony_ci MakeTask( 4048bf80f4bSopenharmony_ci [](auto strong) { 4058bf80f4bSopenharmony_ci if (auto self = static_cast<MeshImpl*>(strong.get())) { 4068bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTED); 4078bf80f4bSopenharmony_ci self->SetStatus( 4088bf80f4bSopenharmony_ci SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED); 4098bf80f4bSopenharmony_ci if (META_NS::GetValue(self->MaterialOverride())) { 4108bf80f4bSopenharmony_ci self->SyncMaterialOverrideToSubmeshes(); 4118bf80f4bSopenharmony_ci } 4128bf80f4bSopenharmony_ci } 4138bf80f4bSopenharmony_ci return false; 4148bf80f4bSopenharmony_ci }, 4158bf80f4bSopenharmony_ci privateIntf), 4168bf80f4bSopenharmony_ci false); 4178bf80f4bSopenharmony_ci } 4188bf80f4bSopenharmony_ci return false; 4198bf80f4bSopenharmony_ci }, 4208bf80f4bSopenharmony_ci GetSelf<INodeEcsInterfacePrivate>()), 4218bf80f4bSopenharmony_ci false); 4228bf80f4bSopenharmony_ci } 4238bf80f4bSopenharmony_ci } 4248bf80f4bSopenharmony_ci 4258bf80f4bSopenharmony_ci void UpdateMeshFromArraysI16(SCENE_NS::MeshGeometryArrayPtr<uint16_t> arrays) override 4268bf80f4bSopenharmony_ci { 4278bf80f4bSopenharmony_ci UpdateMeshFromArrays<uint16_t>(arrays, RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT16); 4288bf80f4bSopenharmony_ci } 4298bf80f4bSopenharmony_ci 4308bf80f4bSopenharmony_ci void UpdateMeshFromArraysI32(SCENE_NS::MeshGeometryArrayPtr<uint32_t> arrays) override 4318bf80f4bSopenharmony_ci { 4328bf80f4bSopenharmony_ci UpdateMeshFromArrays<uint32_t>(arrays, RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT32); 4338bf80f4bSopenharmony_ci } 4348bf80f4bSopenharmony_ci 4358bf80f4bSopenharmony_ci void AddSubmeshesFromArrayI16(SCENE_NS::MeshGeometryArrayPtr<uint16_t> arrays) override 4368bf80f4bSopenharmony_ci { 4378bf80f4bSopenharmony_ci UpdateMeshFromArrays<uint16_t>(arrays, RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT16, true); 4388bf80f4bSopenharmony_ci } 4398bf80f4bSopenharmony_ci 4408bf80f4bSopenharmony_ci void AddSubmeshesFromArraysI32(SCENE_NS::MeshGeometryArrayPtr<uint32_t> arrays) override 4418bf80f4bSopenharmony_ci { 4428bf80f4bSopenharmony_ci UpdateMeshFromArrays<uint32_t>(arrays, RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT32, true); 4438bf80f4bSopenharmony_ci } 4448bf80f4bSopenharmony_ci 4458bf80f4bSopenharmony_ci void CloneSubmesh(SCENE_NS::ISubMesh::Ptr submesh) override 4468bf80f4bSopenharmony_ci { 4478bf80f4bSopenharmony_ci if (auto sh = SceneHolder()) { 4488bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask( 4498bf80f4bSopenharmony_ci [source = interface_pointer_cast<SCENE_NS::ISubMeshPrivate>(submesh)->GetEntity(), 4508bf80f4bSopenharmony_ci index = META_NS::GetValue(submesh->Handle())](auto privateIntf) { 4518bf80f4bSopenharmony_ci privateIntf->SceneHolder()->CopySubMesh( 4528bf80f4bSopenharmony_ci privateIntf->EcsObject()->GetEntity(), source, index); 4538bf80f4bSopenharmony_ci 4548bf80f4bSopenharmony_ci return false; 4558bf80f4bSopenharmony_ci }, 4568bf80f4bSopenharmony_ci GetSelf<INodeEcsInterfacePrivate>()), 4578bf80f4bSopenharmony_ci false); 4588bf80f4bSopenharmony_ci } 4598bf80f4bSopenharmony_ci // Submesh bridge should automatically reflect the updates 4608bf80f4bSopenharmony_ci } 4618bf80f4bSopenharmony_ci 4628bf80f4bSopenharmony_ci void RemoveSubMesh(size_t index) override 4638bf80f4bSopenharmony_ci { 4648bf80f4bSopenharmony_ci if (submeshHandler_) { 4658bf80f4bSopenharmony_ci submeshHandler_->RemoveSubmesh(index); 4668bf80f4bSopenharmony_ci } else { 4678bf80f4bSopenharmony_ci CORE_LOG_W("%s: mesh is not ready yet, call has no effect", __func__); 4688bf80f4bSopenharmony_ci } 4698bf80f4bSopenharmony_ci } 4708bf80f4bSopenharmony_ci virtual void RemoveAllSubmeshes() override 4718bf80f4bSopenharmony_ci { 4728bf80f4bSopenharmony_ci if (submeshHandler_) { 4738bf80f4bSopenharmony_ci submeshHandler_->RemoveSubmesh(-1); 4748bf80f4bSopenharmony_ci } else { 4758bf80f4bSopenharmony_ci CORE_LOG_W("%s: mesh is not ready yet, call has no effect", __func__); 4768bf80f4bSopenharmony_ci } 4778bf80f4bSopenharmony_ci } 4788bf80f4bSopenharmony_ci 4798bf80f4bSopenharmony_ciprivate: 4808bf80f4bSopenharmony_ci SCENE_NS::ISubMeshBridge::Ptr submeshHandler_; 4818bf80f4bSopenharmony_ci}; 4828bf80f4bSopenharmony_ci} // namespace 4838bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 4848bf80f4bSopenharmony_civoid RegisterMeshImpl() 4858bf80f4bSopenharmony_ci{ 4868bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().RegisterObjectType<MeshImpl>(); 4878bf80f4bSopenharmony_ci} 4888bf80f4bSopenharmony_civoid UnregisterMeshImpl() 4898bf80f4bSopenharmony_ci{ 4908bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().UnregisterObjectType<MeshImpl>(); 4918bf80f4bSopenharmony_ci} 4928bf80f4bSopenharmony_ci 4938bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 494