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_mesh.h> 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <meta/ext/concrete_base_object.h> 198bf80f4bSopenharmony_ci 208bf80f4bSopenharmony_ci#include "bind_templates.inl" 218bf80f4bSopenharmony_ci#include "intf_multi_mesh_initialization.h" 228bf80f4bSopenharmony_ci#include "node_impl.h" 238bf80f4bSopenharmony_ci#include "task_utils.h" 248bf80f4bSopenharmony_ci 258bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask; 268bf80f4bSopenharmony_cinamespace { 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ciclass MultiMeshImpl : public META_NS::ObjectFwd<MultiMeshImpl, SCENE_NS::ClassId::MultiMeshProxy, 298bf80f4bSopenharmony_ci META_NS::ClassId::Object, SCENE_NS::IMultiMeshProxy, IMultimeshInitilization> { 308bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY( 318bf80f4bSopenharmony_ci SCENE_NS::IMultiMeshProxy, SCENE_NS::IMaterial::Ptr, MaterialOverride, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER) 328bf80f4bSopenharmony_ci // META_IMPLEMENT_INTERFACE_READONLY_PROPERTY( 338bf80f4bSopenharmony_ci // SCENE_NS::IMultiMeshProxy, BASE_NS::string, MaterialOverrideUri, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER) 348bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY( 358bf80f4bSopenharmony_ci SCENE_NS::IMultiMeshProxy, SCENE_NS::IMesh::Ptr, Mesh, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER) 368bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMultiMeshProxy, size_t, VisibleInstanceCount, 0u) 378bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMultiMeshProxy, BASE_NS::Math::Vec4, CustomData) 388bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMultiMeshProxy, BASE_NS::Math::Mat4X4, Transforms) 398bf80f4bSopenharmony_ci 408bf80f4bSopenharmony_ci void SetInstanceCount(size_t count) override 418bf80f4bSopenharmony_ci { 428bf80f4bSopenharmony_ci // post to engine 438bf80f4bSopenharmony_ci if (auto sh = sceneHolder_.lock()) { 448bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask( 458bf80f4bSopenharmony_ci [count](auto selfObject) { 468bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) { 478bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 488bf80f4bSopenharmony_ci CORE_NS::Entity mm; 498bf80f4bSopenharmony_ci mm.id = self->handle_; 508bf80f4bSopenharmony_ci sceneHolder->SetInstanceCountMultimeshArray(mm, count); 518bf80f4bSopenharmony_ci } 528bf80f4bSopenharmony_ci } 538bf80f4bSopenharmony_ci return false; 548bf80f4bSopenharmony_ci }, 558bf80f4bSopenharmony_ci GetSelf()), 568bf80f4bSopenharmony_ci false); 578bf80f4bSopenharmony_ci } 588bf80f4bSopenharmony_ci 598bf80f4bSopenharmony_ci // Make sure that array properties are in sync 608bf80f4bSopenharmony_ci auto size = META_ACCESS_PROPERTY(CustomData)->GetSize(); 618bf80f4bSopenharmony_ci assert(size == META_ACCESS_PROPERTY(Transforms)->GetSize()); 628bf80f4bSopenharmony_ci do { 638bf80f4bSopenharmony_ci if (count > size) { 648bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomData)->AddValue({ 1.f, 1.f, 1.f, 1.f }); 658bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Transforms)->AddValue(BASE_NS::Math::IDENTITY_4X4); 668bf80f4bSopenharmony_ci } else if (count < size) { 678bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomData)->RemoveAt(size - 1); 688bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Transforms)->RemoveAt(size - 1); 698bf80f4bSopenharmony_ci } 708bf80f4bSopenharmony_ci size = META_ACCESS_PROPERTY(CustomData)->GetSize(); 718bf80f4bSopenharmony_ci } while (size != count); 728bf80f4bSopenharmony_ci } 738bf80f4bSopenharmony_ci 748bf80f4bSopenharmony_ci SceneHolder::WeakPtr sceneHolder_; 758bf80f4bSopenharmony_ci uint64_t handle_ {}; 768bf80f4bSopenharmony_ci BASE_NS::vector<CORE_NS::Entity> overridenMaterials_; 778bf80f4bSopenharmony_ci 788bf80f4bSopenharmony_ci void Initialize(SceneHolder::Ptr sceneHolder, size_t instanceCount, CORE_NS::Entity baseComponent) override 798bf80f4bSopenharmony_ci { 808bf80f4bSopenharmony_ci sceneHolder_ = sceneHolder; 818bf80f4bSopenharmony_ci if (auto sh = sceneHolder) { 828bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask( 838bf80f4bSopenharmony_ci [baseComponent](auto sceneHolder, auto self) { 848bf80f4bSopenharmony_ci auto entity = sceneHolder->CreateMultiMeshInstance(baseComponent); 858bf80f4bSopenharmony_ci static_cast<MultiMeshImpl*>(self.get())->handle_ = entity.id; 868bf80f4bSopenharmony_ci 878bf80f4bSopenharmony_ci return false; 888bf80f4bSopenharmony_ci }, 898bf80f4bSopenharmony_ci sceneHolder_, GetSelf()), 908bf80f4bSopenharmony_ci false); 918bf80f4bSopenharmony_ci } 928bf80f4bSopenharmony_ci SetInstanceCount(instanceCount); 938bf80f4bSopenharmony_ci } 948bf80f4bSopenharmony_ci 958bf80f4bSopenharmony_ci bool Build(const IMetadata::Ptr& data) override 968bf80f4bSopenharmony_ci { 978bf80f4bSopenharmony_ci // subscribe mesh changes 988bf80f4bSopenharmony_ci Mesh()->OnChanged()->AddHandler( 998bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() { 1008bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 1018bf80f4bSopenharmony_ci if (auto sh = self->sceneHolder_.lock()) { 1028bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask([weak]() { 1038bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 1048bf80f4bSopenharmony_ci auto mesh = interface_pointer_cast<INodeEcsInterfacePrivate>(self->Mesh()->GetValue()); 1058bf80f4bSopenharmony_ci if (!mesh || !mesh->EcsObject()) { 1068bf80f4bSopenharmony_ci return false; // Not sure if user should be able to reset ecs mesh by 1078bf80f4bSopenharmony_ci // setting the property as null 1088bf80f4bSopenharmony_ci } 1098bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 1108bf80f4bSopenharmony_ci CORE_NS::Entity mm; 1118bf80f4bSopenharmony_ci mm.id = self->handle_; 1128bf80f4bSopenharmony_ci sceneHolder->SetMeshMultimeshArray(mm, mesh->EcsObject()->GetEntity()); 1138bf80f4bSopenharmony_ci } 1148bf80f4bSopenharmony_ci } 1158bf80f4bSopenharmony_ci return false; 1168bf80f4bSopenharmony_ci }), 1178bf80f4bSopenharmony_ci false); 1188bf80f4bSopenharmony_ci } 1198bf80f4bSopenharmony_ci } 1208bf80f4bSopenharmony_ci }), 1218bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 1228bf80f4bSopenharmony_ci 1238bf80f4bSopenharmony_ci // subscribe material changes 1248bf80f4bSopenharmony_ci MaterialOverride()->OnChanged()->AddHandler( 1258bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() { 1268bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 1278bf80f4bSopenharmony_ci if (auto sh = self->sceneHolder_.lock()) { 1288bf80f4bSopenharmony_ci sh->QueueEngineTask( 1298bf80f4bSopenharmony_ci MakeTask( 1308bf80f4bSopenharmony_ci [](auto selfObject) { 1318bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) { 1328bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 1338bf80f4bSopenharmony_ci CORE_NS::Entity mm; 1348bf80f4bSopenharmony_ci mm.id = self->handle_; 1358bf80f4bSopenharmony_ci auto material = interface_pointer_cast<INodeEcsInterfacePrivate>( 1368bf80f4bSopenharmony_ci self->MaterialOverride()->GetValue()); 1378bf80f4bSopenharmony_ci if (!material || !material->EcsObject()) { 1388bf80f4bSopenharmony_ci if (!self->overridenMaterials_.empty()) { 1398bf80f4bSopenharmony_ci sceneHolder->ResetOverrideMaterialMultimeshArray( 1408bf80f4bSopenharmony_ci mm, self->overridenMaterials_); 1418bf80f4bSopenharmony_ci } 1428bf80f4bSopenharmony_ci } else { 1438bf80f4bSopenharmony_ci auto backup = sceneHolder->SetOverrideMaterialMultimeshArray( 1448bf80f4bSopenharmony_ci mm, material->EcsObject()->GetEntity()); 1458bf80f4bSopenharmony_ci if (self->overridenMaterials_.empty()) { 1468bf80f4bSopenharmony_ci self->overridenMaterials_ = 1478bf80f4bSopenharmony_ci backup; // store backup only for the first change 1488bf80f4bSopenharmony_ci } 1498bf80f4bSopenharmony_ci } 1508bf80f4bSopenharmony_ci } 1518bf80f4bSopenharmony_ci } 1528bf80f4bSopenharmony_ci return false; 1538bf80f4bSopenharmony_ci }, 1548bf80f4bSopenharmony_ci weak), 1558bf80f4bSopenharmony_ci false); 1568bf80f4bSopenharmony_ci } 1578bf80f4bSopenharmony_ci } 1588bf80f4bSopenharmony_ci }), 1598bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 1608bf80f4bSopenharmony_ci 1618bf80f4bSopenharmony_ci // subscribe visible count changes 1628bf80f4bSopenharmony_ci VisibleInstanceCount()->OnChanged()->AddHandler( 1638bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() { 1648bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 1658bf80f4bSopenharmony_ci auto count = self->VisibleInstanceCount()->GetValue(); 1668bf80f4bSopenharmony_ci if (auto sh = self->sceneHolder_.lock()) { 1678bf80f4bSopenharmony_ci sh->QueueEngineTask(MakeTask( 1688bf80f4bSopenharmony_ci [count](auto selfObject) { 1698bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) { 1708bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 1718bf80f4bSopenharmony_ci CORE_NS::Entity mm; 1728bf80f4bSopenharmony_ci mm.id = self->handle_; 1738bf80f4bSopenharmony_ci sceneHolder->SetVisibleCountMultimeshArray(mm, count); 1748bf80f4bSopenharmony_ci } 1758bf80f4bSopenharmony_ci } 1768bf80f4bSopenharmony_ci return false; 1778bf80f4bSopenharmony_ci }, 1788bf80f4bSopenharmony_ci weak), 1798bf80f4bSopenharmony_ci false); 1808bf80f4bSopenharmony_ci } 1818bf80f4bSopenharmony_ci } 1828bf80f4bSopenharmony_ci }), 1838bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 1848bf80f4bSopenharmony_ci 1858bf80f4bSopenharmony_ci //todo 1868bf80f4bSopenharmony_ci // subscribe CustomData changes, write only 1878bf80f4bSopenharmony_ci /*CustomData()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IMetaArrayProperty:: 1888bf80f4bSopenharmony_ci OnChangedType>([weak = BASE_NS::weak_ptr(GetSelf())]( 1898bf80f4bSopenharmony_ci META::ArrayChangeNotification::ConstPtr ptr) { 1908bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 1918bf80f4bSopenharmony_ci for (auto& ref : ptr->Changes) { 1928bf80f4bSopenharmony_ci if (ref.Type == META::ArrayChangeNotification::MODIFIED || 1938bf80f4bSopenharmony_ci ref.Type == META::ArrayChangeNotification::ADDED) { 1948bf80f4bSopenharmony_ci auto ix = ref.Begin; 1958bf80f4bSopenharmony_ci auto data = self->CustomData()->Get(ix); 1968bf80f4bSopenharmony_ci if (auto sh = self->sceneHolder_.lock()) { 1978bf80f4bSopenharmony_ci sh->QueueEngineTask( 1988bf80f4bSopenharmony_ci MakeTask( 1998bf80f4bSopenharmony_ci [data, ix](auto selfObject) { 2008bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) { 2018bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 2028bf80f4bSopenharmony_ci CORE_NS::Entity mm; 2038bf80f4bSopenharmony_ci mm.id = self->handle_; 2048bf80f4bSopenharmony_ci sceneHolder->SetCustomData(mm, ix, { data.x, data.y, data.z, data.w }); 2058bf80f4bSopenharmony_ci } 2068bf80f4bSopenharmony_ci } 2078bf80f4bSopenharmony_ci return false; 2088bf80f4bSopenharmony_ci }, 2098bf80f4bSopenharmony_ci weak), 2108bf80f4bSopenharmony_ci false); 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci } 2138bf80f4bSopenharmony_ci } 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci }), 2168bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this));*/ 2178bf80f4bSopenharmony_ci 2188bf80f4bSopenharmony_ci //todo 2198bf80f4bSopenharmony_ci // subscribe Transformation changes, write only 2208bf80f4bSopenharmony_ci /* 2218bf80f4bSopenharmony_ci Transforms()->OnChanged()->AddHandler( 2228bf80f4bSopenharmony_ci META_NS::MakeCallback<META_NS::IMetaArrayProperty::OnChangedType>( 2238bf80f4bSopenharmony_ci [weak = BASE_NS::weak_ptr(GetSelf())](META::ArrayChangeNotification::ConstPtr ptr) { 2248bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) { 2258bf80f4bSopenharmony_ci for (auto& ref : ptr->Changes) { 2268bf80f4bSopenharmony_ci if (ref.Type == META::ArrayChangeNotification::MODIFIED || 2278bf80f4bSopenharmony_ci ref.Type == META::ArrayChangeNotification::ADDED) { 2288bf80f4bSopenharmony_ci auto ix = ref.Begin; 2298bf80f4bSopenharmony_ci auto data = self->Transforms()->Get(ix); 2308bf80f4bSopenharmony_ci if (auto sh = self->sceneHolder_.lock()) { 2318bf80f4bSopenharmony_ci sh->QueueEngineTask( 2328bf80f4bSopenharmony_ci MakeTask( 2338bf80f4bSopenharmony_ci [data, ix](auto selfObject) { 2348bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) { 2358bf80f4bSopenharmony_ci if (auto sceneHolder = self->sceneHolder_.lock()) { 2368bf80f4bSopenharmony_ci CORE_NS::Entity mm; 2378bf80f4bSopenharmony_ci mm.id = self->handle_; 2388bf80f4bSopenharmony_ci sceneHolder->SetTransformation(mm, ix, data); 2398bf80f4bSopenharmony_ci } 2408bf80f4bSopenharmony_ci } 2418bf80f4bSopenharmony_ci return false; 2428bf80f4bSopenharmony_ci }, 2438bf80f4bSopenharmony_ci weak), 2448bf80f4bSopenharmony_ci false); 2458bf80f4bSopenharmony_ci } 2468bf80f4bSopenharmony_ci } 2478bf80f4bSopenharmony_ci } 2488bf80f4bSopenharmony_ci } 2498bf80f4bSopenharmony_ci }), 2508bf80f4bSopenharmony_ci reinterpret_cast<uint64_t>(this)); 2518bf80f4bSopenharmony_ci */ 2528bf80f4bSopenharmony_ci return true; 2538bf80f4bSopenharmony_ci } 2548bf80f4bSopenharmony_ci}; 2558bf80f4bSopenharmony_ci} // namespace 2568bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 2578bf80f4bSopenharmony_civoid RegisterMultiMeshImpl() 2588bf80f4bSopenharmony_ci{ 2598bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().RegisterObjectType<MultiMeshImpl>(); 2608bf80f4bSopenharmony_ci} 2618bf80f4bSopenharmony_civoid UnregisterMultiMeshImpl() 2628bf80f4bSopenharmony_ci{ 2638bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().UnregisterObjectType<MultiMeshImpl>(); 2648bf80f4bSopenharmony_ci} 2658bf80f4bSopenharmony_ci 2668bf80f4bSopenharmony_ciSCENE_END_NAMESPACE()