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/mesh_uid.h>
168bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_material.h>
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <3d/ecs/components/mesh_component.h>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <meta/ext/object.h>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include "intf_node_private.h"
238bf80f4bSopenharmony_ci#include "intf_submesh_bridge.h"
248bf80f4bSopenharmony_ci#include "submesh_handler_uid.h"
258bf80f4bSopenharmony_ci#include "task_utils.h"
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask;
288bf80f4bSopenharmony_ci
298bf80f4bSopenharmony_cinamespace {
308bf80f4bSopenharmony_ciclass SubMeshHandler : public META_NS::ObjectFwd<SubMeshHandler, SCENE_NS::ClassId::SubMeshHandler,
318bf80f4bSopenharmony_ci                           META_NS::ClassId::Object, SCENE_NS::IEcsProxyObject, SCENE_NS::ISubMeshBridge> {
328bf80f4bSopenharmony_cipublic:
338bf80f4bSopenharmony_ci    void Initialize(CORE3D_NS::IMeshComponentManager* componentManager, CORE_NS::Entity entity,
348bf80f4bSopenharmony_ci        META_NS::IProperty::Ptr submeshes, INodeEcsInterfacePrivate::Ptr node) override
358bf80f4bSopenharmony_ci    {
368bf80f4bSopenharmony_ci        node_ = node;
378bf80f4bSopenharmony_ci        if (node) {
388bf80f4bSopenharmony_ci            componentManager_ = componentManager;
398bf80f4bSopenharmony_ci            entity_ = entity;
408bf80f4bSopenharmony_ci            submeshes_ = META_NS::ArrayProperty<SCENE_NS::ISubMesh::Ptr>(submeshes);
418bf80f4bSopenharmony_ci            SetCommonListener(node->SceneHolder()->GetCommonEcsListener());
428bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
438bf80f4bSopenharmony_ci                scene->AddEngineTask(MakeTask(
448bf80f4bSopenharmony_ci                                         [](auto obj) {
458bf80f4bSopenharmony_ci                                             if (auto self = static_cast<SubMeshHandler*>(obj.get())) {
468bf80f4bSopenharmony_ci                                                 self->DoComponentEvent(
478bf80f4bSopenharmony_ci                                                     CORE_NS::IEcs::ComponentListener::EventType::MODIFIED,
488bf80f4bSopenharmony_ci                                                     *self->componentManager_, self->entity_);
498bf80f4bSopenharmony_ci                                             }
508bf80f4bSopenharmony_ci                                             return false;
518bf80f4bSopenharmony_ci                                         },
528bf80f4bSopenharmony_ci                                         GetSelf()),
538bf80f4bSopenharmony_ci                    false);
548bf80f4bSopenharmony_ci            }
558bf80f4bSopenharmony_ci        }
568bf80f4bSopenharmony_ci    }
578bf80f4bSopenharmony_ci
588bf80f4bSopenharmony_ci    void Destroy() override
598bf80f4bSopenharmony_ci    {
608bf80f4bSopenharmony_ci        if (listener_) {
618bf80f4bSopenharmony_ci            listener_->RemoveEntity(entity_, GetSelf<SCENE_NS::IEcsProxyObject>(),
628bf80f4bSopenharmony_ci                *static_cast<CORE_NS::IComponentManager*>(componentManager_));
638bf80f4bSopenharmony_ci        }
648bf80f4bSopenharmony_ci    }
658bf80f4bSopenharmony_ci
668bf80f4bSopenharmony_ci    // IEcsProxyObject
678bf80f4bSopenharmony_ci
688bf80f4bSopenharmony_ci    void SetCommonListener(BASE_NS::shared_ptr<SCENE_NS::EcsListener> listener) override
698bf80f4bSopenharmony_ci    {
708bf80f4bSopenharmony_ci        if (listener_) {
718bf80f4bSopenharmony_ci            listener_->RemoveEntity(entity_, GetSelf<SCENE_NS::IEcsProxyObject>(),
728bf80f4bSopenharmony_ci                *static_cast<CORE_NS::IComponentManager*>(componentManager_));
738bf80f4bSopenharmony_ci        }
748bf80f4bSopenharmony_ci        listener_ = listener;
758bf80f4bSopenharmony_ci        if (listener_) {
768bf80f4bSopenharmony_ci            listener_->AddEntity(entity_, GetSelf<SCENE_NS::IEcsProxyObject>(),
778bf80f4bSopenharmony_ci                *static_cast<CORE_NS::IComponentManager*>(componentManager_));
788bf80f4bSopenharmony_ci        }
798bf80f4bSopenharmony_ci    }
808bf80f4bSopenharmony_ci
818bf80f4bSopenharmony_ci    void DoEntityEvent(CORE_NS::IEcs::EntityListener::EventType, const CORE_NS::Entity&) override {}
828bf80f4bSopenharmony_ci
838bf80f4bSopenharmony_ci    SCENE_NS::IMaterial::Ptr GetMaterialFromEntity(
848bf80f4bSopenharmony_ci        SCENE_NS::IScene::Ptr scene, SceneHolder::Ptr sceneHolder, CORE_NS::Entity entity)
858bf80f4bSopenharmony_ci    {
868bf80f4bSopenharmony_ci        // First see if we have this material already.
878bf80f4bSopenharmony_ci        auto materials = scene->GetMaterials();
888bf80f4bSopenharmony_ci        for (auto material : materials) {
898bf80f4bSopenharmony_ci            auto ecsObject = interface_pointer_cast<SCENE_NS::IEcsObject>(material);
908bf80f4bSopenharmony_ci            if (ecsObject && ecsObject->GetEntity() == entity) {
918bf80f4bSopenharmony_ci                return material;
928bf80f4bSopenharmony_ci            }
938bf80f4bSopenharmony_ci        }
948bf80f4bSopenharmony_ci
958bf80f4bSopenharmony_ci        // Then try to resolve from uri.
968bf80f4bSopenharmony_ci        BASE_NS::string uri;
978bf80f4bSopenharmony_ci        if (sceneHolder->GetEntityUri(entity, uri)) {
988bf80f4bSopenharmony_ci            return scene->GetMaterial(uri);
998bf80f4bSopenharmony_ci        }
1008bf80f4bSopenharmony_ci
1018bf80f4bSopenharmony_ci        BASE_NS::string name;
1028bf80f4bSopenharmony_ci        if (sceneHolder->GetEntityName(entity, name)) {
1038bf80f4bSopenharmony_ci            return scene->GetMaterial(name);
1048bf80f4bSopenharmony_ci        }
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_ci        return {};
1078bf80f4bSopenharmony_ci    }
1088bf80f4bSopenharmony_ci
1098bf80f4bSopenharmony_ci    // ToDo: This runs on "engine queue", someday the property operations could be decoupled
1108bf80f4bSopenharmony_ci    // Another todo, this should presumably be closer to SceneHolder instead interleaved into the node impl
1118bf80f4bSopenharmony_ci    void DoComponentEvent(CORE_NS::IEcs::ComponentListener::EventType type,
1128bf80f4bSopenharmony_ci        const CORE_NS::IComponentManager& componentManager, const CORE_NS::Entity& entity) override
1138bf80f4bSopenharmony_ci    {
1148bf80f4bSopenharmony_ci        if (entity != entity_) {
1158bf80f4bSopenharmony_ci            CORE_LOG_W("DoComponentEvent called for wrong entity.");
1168bf80f4bSopenharmony_ci            return;
1178bf80f4bSopenharmony_ci        }
1188bf80f4bSopenharmony_ci
1198bf80f4bSopenharmony_ci        if (type == CORE_NS::IEcs::ComponentListener::EventType::MODIFIED) {
1208bf80f4bSopenharmony_ci            // Read data here, we don't want to keep read lock when we update materials below
1218bf80f4bSopenharmony_ci            // as it can cause changes to material components further down the pipeline.
1228bf80f4bSopenharmony_ci            auto componentData = componentManager_->Get(entity);
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_ci            // This may be nasty from the application point of view, but lessens a risk
1258bf80f4bSopenharmony_ci            // that index changes would be propagated incorrectly to client app
1268bf80f4bSopenharmony_ci            if (submeshes_->GetSize() > componentData.submeshes.size()) {
1278bf80f4bSopenharmony_ci                submeshes_->Reset();
1288bf80f4bSopenharmony_ci            }
1298bf80f4bSopenharmony_ci
1308bf80f4bSopenharmony_ci            while (submeshes_->GetSize() < componentData.submeshes.size()) {
1318bf80f4bSopenharmony_ci                auto submesh = GetObjectRegistry().Create<SCENE_NS::ISubMesh>(SCENE_NS::ClassId::SubMesh);
1328bf80f4bSopenharmony_ci                submeshes_->AddValue(submesh);
1338bf80f4bSopenharmony_ci            }
1348bf80f4bSopenharmony_ci
1358bf80f4bSopenharmony_ci            for (auto i = 0; i < componentData.submeshes.size(); ++i) {
1368bf80f4bSopenharmony_ci                const auto& submesh = componentData.submeshes.at(i);
1378bf80f4bSopenharmony_ci                auto ptr = submeshes_->GetValueAt(i);
1388bf80f4bSopenharmony_ci                // TODO: These could be initialized only once.
1398bf80f4bSopenharmony_ci                ptr->Name()->SetValue(BASE_NS::string("Submesh ") + BASE_NS::to_string(i));
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ci                META_NS::SetValue(ptr->AABBMin(), submesh.aabbMin);
1428bf80f4bSopenharmony_ci                META_NS::SetValue(ptr->AABBMax(), submesh.aabbMax);
1438bf80f4bSopenharmony_ci                META_NS::SetValue(ptr->RenderSortLayerOrder(), submesh.renderSortLayerOrder);
1448bf80f4bSopenharmony_ci                META_NS::SetValue(ptr->Handle(), i);
1458bf80f4bSopenharmony_ci
1468bf80f4bSopenharmony_ci                auto priv = interface_pointer_cast<SCENE_NS::ISubMeshPrivate>(ptr);
1478bf80f4bSopenharmony_ci                if (CORE_NS::EntityUtil::IsValid(submesh.material)) {
1488bf80f4bSopenharmony_ci                    if (auto node = node_.lock()) {
1498bf80f4bSopenharmony_ci                        // This would appreciate more async approach
1508bf80f4bSopenharmony_ci                        auto sceneHolder = node->SceneHolder();
1518bf80f4bSopenharmony_ci                        auto scene = interface_pointer_cast<SCENE_NS::IScene>(node->EcsScene());
1528bf80f4bSopenharmony_ci
1538bf80f4bSopenharmony_ci                        if (scene && sceneHolder) {
1548bf80f4bSopenharmony_ci                            auto material = GetMaterialFromEntity(scene, sceneHolder, submesh.material);
1558bf80f4bSopenharmony_ci                            priv->SetDefaultMaterial(material);
1568bf80f4bSopenharmony_ci                        }
1578bf80f4bSopenharmony_ci                    }
1588bf80f4bSopenharmony_ci                } else {
1598bf80f4bSopenharmony_ci                    priv->SetDefaultMaterial({});
1608bf80f4bSopenharmony_ci                }
1618bf80f4bSopenharmony_ci                priv->AddSubmeshBrigde(GetSelf<ISubMeshBridge>());
1628bf80f4bSopenharmony_ci            }
1638bf80f4bSopenharmony_ci        }
1648bf80f4bSopenharmony_ci    }
1658bf80f4bSopenharmony_ci
1668bf80f4bSopenharmony_cipublic: // ISubMeshBridge
1678bf80f4bSopenharmony_ci    void SetRenderSortLayerOrder(size_t index, uint8_t value) override
1688bf80f4bSopenharmony_ci    {
1698bf80f4bSopenharmony_ci#ifdef SYNC_ACCESS_ECS
1708bf80f4bSopenharmony_ci        if (auto handle = componentManager_->Write(entity_)) {
1718bf80f4bSopenharmony_ci            if (index >= 0 && index < handle->submeshes.size()) {
1728bf80f4bSopenharmony_ci                handle->submeshes[index].renderSortOrder = value;
1738bf80f4bSopenharmony_ci            }
1748bf80f4bSopenharmony_ci        }
1758bf80f4bSopenharmony_ci#else
1768bf80f4bSopenharmony_ci        if (auto node = node_.lock()) {
1778bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
1788bf80f4bSopenharmony_ci                scene->AddEngineTask(MakeTask(
1798bf80f4bSopenharmony_ci                                         [index, value](auto selfNode) {
1808bf80f4bSopenharmony_ci                                             if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfNode)) {
1818bf80f4bSopenharmony_ci                                                 if (auto node = interface_cast<INodeEcsInterfacePrivate>(selfNode)) {
1828bf80f4bSopenharmony_ci                                                     if (auto sceneHolder = node->SceneHolder()) {
1838bf80f4bSopenharmony_ci                                                         sceneHolder->SetSubmeshRenderSortOrder(
1848bf80f4bSopenharmony_ci                                                             self->GetEntity(), index, value);
1858bf80f4bSopenharmony_ci                                                     }
1868bf80f4bSopenharmony_ci                                                 }
1878bf80f4bSopenharmony_ci                                             }
1888bf80f4bSopenharmony_ci                                             return false;
1898bf80f4bSopenharmony_ci                                         },
1908bf80f4bSopenharmony_ci                                         node),
1918bf80f4bSopenharmony_ci                    false);
1928bf80f4bSopenharmony_ci            }
1938bf80f4bSopenharmony_ci        }
1948bf80f4bSopenharmony_ci#endif
1958bf80f4bSopenharmony_ci        if (index < submeshes_->GetSize()) {
1968bf80f4bSopenharmony_ci            META_NS::SetValue(submeshes_->GetValueAt(index)->RenderSortLayerOrder(), value);
1978bf80f4bSopenharmony_ci        }
1988bf80f4bSopenharmony_ci    }
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_ci    void SetMaterialToEcs(size_t index, SCENE_NS::IMaterial::Ptr& material) override
2018bf80f4bSopenharmony_ci    {
2028bf80f4bSopenharmony_ci        if (auto node = node_.lock()) {
2038bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
2048bf80f4bSopenharmony_ci                scene->AddEngineTask(
2058bf80f4bSopenharmony_ci                    MakeTask(
2068bf80f4bSopenharmony_ci                        [mat = SCENE_NS::IMaterial::WeakPtr(material), index](auto node) {
2078bf80f4bSopenharmony_ci                            if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(node)) {
2088bf80f4bSopenharmony_ci                                CORE_NS::Entity entity {};
2098bf80f4bSopenharmony_ci                                if (auto ecsObject = interface_pointer_cast<SCENE_NS::IEcsObject>(mat.lock())) {
2108bf80f4bSopenharmony_ci                                    entity = ecsObject->GetEntity();
2118bf80f4bSopenharmony_ci                                }
2128bf80f4bSopenharmony_ci                                auto sceneHolder = node->SceneHolder();
2138bf80f4bSopenharmony_ci                                if (sceneHolder) {
2148bf80f4bSopenharmony_ci                                    sceneHolder->SetMaterial(self->GetEntity(), entity, index);
2158bf80f4bSopenharmony_ci                                }
2168bf80f4bSopenharmony_ci                            }
2178bf80f4bSopenharmony_ci                            return false;
2188bf80f4bSopenharmony_ci                        },
2198bf80f4bSopenharmony_ci                        node_),
2208bf80f4bSopenharmony_ci                    false);
2218bf80f4bSopenharmony_ci            }
2228bf80f4bSopenharmony_ci        }
2238bf80f4bSopenharmony_ci    }
2248bf80f4bSopenharmony_ci
2258bf80f4bSopenharmony_ci    void SetAABBMin(size_t index, BASE_NS::Math::Vec3 vec) override
2268bf80f4bSopenharmony_ci    {
2278bf80f4bSopenharmony_ci#ifdef SYNC_ACCESS_ECS
2288bf80f4bSopenharmony_ci        if (auto handle = componentManager_->Write(entity_)) {
2298bf80f4bSopenharmony_ci            if (index >= 0 && index < handle->submeshes.size()) {
2308bf80f4bSopenharmony_ci                handle->submeshes[index].aabbMin = vec;
2318bf80f4bSopenharmony_ci                handle->aabbMin = BASE_NS::Math::min(handle->aabbMin, vec);
2328bf80f4bSopenharmony_ci            }
2338bf80f4bSopenharmony_ci        }
2348bf80f4bSopenharmony_ci#else
2358bf80f4bSopenharmony_ci        if (auto node = node_.lock()) {
2368bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
2378bf80f4bSopenharmony_ci                scene->AddEngineTask(MakeTask(
2388bf80f4bSopenharmony_ci                                         [index, vec](auto selfNode) {
2398bf80f4bSopenharmony_ci                                             if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfNode)) {
2408bf80f4bSopenharmony_ci                                                 if (auto node = interface_cast<INodeEcsInterfacePrivate>(selfNode)) {
2418bf80f4bSopenharmony_ci                                                     if (auto sceneHolder = node->SceneHolder()) {
2428bf80f4bSopenharmony_ci                                                         sceneHolder->SetSubmeshAABBMin(self->GetEntity(), index, vec);
2438bf80f4bSopenharmony_ci                                                     }
2448bf80f4bSopenharmony_ci                                                 }
2458bf80f4bSopenharmony_ci                                             }
2468bf80f4bSopenharmony_ci                                             return false;
2478bf80f4bSopenharmony_ci                                         },
2488bf80f4bSopenharmony_ci                                         node),
2498bf80f4bSopenharmony_ci                    false);
2508bf80f4bSopenharmony_ci            }
2518bf80f4bSopenharmony_ci        }
2528bf80f4bSopenharmony_ci#endif
2538bf80f4bSopenharmony_ci        if (index < submeshes_->GetSize()) {
2548bf80f4bSopenharmony_ci            META_NS::SetValue(submeshes_->GetValueAt(index)->AABBMin(), vec);
2558bf80f4bSopenharmony_ci        }
2568bf80f4bSopenharmony_ci    }
2578bf80f4bSopenharmony_ci
2588bf80f4bSopenharmony_ci    void SetAABBMax(size_t index, BASE_NS::Math::Vec3 vec) override
2598bf80f4bSopenharmony_ci    {
2608bf80f4bSopenharmony_ci#ifdef SYNC_ACCESS_ECS
2618bf80f4bSopenharmony_ci        if (auto handle = componentManager_->Write(entity_)) {
2628bf80f4bSopenharmony_ci            if (index >= 0 && index < handle->submeshes.size()) {
2638bf80f4bSopenharmony_ci                handle->submeshes[index].aabbMax = vec;
2648bf80f4bSopenharmony_ci                handle->aabbMax = BASE_NS::Math::max(handle->aabbMax, vec);
2658bf80f4bSopenharmony_ci            }
2668bf80f4bSopenharmony_ci        }
2678bf80f4bSopenharmony_ci#else
2688bf80f4bSopenharmony_ci        if (auto node = node_.lock()) {
2698bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
2708bf80f4bSopenharmony_ci                scene->AddEngineTask(MakeTask(
2718bf80f4bSopenharmony_ci                                         [index, vec](auto selfNode) {
2728bf80f4bSopenharmony_ci                                             if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfNode)) {
2738bf80f4bSopenharmony_ci                                                 if (auto node = interface_cast<INodeEcsInterfacePrivate>(selfNode)) {
2748bf80f4bSopenharmony_ci                                                     if (auto sceneHolder = node->SceneHolder()) {
2758bf80f4bSopenharmony_ci                                                         sceneHolder->SetSubmeshAABBMax(self->GetEntity(), index, vec);
2768bf80f4bSopenharmony_ci                                                     }
2778bf80f4bSopenharmony_ci                                                 }
2788bf80f4bSopenharmony_ci                                             }
2798bf80f4bSopenharmony_ci                                             return false;
2808bf80f4bSopenharmony_ci                                         },
2818bf80f4bSopenharmony_ci                                         node),
2828bf80f4bSopenharmony_ci                    false);
2838bf80f4bSopenharmony_ci            }
2848bf80f4bSopenharmony_ci        }
2858bf80f4bSopenharmony_ci#endif
2868bf80f4bSopenharmony_ci        if (index < submeshes_->GetSize()) {
2878bf80f4bSopenharmony_ci            META_NS::SetValue(submeshes_->GetValueAt(index)->AABBMax(), vec);
2888bf80f4bSopenharmony_ci        }
2898bf80f4bSopenharmony_ci    }
2908bf80f4bSopenharmony_ci
2918bf80f4bSopenharmony_ci    void RemoveSubmesh(int32_t index) override
2928bf80f4bSopenharmony_ci    {
2938bf80f4bSopenharmony_ci#ifdef SYNC_ACCESS_ECS
2948bf80f4bSopenharmony_ci        if (auto handle = componentManager_->Write(entity_)) {
2958bf80f4bSopenharmony_ci            if (index < 0) {
2968bf80f4bSopenharmony_ci                handle->submeshes.clear();
2978bf80f4bSopenharmony_ci                handle->aabbMin = { 0.f, 0.f, 0.f };
2988bf80f4bSopenharmony_ci                handle->aabbMax = { 0.f, 0.f, 0.f };
2998bf80f4bSopenharmony_ci            } else if (index < handle->submeshes.size()) {
3008bf80f4bSopenharmony_ci                handle->submeshes.erase(handle->submeshes.begin() + index);
3018bf80f4bSopenharmony_ci                for (const auto& submesh : handle->submeshes) {
3028bf80f4bSopenharmony_ci                    handle->aabbMin = BASE_NS::Math::min(handle->aabbMin, submesh.aabbMin);
3038bf80f4bSopenharmony_ci                    handle->aabbMax = BASE_NS::Math::max(handle->aabbMax, submesh.aabbMax);
3048bf80f4bSopenharmony_ci                }
3058bf80f4bSopenharmony_ci            }
3068bf80f4bSopenharmony_ci        }
3078bf80f4bSopenharmony_ci#else
3088bf80f4bSopenharmony_ci        if (auto node = node_.lock()) {
3098bf80f4bSopenharmony_ci            if (auto scene = node->EcsScene()) {
3108bf80f4bSopenharmony_ci                scene->AddEngineTask(MakeTask(
3118bf80f4bSopenharmony_ci                                         [index](auto selfNode) {
3128bf80f4bSopenharmony_ci                                             if (auto self = interface_pointer_cast<SCENE_NS::IEcsObject>(selfNode)) {
3138bf80f4bSopenharmony_ci                                                 if (auto node = interface_cast<INodeEcsInterfacePrivate>(selfNode)) {
3148bf80f4bSopenharmony_ci                                                     if (auto sceneHolder = node->SceneHolder()) {
3158bf80f4bSopenharmony_ci                                                         sceneHolder->RemoveSubmesh(self->GetEntity(), index);
3168bf80f4bSopenharmony_ci                                                     }
3178bf80f4bSopenharmony_ci                                                 }
3188bf80f4bSopenharmony_ci                                             }
3198bf80f4bSopenharmony_ci                                             return false;
3208bf80f4bSopenharmony_ci                                         },
3218bf80f4bSopenharmony_ci                                         node_),
3228bf80f4bSopenharmony_ci                    false);
3238bf80f4bSopenharmony_ci            }
3248bf80f4bSopenharmony_ci        }
3258bf80f4bSopenharmony_ci#endif
3268bf80f4bSopenharmony_ci    }
3278bf80f4bSopenharmony_ci
3288bf80f4bSopenharmony_ci    CORE_NS::Entity GetEntity() const override
3298bf80f4bSopenharmony_ci    {
3308bf80f4bSopenharmony_ci        return entity_;
3318bf80f4bSopenharmony_ci    }
3328bf80f4bSopenharmony_ci
3338bf80f4bSopenharmony_ci    BASE_NS::shared_ptr<SCENE_NS::EcsListener> listener_ {};
3348bf80f4bSopenharmony_ci    CORE3D_NS::IMeshComponentManager* componentManager_ {};
3358bf80f4bSopenharmony_ci    CORE_NS::Entity entity_ {};
3368bf80f4bSopenharmony_ci    META_NS::ArrayProperty<SCENE_NS::ISubMesh::Ptr> submeshes_ {};
3378bf80f4bSopenharmony_ci    INodeEcsInterfacePrivate::WeakPtr node_ {};
3388bf80f4bSopenharmony_ci};
3398bf80f4bSopenharmony_ci} // namespace
3408bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE()
3418bf80f4bSopenharmony_ci
3428bf80f4bSopenharmony_civoid RegisterSubMeshHandler()
3438bf80f4bSopenharmony_ci{
3448bf80f4bSopenharmony_ci    META_NS::GetObjectRegistry().RegisterObjectType<SubMeshHandler>();
3458bf80f4bSopenharmony_ci}
3468bf80f4bSopenharmony_civoid UnregisterSubMeshHandler()
3478bf80f4bSopenharmony_ci{
3488bf80f4bSopenharmony_ci    META_NS::GetObjectRegistry().UnregisterObjectType<SubMeshHandler>();
3498bf80f4bSopenharmony_ci}
3508bf80f4bSopenharmony_ciSCENE_END_NAMESPACE()