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 <3d/ecs/components/material_component.h> 178bf80f4bSopenharmony_ci#include <atomic> 188bf80f4bSopenharmony_ci#include <meta/api/make_callback.h> 198bf80f4bSopenharmony_ci#include <meta/interface/detail/array_property.h> 208bf80f4bSopenharmony_ci#include <meta/api/property/array_element_bind.h> 218bf80f4bSopenharmony_ci#include <meta/ext/concrete_base_object.h> 228bf80f4bSopenharmony_ci 238bf80f4bSopenharmony_ci#include "bind_templates.inl" 248bf80f4bSopenharmony_ci#include "intf_proxy_object_holder.h" 258bf80f4bSopenharmony_ci#include "node_impl.h" 268bf80f4bSopenharmony_ci#include "task_utils.h" 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ciusing CORE3D_NS::MaterialComponent; 298bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 308bf80f4bSopenharmony_ciMETA_TYPE(MaterialComponent::TextureInfo); 318bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 328bf80f4bSopenharmony_ci 338bf80f4bSopenharmony_ciusing SCENE_NS::MakeTask; 348bf80f4bSopenharmony_ci#define GET_HOLDER(info) interface_pointer_cast<SCENE_NS::IProxyObjectHolder>(info)->Holder() 358bf80f4bSopenharmony_ci 368bf80f4bSopenharmony_cinamespace { 378bf80f4bSopenharmony_citemplate<typename... Types> 388bf80f4bSopenharmony_ciinline void BindMetaProperty( 398bf80f4bSopenharmony_ci PropertyHandlerArrayHolder& handler, META_NS::IProperty::Ptr& clone, META_NS::IProperty::Ptr& prop) 408bf80f4bSopenharmony_ci{ 418bf80f4bSopenharmony_ci (BindIfCorrectType<Types>(handler, clone, prop) || ...); 428bf80f4bSopenharmony_ci} 438bf80f4bSopenharmony_ci 448bf80f4bSopenharmony_civoid BindMetaProperty( 458bf80f4bSopenharmony_ci PropertyHandlerArrayHolder& handler, META_NS::IProperty::Ptr& clone, META_NS::IProperty::Ptr& prop) 468bf80f4bSopenharmony_ci{ 478bf80f4bSopenharmony_ci BindMetaProperty<BASE_NS::Math::Vec4, BASE_NS::Math::UVec4, BASE_NS::Math::IVec4, BASE_NS::Math::Vec3, 488bf80f4bSopenharmony_ci BASE_NS::Math::UVec3, BASE_NS::Math::IVec3, BASE_NS::Math::Vec2, BASE_NS::Math::UVec2, BASE_NS::Math::IVec2, 498bf80f4bSopenharmony_ci float, int32_t, uint32_t, BASE_NS::Math::Mat3X3, BASE_NS::Math::Mat4X4, bool, CORE_NS::Entity, 508bf80f4bSopenharmony_ci CORE_NS::EntityReference>(handler, clone, prop); 518bf80f4bSopenharmony_ci} 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_cibool IsGltfResource(BASE_NS::string_view uri, BASE_NS::string_view resourcePath) 548bf80f4bSopenharmony_ci{ 558bf80f4bSopenharmony_ci // Image uris loaded form a glTF are in a format like this: "file://model.gltf/images/0" 568bf80f4bSopenharmony_ci 578bf80f4bSopenharmony_ci // There must be an identifier string at the end of the uri after the '/'. 588bf80f4bSopenharmony_ci const auto idSeparator = uri.find_last_of('/'); 598bf80f4bSopenharmony_ci if (idSeparator == BASE_NS::string_view::npos) { 608bf80f4bSopenharmony_ci return false; 618bf80f4bSopenharmony_ci } 628bf80f4bSopenharmony_ci 638bf80f4bSopenharmony_ci // We don't care what is after the separator, but it should be preceded by <resourcePath>" e.g. /images". 648bf80f4bSopenharmony_ci auto rest = uri.substr(0, idSeparator); 658bf80f4bSopenharmony_ci if (!rest.ends_with(resourcePath)) { 668bf80f4bSopenharmony_ci return false; 678bf80f4bSopenharmony_ci } 688bf80f4bSopenharmony_ci rest = rest.substr(0, rest.size() - resourcePath.size()); 698bf80f4bSopenharmony_ci 708bf80f4bSopenharmony_ci // Take the last 5 characters in lower case to check the extension. 718bf80f4bSopenharmony_ci if (rest.size() < 5) { 728bf80f4bSopenharmony_ci return false; 738bf80f4bSopenharmony_ci } 748bf80f4bSopenharmony_ci const auto extension = BASE_NS::string(rest.substr(rest.size() - 5, 5)).toLower(); 758bf80f4bSopenharmony_ci if (!extension.ends_with(".glb") && !extension.ends_with(".gltf")) { 768bf80f4bSopenharmony_ci return false; 778bf80f4bSopenharmony_ci } 788bf80f4bSopenharmony_ci 798bf80f4bSopenharmony_ci return true; 808bf80f4bSopenharmony_ci} 818bf80f4bSopenharmony_ci 828bf80f4bSopenharmony_cibool IsGltfImage(BASE_NS::string_view uri) 838bf80f4bSopenharmony_ci{ 848bf80f4bSopenharmony_ci return IsGltfResource(uri, "/images"); 858bf80f4bSopenharmony_ci} 868bf80f4bSopenharmony_ci 878bf80f4bSopenharmony_cibool IsGltfMaterial(BASE_NS::string_view uri) 888bf80f4bSopenharmony_ci{ 898bf80f4bSopenharmony_ci return IsGltfResource(uri, "/materials"); 908bf80f4bSopenharmony_ci} 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_ciclass MaterialImpl : public META_NS::ConcreteBaseMetaObjectFwd<MaterialImpl, NodeImpl, SCENE_NS::ClassId::Material, 938bf80f4bSopenharmony_ci SCENE_NS::IMaterial, ITextureStorage> { 948bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view MATERIAL_COMPONENT_NAME = "MaterialComponent"; 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view CUSTOM_PREFIX = "MaterialComponent.customProperties."; 978bf80f4bSopenharmony_ci static constexpr size_t CUSTOM_PREFIX_SIZE = CUSTOM_PREFIX.size(); 988bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view TEXTURE_PREFIX = "MaterialComponent.TextureInfo."; 998bf80f4bSopenharmony_ci static constexpr size_t TEXTURE_PREFIX_SIZE = TEXTURE_PREFIX.size(); 1008bf80f4bSopenharmony_ci 1018bf80f4bSopenharmony_ci bool Build(const IMetadata::Ptr& data) override 1028bf80f4bSopenharmony_ci { 1038bf80f4bSopenharmony_ci bool ret = false; 1048bf80f4bSopenharmony_ci if (ret = NodeImpl::Build(data); ret) { 1058bf80f4bSopenharmony_ci // bind everything from material component, otherwise obey the wishes of other components 1068bf80f4bSopenharmony_ci PropertyNameMask()[MATERIAL_COMPONENT_NAME] = {}; 1078bf80f4bSopenharmony_ci OnTypeChanged(); // initialize inputs 1088bf80f4bSopenharmony_ci } 1098bf80f4bSopenharmony_ci return ret; 1108bf80f4bSopenharmony_ci } 1118bf80f4bSopenharmony_ci 1128bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, uint8_t, Type, 0) 1138bf80f4bSopenharmony_ci 1148bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, float, AlphaCutoff, 1.f) 1158bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, uint32_t, LightingFlags, 1168bf80f4bSopenharmony_ci CORE3D_NS::MaterialComponent::LightingFlagBits::SHADOW_RECEIVER_BIT | 1178bf80f4bSopenharmony_ci CORE3D_NS::MaterialComponent::LightingFlagBits::SHADOW_CASTER_BIT | 1188bf80f4bSopenharmony_ci CORE3D_NS::MaterialComponent::LightingFlagBits::PUNCTUAL_LIGHT_RECEIVER_BIT | 1198bf80f4bSopenharmony_ci CORE3D_NS::MaterialComponent::LightingFlagBits::INDIRECT_LIGHT_RECEIVER_BIT) 1208bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::IShader::Ptr, MaterialShader, {}) 1218bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::IGraphicsState::Ptr, MaterialShaderState, {}) 1228bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::IShader::Ptr, DepthShader, {}) 1238bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::IGraphicsState::Ptr, DepthShaderState, {}) 1248bf80f4bSopenharmony_ci 1258bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(SCENE_NS::IMaterial, META_NS::IObject::Ptr, CustomProperties, {}) 1268bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::ITextureInfo::Ptr, Inputs, {}) 1278bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMaterial, SCENE_NS::ITextureInfo::Ptr, Textures, {}) 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_ci bool updatingInputs_ { false }; 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_ci void Activate() override 1338bf80f4bSopenharmony_ci { 1348bf80f4bSopenharmony_ci auto sceneHolder = SceneHolder(); 1358bf80f4bSopenharmony_ci if (!sceneHolder) { 1368bf80f4bSopenharmony_ci return; 1378bf80f4bSopenharmony_ci } 1388bf80f4bSopenharmony_ci 1398bf80f4bSopenharmony_ci auto task = META_NS::MakeCallback<META_NS::ITaskQueueTask>( 1408bf80f4bSopenharmony_ci [e = ecsObject_->GetEntity(), w = BASE_NS::weak_ptr(sceneHolder)] { 1418bf80f4bSopenharmony_ci auto sh = w.lock(); 1428bf80f4bSopenharmony_ci if (sh) { 1438bf80f4bSopenharmony_ci sh->SetEntityActive(e, true); 1448bf80f4bSopenharmony_ci } 1458bf80f4bSopenharmony_ci return false; 1468bf80f4bSopenharmony_ci }); 1478bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask(task, false); 1488bf80f4bSopenharmony_ci } 1498bf80f4bSopenharmony_ci 1508bf80f4bSopenharmony_ci void Deactivate() override 1518bf80f4bSopenharmony_ci { 1528bf80f4bSopenharmony_ci auto sceneHolder = SceneHolder(); 1538bf80f4bSopenharmony_ci if (!sceneHolder) { 1548bf80f4bSopenharmony_ci return; 1558bf80f4bSopenharmony_ci } 1568bf80f4bSopenharmony_ci 1578bf80f4bSopenharmony_ci auto task = META_NS::MakeCallback<META_NS::ITaskQueueTask>( 1588bf80f4bSopenharmony_ci [e = ecsObject_->GetEntity(), w = BASE_NS::weak_ptr(sceneHolder)] { 1598bf80f4bSopenharmony_ci auto sh = w.lock(); 1608bf80f4bSopenharmony_ci if (sh) { 1618bf80f4bSopenharmony_ci sh->SetEntityActive(e, false); 1628bf80f4bSopenharmony_ci } 1638bf80f4bSopenharmony_ci return false; 1648bf80f4bSopenharmony_ci }); 1658bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask(task, false); 1668bf80f4bSopenharmony_ci } 1678bf80f4bSopenharmony_ci 1688bf80f4bSopenharmony_ci void SetPath(const BASE_NS::string& path, const BASE_NS::string& name, CORE_NS::Entity entity) override 1698bf80f4bSopenharmony_ci { 1708bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Path)->SetValue(path); 1718bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Name)->SetValue(name); 1728bf80f4bSopenharmony_ci 1738bf80f4bSopenharmony_ci if (auto iscene = GetScene()) { 1748bf80f4bSopenharmony_ci iscene->UpdateCachedReference(GetSelf<SCENE_NS::INode>()); 1758bf80f4bSopenharmony_ci } 1768bf80f4bSopenharmony_ci if (auto scene = EcsScene()) { 1778bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTING); 1788bf80f4bSopenharmony_ci 1798bf80f4bSopenharmony_ci initializeTaskToken_ = scene->AddEngineTask(MakeTask([me = BASE_NS::weak_ptr(GetSelf()), 1808bf80f4bSopenharmony_ci materialName = name, 1818bf80f4bSopenharmony_ci fullpath = path + name, entity]() { 1828bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(me.lock())) { 1838bf80f4bSopenharmony_ci if (auto sceneHolder = self->SceneHolder()) { 1848bf80f4bSopenharmony_ci CORE_NS::Entity materialEntity = entity; 1858bf80f4bSopenharmony_ci 1868bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(materialEntity)) { 1878bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("binding material: %s", materialName.c_str()); 1888bf80f4bSopenharmony_ci if (auto proxyIf = interface_pointer_cast<SCENE_NS::IEcsProxyObject>(self->EcsObject())) { 1898bf80f4bSopenharmony_ci proxyIf->SetCommonListener(sceneHolder->GetCommonEcsListener()); 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci self->EcsObject()->DefineTargetProperties(self->PropertyNameMask()); 1928bf80f4bSopenharmony_ci self->EcsObject()->SetEntity(sceneHolder->GetEcs(), materialEntity); 1938bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 1948bf80f4bSopenharmony_ci MakeTask( 1958bf80f4bSopenharmony_ci [fullpath](auto selfObject) { 1968bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 1978bf80f4bSopenharmony_ci self->CompleteInitialization(fullpath); 1988bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_CONNECTED); 1998bf80f4bSopenharmony_ci if (auto node = interface_pointer_cast<SCENE_NS::INode>(selfObject)) { 2008bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(node->OnLoaded()); 2018bf80f4bSopenharmony_ci } 2028bf80f4bSopenharmony_ci } 2038bf80f4bSopenharmony_ci return false; 2048bf80f4bSopenharmony_ci }, 2058bf80f4bSopenharmony_ci me), 2068bf80f4bSopenharmony_ci false); 2078bf80f4bSopenharmony_ci } else { 2088bf80f4bSopenharmony_ci CORE_LOG_W("Could not find '%s' material", fullpath.c_str()); 2098bf80f4bSopenharmony_ci sceneHolder->QueueApplicationTask( 2108bf80f4bSopenharmony_ci MakeTask( 2118bf80f4bSopenharmony_ci [](auto selfObject) { 2128bf80f4bSopenharmony_ci if (auto self = static_pointer_cast<NodeImpl>(selfObject)) { 2138bf80f4bSopenharmony_ci self->SetStatus(SCENE_NS::INode::NODE_STATUS_DISCONNECTED); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci return false; 2168bf80f4bSopenharmony_ci }, 2178bf80f4bSopenharmony_ci me), 2188bf80f4bSopenharmony_ci false); 2198bf80f4bSopenharmony_ci } 2208bf80f4bSopenharmony_ci } 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci return false; 2238bf80f4bSopenharmony_ci }), 2248bf80f4bSopenharmony_ci false); 2258bf80f4bSopenharmony_ci } 2268bf80f4bSopenharmony_ci } 2278bf80f4bSopenharmony_ci 2288bf80f4bSopenharmony_cipublic: // ISerialization 2298bf80f4bSopenharmony_ci void ApplyTextureInfoImage(size_t arrayIndex, SCENE_NS::ITextureInfo& info) 2308bf80f4bSopenharmony_ci { 2318bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 2328bf80f4bSopenharmony_ci bool shouldReset { true }; 2338bf80f4bSopenharmony_ci auto value = info.Image()->GetValue(); 2348bf80f4bSopenharmony_ci if (auto uriBitmap = interface_cast<SCENE_NS::IBitmap>(value)) { 2358bf80f4bSopenharmony_ci auto uri = META_NS::GetValue(uriBitmap->Uri()); 2368bf80f4bSopenharmony_ci if (!uri.empty()) { 2378bf80f4bSopenharmony_ci shouldReset = false; 2388bf80f4bSopenharmony_ci 2398bf80f4bSopenharmony_ci if (IsGltfImage(uri)) { 2408bf80f4bSopenharmony_ci return; 2418bf80f4bSopenharmony_ci } 2428bf80f4bSopenharmony_ci 2438bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask( 2448bf80f4bSopenharmony_ci MakeTask( 2458bf80f4bSopenharmony_ci [uri, entityId = EcsObject()->GetEntity().id, arrayIndex](auto sh) { 2468bf80f4bSopenharmony_ci CORE_NS::Entity target { entityId }; 2478bf80f4bSopenharmony_ci auto image = sh->LoadImage(uri); 2488bf80f4bSopenharmony_ci sh->SetTexture(arrayIndex, target, image); 2498bf80f4bSopenharmony_ci 2508bf80f4bSopenharmony_ci return false; 2518bf80f4bSopenharmony_ci }, 2528bf80f4bSopenharmony_ci sceneHolder), 2538bf80f4bSopenharmony_ci false); 2548bf80f4bSopenharmony_ci } 2558bf80f4bSopenharmony_ci } 2568bf80f4bSopenharmony_ci if (shouldReset) { 2578bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask(MakeTask( 2588bf80f4bSopenharmony_ci [entity = EcsObject()->GetEntity(), arrayIndex](auto sh) { 2598bf80f4bSopenharmony_ci sh->SetTexture(arrayIndex, entity, {}); 2608bf80f4bSopenharmony_ci return false; 2618bf80f4bSopenharmony_ci }, 2628bf80f4bSopenharmony_ci sceneHolder), 2638bf80f4bSopenharmony_ci false); 2648bf80f4bSopenharmony_ci } 2658bf80f4bSopenharmony_ci } 2668bf80f4bSopenharmony_ci } 2678bf80f4bSopenharmony_ci 2688bf80f4bSopenharmony_ci void SubscribeToTextureInfo(size_t arrayIndex, SCENE_NS::ITextureInfo::Ptr info) 2698bf80f4bSopenharmony_ci { 2708bf80f4bSopenharmony_ci info->SetTextureSlotIndex(arrayIndex); 2718bf80f4bSopenharmony_ci 2728bf80f4bSopenharmony_ci // EcsObject would provide use entity ref while we would like to use the enums to define which 2738bf80f4bSopenharmony_ci // sampler to use Perhaps we create new factory method for scene-interface and then apply the direct 2748bf80f4bSopenharmony_ci // biding from now on 2758bf80f4bSopenharmony_ci GET_HOLDER(info) 2768bf80f4bSopenharmony_ci .NewHandler(info->Sampler(), nullptr) 2778bf80f4bSopenharmony_ci .Subscribe(info->Sampler(), [this, prop = info->Sampler(), arrayIndex]() { 2788bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 2798bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask( 2808bf80f4bSopenharmony_ci MakeTask( 2818bf80f4bSopenharmony_ci [value = prop->GetValue(), entityId = EcsObject()->GetEntity().id, arrayIndex](auto sh) { 2828bf80f4bSopenharmony_ci CORE_NS::Entity target { entityId }; 2838bf80f4bSopenharmony_ci sh->SetSampler( 2848bf80f4bSopenharmony_ci arrayIndex, target, static_cast<SCENE_NS::ITextureInfo::SamplerId>(value)); 2858bf80f4bSopenharmony_ci 2868bf80f4bSopenharmony_ci return false; 2878bf80f4bSopenharmony_ci }, 2888bf80f4bSopenharmony_ci sceneHolder), 2898bf80f4bSopenharmony_ci false); 2908bf80f4bSopenharmony_ci } 2918bf80f4bSopenharmony_ci }); 2928bf80f4bSopenharmony_ci 2938bf80f4bSopenharmony_ci GET_HOLDER(info) 2948bf80f4bSopenharmony_ci .NewHandler(info->Image(), nullptr) 2958bf80f4bSopenharmony_ci .Subscribe(info->Image(), 2968bf80f4bSopenharmony_ci [this, textureInfo = info.get(), arrayIndex]() { ApplyTextureInfoImage(arrayIndex, *textureInfo); }); 2978bf80f4bSopenharmony_ci } 2988bf80f4bSopenharmony_ci /* 2998bf80f4bSopenharmony_ci bool Export( 3008bf80f4bSopenharmony_ci META_NS::Serialization::IExportContext& context, META_NS::Serialization::ClassPrimitive& value) const override 3018bf80f4bSopenharmony_ci { 3028bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("MaterialImpl::%s %s", __func__, Name()->Get().c_str()); 3038bf80f4bSopenharmony_ci 3048bf80f4bSopenharmony_ci // This is not a shared material and therefore we will export it here. 3058bf80f4bSopenharmony_ci return Fwd::Export(context, value); 3068bf80f4bSopenharmony_ci } 3078bf80f4bSopenharmony_ci 3088bf80f4bSopenharmony_ci bool Import( 3098bf80f4bSopenharmony_ci META_NS::Serialization::IImportContext& context, const META_NS::Serialization::ClassPrimitive& value) override 3108bf80f4bSopenharmony_ci { 3118bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Inputs)->Reset(); 3128bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomProperties)->Reset(); 3138bf80f4bSopenharmony_ci 3148bf80f4bSopenharmony_ci if (!Fwd::Import(context, value)) { 3158bf80f4bSopenharmony_ci return false; 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci 3188bf80f4bSopenharmony_ci if (Inputs()) { 3198bf80f4bSopenharmony_ci // Subscribe all texture infos. 3208bf80f4bSopenharmony_ci for (auto i = 0; i < Inputs()->Size(); ++i) { 3218bf80f4bSopenharmony_ci auto info = Inputs()->Get(i); 3228bf80f4bSopenharmony_ci 3238bf80f4bSopenharmony_ci auto textureSlotIndex = info->GetTextureSlotIndex(); 3248bf80f4bSopenharmony_ci if (textureSlotIndex == ~0u) { 3258bf80f4bSopenharmony_ci textureSlotIndex = i; 3268bf80f4bSopenharmony_ci } 3278bf80f4bSopenharmony_ci 3288bf80f4bSopenharmony_ci info->SetTextureSlotIndex(textureSlotIndex); 3298bf80f4bSopenharmony_ci } 3308bf80f4bSopenharmony_ci } 3318bf80f4bSopenharmony_ci 3328bf80f4bSopenharmony_ci return true; 3338bf80f4bSopenharmony_ci } 3348bf80f4bSopenharmony_ci */ 3358bf80f4bSopenharmony_ci SCENE_NS::ITextureInfo::Ptr GetTextureInfoByIndex( 3368bf80f4bSopenharmony_ci uint32_t index, BASE_NS::vector<SCENE_NS::ITextureInfo::Ptr>& textures) 3378bf80f4bSopenharmony_ci { 3388bf80f4bSopenharmony_ci // First, look from current inputs. 3398bf80f4bSopenharmony_ci auto existingInfo = GetTextureInfo(index); 3408bf80f4bSopenharmony_ci if (existingInfo) { 3418bf80f4bSopenharmony_ci // Found existing info, we absolutely want to re-use it. 3428bf80f4bSopenharmony_ci // This is to keep e.g. property animations working (they bind to this exact object). 3438bf80f4bSopenharmony_ci auto it = std::find(textures.begin(), textures.end(), existingInfo); 3448bf80f4bSopenharmony_ci if (it == textures.end()) { 3458bf80f4bSopenharmony_ci // Add this info to textures list. 3468bf80f4bSopenharmony_ci textures.push_back(existingInfo); 3478bf80f4bSopenharmony_ci } 3488bf80f4bSopenharmony_ci return existingInfo; 3498bf80f4bSopenharmony_ci } 3508bf80f4bSopenharmony_ci 3518bf80f4bSopenharmony_ci for (auto& info : textures) { 3528bf80f4bSopenharmony_ci if (info->GetTextureSlotIndex() == index) { 3538bf80f4bSopenharmony_ci return info; 3548bf80f4bSopenharmony_ci } 3558bf80f4bSopenharmony_ci } 3568bf80f4bSopenharmony_ci 3578bf80f4bSopenharmony_ci return {}; 3588bf80f4bSopenharmony_ci } 3598bf80f4bSopenharmony_ci 3608bf80f4bSopenharmony_ci SCENE_NS::ITextureInfo::Ptr BindTextureSlot(const BASE_NS::string_view& propName, META_NS::IMetadata::Ptr& meta, 3618bf80f4bSopenharmony_ci BASE_NS::vector<SCENE_NS::ITextureInfo::Ptr>& textures) 3628bf80f4bSopenharmony_ci { 3638bf80f4bSopenharmony_ci SCENE_NS::ITextureInfo::Ptr result; 3648bf80f4bSopenharmony_ci 3658bf80f4bSopenharmony_ci // fork out the identifier 3668bf80f4bSopenharmony_ci size_t ix = TEXTURE_PREFIX_SIZE; 3678bf80f4bSopenharmony_ci ix = propName.find('.', ix + 1); 3688bf80f4bSopenharmony_ci size_t textureSlotId = 0; 3698bf80f4bSopenharmony_ci 3708bf80f4bSopenharmony_ci if (ix == BASE_NS::string_view::npos) { 3718bf80f4bSopenharmony_ci return result; 3728bf80f4bSopenharmony_ci } else { 3738bf80f4bSopenharmony_ci // how cool is this 3748bf80f4bSopenharmony_ci for (int ii = TEXTURE_PREFIX_SIZE; ii < ix; ii++) { 3758bf80f4bSopenharmony_ci textureSlotId += (propName[ii] - '0') * pow(10, (ix - ii - 1)); // 10 exponent 3768bf80f4bSopenharmony_ci } 3778bf80f4bSopenharmony_ci } 3788bf80f4bSopenharmony_ci 3798bf80f4bSopenharmony_ci auto textureSlotIndex = textureSlotId - 1; 3808bf80f4bSopenharmony_ci 3818bf80f4bSopenharmony_ci bool applyPropertyToEcs = false; 3828bf80f4bSopenharmony_ci if (textureSlotId) { 3838bf80f4bSopenharmony_ci auto info = GetTextureInfoByIndex(textureSlotIndex, textures); 3848bf80f4bSopenharmony_ci if (!info) { 3858bf80f4bSopenharmony_ci info = GetObjectRegistry().Create<SCENE_NS::ITextureInfo>(SCENE_NS::ClassId::TextureInfo); 3868bf80f4bSopenharmony_ci if (!info) { 3878bf80f4bSopenharmony_ci return {}; 3888bf80f4bSopenharmony_ci } 3898bf80f4bSopenharmony_ci 3908bf80f4bSopenharmony_ci info->SetTextureSlotIndex(textureSlotIndex); 3918bf80f4bSopenharmony_ci textures.push_back(info); 3928bf80f4bSopenharmony_ci } 3938bf80f4bSopenharmony_ci 3948bf80f4bSopenharmony_ci GET_HOLDER(info).SetSceneHolder(SceneHolder()); 3958bf80f4bSopenharmony_ci 3968bf80f4bSopenharmony_ci { 3978bf80f4bSopenharmony_ci // Update name. 3988bf80f4bSopenharmony_ci BASE_NS::string textureSlotName(propName.substr(ix + 1)); 3998bf80f4bSopenharmony_ci size_t dotIndex = textureSlotName.find('.'); 4008bf80f4bSopenharmony_ci if (dotIndex != BASE_NS::string_view::npos && dotIndex != 0) { 4018bf80f4bSopenharmony_ci textureSlotName = textureSlotName.substr(0, dotIndex); 4028bf80f4bSopenharmony_ci } 4038bf80f4bSopenharmony_ci if (GetValue(info->Name()) != textureSlotName) { 4048bf80f4bSopenharmony_ci SetValue(info->Name(), textureSlotName); 4058bf80f4bSopenharmony_ci } 4068bf80f4bSopenharmony_ci } 4078bf80f4bSopenharmony_ci 4088bf80f4bSopenharmony_ci // progress one more dot 4098bf80f4bSopenharmony_ci ix = propName.find('.', ix + 1); 4108bf80f4bSopenharmony_ci 4118bf80f4bSopenharmony_ci BASE_NS::string propertyName(propName.substr(ix)); 4128bf80f4bSopenharmony_ci if (propertyName == ".factor") { 4138bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4>(GET_HOLDER(info), info->Factor(), meta, propName); 4148bf80f4bSopenharmony_ci } else if (propertyName == ".transform.translation") { 4158bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec2>(GET_HOLDER(info), info->Translation(), meta, propName); 4168bf80f4bSopenharmony_ci } else if (propertyName == ".transform.rotation") { 4178bf80f4bSopenharmony_ci BindChanges<float>(GET_HOLDER(info), info->Rotation(), meta, propName); 4188bf80f4bSopenharmony_ci } else if (propertyName == ".transform.scale") { 4198bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec2>(GET_HOLDER(info), info->Scale(), meta, propName); 4208bf80f4bSopenharmony_ci } else if (propertyName == ".image") { 4218bf80f4bSopenharmony_ci auto prop = meta->GetPropertyByName(propName); 4228bf80f4bSopenharmony_ci 4238bf80f4bSopenharmony_ci // Here we will initialize the image property. 4248bf80f4bSopenharmony_ci if (info->Image()->IsValueSet()) { 4258bf80f4bSopenharmony_ci // If the property value is set by the user, we will propagate it to ecs. 4268bf80f4bSopenharmony_ci ApplyTextureInfoImage(textureSlotIndex, *info); 4278bf80f4bSopenharmony_ci } else { 4288bf80f4bSopenharmony_ci // If the property value is not set, we will fetch it from ecs. 4298bf80f4bSopenharmony_ci CheckImageHandle(textureSlotIndex, BASE_NS::weak_ptr<SCENE_NS::ITextureInfo>(info)); 4308bf80f4bSopenharmony_ci } 4318bf80f4bSopenharmony_ci 4328bf80f4bSopenharmony_ci prop->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>( 4338bf80f4bSopenharmony_ci [this, textureSlotIndex, w_info = Base::weak_ptr(info)]() { 4348bf80f4bSopenharmony_ci CheckImageHandle(textureSlotIndex, w_info); 4358bf80f4bSopenharmony_ci })); 4368bf80f4bSopenharmony_ci GET_HOLDER(info).MarkRelated(info->Image(), prop); 4378bf80f4bSopenharmony_ci 4388bf80f4bSopenharmony_ci SubscribeToTextureInfo(textureSlotIndex, info); 4398bf80f4bSopenharmony_ci } else if (propertyName == ".sampler") { 4408bf80f4bSopenharmony_ci GET_HOLDER(info).MarkRelated(info->Sampler(), meta->GetPropertyByName(propName)); 4418bf80f4bSopenharmony_ci } 4428bf80f4bSopenharmony_ci 4438bf80f4bSopenharmony_ci result = info; 4448bf80f4bSopenharmony_ci } 4458bf80f4bSopenharmony_ci 4468bf80f4bSopenharmony_ci return result; 4478bf80f4bSopenharmony_ci } 4488bf80f4bSopenharmony_ci 4498bf80f4bSopenharmony_ci void CheckImageHandle(size_t arrayIx, BASE_NS::weak_ptr<SCENE_NS::ITextureInfo> w_info) 4508bf80f4bSopenharmony_ci { 4518bf80f4bSopenharmony_ci // Queue engine task 4528bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 4538bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask( 4548bf80f4bSopenharmony_ci MakeTask( 4558bf80f4bSopenharmony_ci [entity = EcsObject()->GetEntity(), arrayIx, w_info](SceneHolder::Ptr sh) { 4568bf80f4bSopenharmony_ci // resolve entity 4578bf80f4bSopenharmony_ci CORE_NS::Entity image; 4588bf80f4bSopenharmony_ci BASE_NS::string name; 4598bf80f4bSopenharmony_ci RENDER_NS::GpuImageDesc imageDesc; 4608bf80f4bSopenharmony_ci RENDER_NS::RenderHandleReference handle; 4618bf80f4bSopenharmony_ci if (sh->GetImageEntity(entity, arrayIx, image)) { 4628bf80f4bSopenharmony_ci // get entity by uri 4638bf80f4bSopenharmony_ci sh->GetEntityUri(image, name); 4648bf80f4bSopenharmony_ci sh->GetImageHandle(image, handle, imageDesc); 4658bf80f4bSopenharmony_ci } 4668bf80f4bSopenharmony_ci SCENE_PLUGIN_VERBOSE_LOG("%s: resolved name: %s", __func__, name.c_str()); 4678bf80f4bSopenharmony_ci // if we get something valid out of those 4688bf80f4bSopenharmony_ci // let the toolkit side check if we have a bitmap and its uri matches 4698bf80f4bSopenharmony_ci if (!name.empty()) { 4708bf80f4bSopenharmony_ci sh->QueueEngineTask( 4718bf80f4bSopenharmony_ci MakeTask( 4728bf80f4bSopenharmony_ci [name](auto info, RENDER_NS::RenderHandleReference handle, auto size) { 4738bf80f4bSopenharmony_ci if (auto bitmap = META_NS::GetValue(info->Image())) { 4748bf80f4bSopenharmony_ci if (auto uriBitmap = interface_cast<SCENE_NS::IBitmap>(bitmap)) { 4758bf80f4bSopenharmony_ci if (auto uri = META_NS::GetValue(uriBitmap->Uri()); 4768bf80f4bSopenharmony_ci !uri.empty() && (uri == name)) { 4778bf80f4bSopenharmony_ci return false; 4788bf80f4bSopenharmony_ci } 4798bf80f4bSopenharmony_ci } 4808bf80f4bSopenharmony_ci } 4818bf80f4bSopenharmony_ci auto uriBitmap = META_NS::GetObjectRegistry().Create<SCENE_NS::IBitmap>( 4828bf80f4bSopenharmony_ci SCENE_NS::ClassId::Bitmap); 4838bf80f4bSopenharmony_ci META_NS::SetValue(uriBitmap->Uri(), name); 4848bf80f4bSopenharmony_ci // TODO: should parse the renderhandle from the entity and set it to the bitmap 4858bf80f4bSopenharmony_ci // also. as we "create" it from the ecs, so the image SHOULD already be loaded. 4868bf80f4bSopenharmony_ci uriBitmap->SetRenderHandle(handle, size); 4878bf80f4bSopenharmony_ci info->Image()->SetDefaultValue(uriBitmap, true); 4888bf80f4bSopenharmony_ci return false; 4898bf80f4bSopenharmony_ci }, 4908bf80f4bSopenharmony_ci w_info, handle, BASE_NS::Math::UVec2(imageDesc.width, imageDesc.height)), 4918bf80f4bSopenharmony_ci false); 4928bf80f4bSopenharmony_ci } 4938bf80f4bSopenharmony_ci return false; 4948bf80f4bSopenharmony_ci }, 4958bf80f4bSopenharmony_ci sceneHolder), 4968bf80f4bSopenharmony_ci false); 4978bf80f4bSopenharmony_ci } 4988bf80f4bSopenharmony_ci } 4998bf80f4bSopenharmony_ci 5008bf80f4bSopenharmony_ci SCENE_NS::ITextureInfo::Ptr GetTextureInfo(size_t ix) const override 5018bf80f4bSopenharmony_ci { 5028bf80f4bSopenharmony_ci if (Inputs()) { 5038bf80f4bSopenharmony_ci for (auto& info : Inputs()->GetValue()) { 5048bf80f4bSopenharmony_ci if (info->GetTextureSlotIndex() == ix) { 5058bf80f4bSopenharmony_ci return info; 5068bf80f4bSopenharmony_ci } 5078bf80f4bSopenharmony_ci } 5088bf80f4bSopenharmony_ci } 5098bf80f4bSopenharmony_ci 5108bf80f4bSopenharmony_ci return SCENE_NS::ITextureInfo::Ptr {}; 5118bf80f4bSopenharmony_ci } 5128bf80f4bSopenharmony_ci 5138bf80f4bSopenharmony_ci void UpdateInputProperties() 5148bf80f4bSopenharmony_ci { 5158bf80f4bSopenharmony_ci auto type = META_NS::GetValue(META_ACCESS_PROPERTY(Type)); 5168bf80f4bSopenharmony_ci bool includeDefaultMappings = 5178bf80f4bSopenharmony_ci (type == SCENE_NS::IMaterial::METALLIC_ROUGHNESS || type == SCENE_NS::IMaterial::SPECULAR_GLOSSINESS || 5188bf80f4bSopenharmony_ci type == SCENE_NS::IMaterial::UNLIT || type == SCENE_NS::IMaterial::UNLIT_SHADOW_ALPHA); 5198bf80f4bSopenharmony_ci 5208bf80f4bSopenharmony_ci // Base Color 5218bf80f4bSopenharmony_ci if (auto meta = 5228bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::BASE_COLOR))) { 5238bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 5248bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 5258bf80f4bSopenharmony_ci meta->RemoveProperty(color); 5268bf80f4bSopenharmony_ci } 5278bf80f4bSopenharmony_ci } else { 5288bf80f4bSopenharmony_ci auto c = META_NS::ConstructProperty<SCENE_NS::Color>(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR); 5298bf80f4bSopenharmony_ci meta->AddProperty(c); 5308bf80f4bSopenharmony_ci } 5318bf80f4bSopenharmony_ci } 5328bf80f4bSopenharmony_ci 5338bf80f4bSopenharmony_ci // Normal 5348bf80f4bSopenharmony_ci if (auto meta = 5358bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::NORMAL))) { 5368bf80f4bSopenharmony_ci if (auto scale = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE)) { 5378bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 5388bf80f4bSopenharmony_ci meta->RemoveProperty(scale); 5398bf80f4bSopenharmony_ci } 5408bf80f4bSopenharmony_ci } else { 5418bf80f4bSopenharmony_ci auto s = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE); 5428bf80f4bSopenharmony_ci meta->AddProperty(s); 5438bf80f4bSopenharmony_ci } 5448bf80f4bSopenharmony_ci } 5458bf80f4bSopenharmony_ci 5468bf80f4bSopenharmony_ci // Material 5478bf80f4bSopenharmony_ci if (auto meta = 5488bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::MATERIAL))) { 5498bf80f4bSopenharmony_ci // SCENE_NS::IMaterial::METALLIC_ROUGHNESS 5508bf80f4bSopenharmony_ci if (auto roughness = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 5518bf80f4bSopenharmony_ci if (type != SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5528bf80f4bSopenharmony_ci meta->RemoveProperty(roughness); 5538bf80f4bSopenharmony_ci } 5548bf80f4bSopenharmony_ci } else if (type == SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5558bf80f4bSopenharmony_ci auto roughness = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS); 5568bf80f4bSopenharmony_ci meta->AddProperty(roughness); 5578bf80f4bSopenharmony_ci } 5588bf80f4bSopenharmony_ci if (auto metallic = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_METALLIC)) { 5598bf80f4bSopenharmony_ci if (type != SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5608bf80f4bSopenharmony_ci meta->RemoveProperty(metallic); 5618bf80f4bSopenharmony_ci } 5628bf80f4bSopenharmony_ci } else if (type == SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5638bf80f4bSopenharmony_ci auto metallic = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_METALLIC); 5648bf80f4bSopenharmony_ci meta->AddProperty(metallic); 5658bf80f4bSopenharmony_ci } 5668bf80f4bSopenharmony_ci if (auto reflectance = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_REFLECTANCE)) { 5678bf80f4bSopenharmony_ci if (type != SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5688bf80f4bSopenharmony_ci meta->RemoveProperty(reflectance); 5698bf80f4bSopenharmony_ci } 5708bf80f4bSopenharmony_ci } else if (type == SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 5718bf80f4bSopenharmony_ci auto reflectance = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_REFLECTANCE); 5728bf80f4bSopenharmony_ci meta->AddProperty(reflectance); 5738bf80f4bSopenharmony_ci } 5748bf80f4bSopenharmony_ci // SCENE_NS::IMaterial::SPECULAR_GLOSSINESS 5758bf80f4bSopenharmony_ci if (auto colorRGB = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 5768bf80f4bSopenharmony_ci if (type != SCENE_NS::IMaterial::SPECULAR_GLOSSINESS) { 5778bf80f4bSopenharmony_ci meta->RemoveProperty(colorRGB); 5788bf80f4bSopenharmony_ci } 5798bf80f4bSopenharmony_ci } else if (type == SCENE_NS::IMaterial::SPECULAR_GLOSSINESS) { 5808bf80f4bSopenharmony_ci auto colorRGB = META_NS::ConstructProperty<SCENE_NS::Color>(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR); 5818bf80f4bSopenharmony_ci meta->AddProperty(colorRGB); 5828bf80f4bSopenharmony_ci } 5838bf80f4bSopenharmony_ci if (auto glossiness = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_GLOSSINESS)) { 5848bf80f4bSopenharmony_ci if (type != SCENE_NS::IMaterial::SPECULAR_GLOSSINESS) { 5858bf80f4bSopenharmony_ci meta->RemoveProperty(glossiness); 5868bf80f4bSopenharmony_ci } 5878bf80f4bSopenharmony_ci } else if (type == SCENE_NS::IMaterial::SPECULAR_GLOSSINESS) { 5888bf80f4bSopenharmony_ci auto glossiness = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_GLOSSINESS); 5898bf80f4bSopenharmony_ci meta->AddProperty(glossiness); 5908bf80f4bSopenharmony_ci } 5918bf80f4bSopenharmony_ci } 5928bf80f4bSopenharmony_ci 5938bf80f4bSopenharmony_ci // Emissive 5948bf80f4bSopenharmony_ci if (auto meta = 5958bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::EMISSIVE))) { 5968bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 5978bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 5988bf80f4bSopenharmony_ci meta->RemoveProperty(color); 5998bf80f4bSopenharmony_ci } 6008bf80f4bSopenharmony_ci } else { 6018bf80f4bSopenharmony_ci auto c = META_NS::ConstructProperty<SCENE_NS::Color>(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR); 6028bf80f4bSopenharmony_ci meta->AddProperty(c); 6038bf80f4bSopenharmony_ci } 6048bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY)) { 6058bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6068bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6078bf80f4bSopenharmony_ci } 6088bf80f4bSopenharmony_ci } else { 6098bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY); 6108bf80f4bSopenharmony_ci meta->AddProperty(p); 6118bf80f4bSopenharmony_ci } 6128bf80f4bSopenharmony_ci } 6138bf80f4bSopenharmony_ci 6148bf80f4bSopenharmony_ci // Ambient Occlusion 6158bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::AO))) { 6168bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH)) { 6178bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6188bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6198bf80f4bSopenharmony_ci } 6208bf80f4bSopenharmony_ci } else { 6218bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH); 6228bf80f4bSopenharmony_ci meta->AddProperty(p); 6238bf80f4bSopenharmony_ci } 6248bf80f4bSopenharmony_ci } 6258bf80f4bSopenharmony_ci 6268bf80f4bSopenharmony_ci // Clear Coat 6278bf80f4bSopenharmony_ci if (auto meta = 6288bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT))) { 6298bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY)) { 6308bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6318bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6328bf80f4bSopenharmony_ci } 6338bf80f4bSopenharmony_ci } else { 6348bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY); 6358bf80f4bSopenharmony_ci meta->AddProperty(p); 6368bf80f4bSopenharmony_ci } 6378bf80f4bSopenharmony_ci } 6388bf80f4bSopenharmony_ci 6398bf80f4bSopenharmony_ci // Clear Coat Roughness 6408bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 6418bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT_ROUGHNESS))) { 6428bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 6438bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6448bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6458bf80f4bSopenharmony_ci } 6468bf80f4bSopenharmony_ci } else { 6478bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS); 6488bf80f4bSopenharmony_ci meta->AddProperty(p); 6498bf80f4bSopenharmony_ci } 6508bf80f4bSopenharmony_ci } 6518bf80f4bSopenharmony_ci 6528bf80f4bSopenharmony_ci // Clear Coat Normal 6538bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 6548bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT_NORMAL))) { 6558bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE)) { 6568bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6578bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6588bf80f4bSopenharmony_ci } 6598bf80f4bSopenharmony_ci } else { 6608bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE); 6618bf80f4bSopenharmony_ci meta->AddProperty(p); 6628bf80f4bSopenharmony_ci } 6638bf80f4bSopenharmony_ci } 6648bf80f4bSopenharmony_ci 6658bf80f4bSopenharmony_ci // Sheen 6668bf80f4bSopenharmony_ci if (auto meta = 6678bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::SHEEN))) { 6688bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 6698bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6708bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6718bf80f4bSopenharmony_ci } 6728bf80f4bSopenharmony_ci } else { 6738bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<SCENE_NS::Color>(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR); 6748bf80f4bSopenharmony_ci meta->AddProperty(p); 6758bf80f4bSopenharmony_ci } 6768bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 6778bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6788bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6798bf80f4bSopenharmony_ci } 6808bf80f4bSopenharmony_ci } else { 6818bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS); 6828bf80f4bSopenharmony_ci meta->AddProperty(p); 6838bf80f4bSopenharmony_ci } 6848bf80f4bSopenharmony_ci } 6858bf80f4bSopenharmony_ci 6868bf80f4bSopenharmony_ci // TRANSMISSION 6878bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 6888bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::TRANSMISSION))) { 6898bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_TRANSMISSION)) { 6908bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 6918bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 6928bf80f4bSopenharmony_ci } 6938bf80f4bSopenharmony_ci } else { 6948bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_TRANSMISSION); 6958bf80f4bSopenharmony_ci meta->AddProperty(p); 6968bf80f4bSopenharmony_ci } 6978bf80f4bSopenharmony_ci } 6988bf80f4bSopenharmony_ci 6998bf80f4bSopenharmony_ci // Specular 7008bf80f4bSopenharmony_ci if (auto meta = 7018bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::SPECULAR))) { 7028bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 7038bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 7048bf80f4bSopenharmony_ci meta->RemoveProperty(color); 7058bf80f4bSopenharmony_ci } 7068bf80f4bSopenharmony_ci } else { 7078bf80f4bSopenharmony_ci auto c = META_NS::ConstructProperty<SCENE_NS::Color>(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR); 7088bf80f4bSopenharmony_ci meta->AddProperty(c); 7098bf80f4bSopenharmony_ci } 7108bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH)) { 7118bf80f4bSopenharmony_ci if (!includeDefaultMappings) { 7128bf80f4bSopenharmony_ci meta->RemoveProperty(prop); 7138bf80f4bSopenharmony_ci } 7148bf80f4bSopenharmony_ci } else { 7158bf80f4bSopenharmony_ci auto p = META_NS::ConstructProperty<float>(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH); 7168bf80f4bSopenharmony_ci meta->AddProperty(p); 7178bf80f4bSopenharmony_ci } 7188bf80f4bSopenharmony_ci } 7198bf80f4bSopenharmony_ci } 7208bf80f4bSopenharmony_ci 7218bf80f4bSopenharmony_ci void BindInputProperties() 7228bf80f4bSopenharmony_ci { 7238bf80f4bSopenharmony_ci auto type = META_NS::GetValue(META_ACCESS_PROPERTY(Type)); 7248bf80f4bSopenharmony_ci 7258bf80f4bSopenharmony_ci // Base Color 7268bf80f4bSopenharmony_ci if (auto meta = 7278bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::BASE_COLOR))) { 7288bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 7298bf80f4bSopenharmony_ci ConvertBindChanges<SCENE_NS::Color, BASE_NS::Math::Vec4>(GET_HOLDER(meta), 7308bf80f4bSopenharmony_ci META_NS::Property<SCENE_NS::Color>(color), meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR); 7318bf80f4bSopenharmony_ci } 7328bf80f4bSopenharmony_ci } 7338bf80f4bSopenharmony_ci 7348bf80f4bSopenharmony_ci // Normal 7358bf80f4bSopenharmony_ci if (auto meta = 7368bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::NORMAL))) { 7378bf80f4bSopenharmony_ci if (auto scale = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE)) { 7388bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(scale), meta, 7398bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 0); 7408bf80f4bSopenharmony_ci } 7418bf80f4bSopenharmony_ci } 7428bf80f4bSopenharmony_ci 7438bf80f4bSopenharmony_ci // Material 7448bf80f4bSopenharmony_ci if (auto meta = 7458bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::MATERIAL))) { 7468bf80f4bSopenharmony_ci // SCENE_NS::IMaterial::METALLIC_ROUGHNESS 7478bf80f4bSopenharmony_ci if (type == SCENE_NS::IMaterial::METALLIC_ROUGHNESS) { 7488bf80f4bSopenharmony_ci if (auto roughness = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 7498bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(roughness), 7508bf80f4bSopenharmony_ci meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 1); 7518bf80f4bSopenharmony_ci } 7528bf80f4bSopenharmony_ci if (auto metallic = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_METALLIC)) { 7538bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(metallic), 7548bf80f4bSopenharmony_ci meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 2); // 2 factor 7558bf80f4bSopenharmony_ci } 7568bf80f4bSopenharmony_ci if (auto reflectance = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_REFLECTANCE)) { 7578bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(reflectance), 7588bf80f4bSopenharmony_ci meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 3); // 3 factor 7598bf80f4bSopenharmony_ci } 7608bf80f4bSopenharmony_ci } 7618bf80f4bSopenharmony_ci 7628bf80f4bSopenharmony_ci // SCENE_NS::IMaterial::SPECULAR_GLOSSINESS 7638bf80f4bSopenharmony_ci if (type == SCENE_NS::IMaterial::SPECULAR_GLOSSINESS) { 7648bf80f4bSopenharmony_ci if (auto colorRGB = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 7658bf80f4bSopenharmony_ci BASE_NS::vector<size_t> slots = { 0, 0, 1, 1, 2, 2 }; 7668bf80f4bSopenharmony_ci BindSlottedChanges<BASE_NS::Math::Vec4, SCENE_NS::Color>(GET_HOLDER(meta), 7678bf80f4bSopenharmony_ci META_NS::Property<SCENE_NS::Color>(colorRGB), meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 7688bf80f4bSopenharmony_ci slots); 7698bf80f4bSopenharmony_ci } 7708bf80f4bSopenharmony_ci if (auto glossiness = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_GLOSSINESS)) { 7718bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(glossiness), 7728bf80f4bSopenharmony_ci meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 3); 7738bf80f4bSopenharmony_ci } 7748bf80f4bSopenharmony_ci } 7758bf80f4bSopenharmony_ci } 7768bf80f4bSopenharmony_ci 7778bf80f4bSopenharmony_ci // Emissive 7788bf80f4bSopenharmony_ci if (auto meta = 7798bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::EMISSIVE))) { 7808bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 7818bf80f4bSopenharmony_ci BASE_NS::vector<size_t> slots = { 0, 0, 1, 1, 2, 2 }; 7828bf80f4bSopenharmony_ci BindSlottedChanges<BASE_NS::Math::Vec4, SCENE_NS::Color>(GET_HOLDER(meta), 7838bf80f4bSopenharmony_ci META_NS::Property<SCENE_NS::Color>(color), meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 7848bf80f4bSopenharmony_ci slots); 7858bf80f4bSopenharmony_ci } 7868bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY)) { 7878bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 7888bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 3); 7898bf80f4bSopenharmony_ci } 7908bf80f4bSopenharmony_ci } 7918bf80f4bSopenharmony_ci 7928bf80f4bSopenharmony_ci // Ambient Occlusion 7938bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::AO))) { 7948bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH)) { 7958bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 7968bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 0); 7978bf80f4bSopenharmony_ci } 7988bf80f4bSopenharmony_ci } 7998bf80f4bSopenharmony_ci 8008bf80f4bSopenharmony_ci // Clear Coat 8018bf80f4bSopenharmony_ci if (auto meta = 8028bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT))) { 8038bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_INTENSITY)) { 8048bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8058bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 0); 8068bf80f4bSopenharmony_ci } 8078bf80f4bSopenharmony_ci } 8088bf80f4bSopenharmony_ci 8098bf80f4bSopenharmony_ci // Clear Coat Roughness 8108bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 8118bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT_ROUGHNESS))) { 8128bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 8138bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8148bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 1); 8158bf80f4bSopenharmony_ci } 8168bf80f4bSopenharmony_ci } 8178bf80f4bSopenharmony_ci 8188bf80f4bSopenharmony_ci // Clear Coat Normal 8198bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 8208bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::CLEARCOAT_NORMAL))) { 8218bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_NORMAL_SCALE)) { 8228bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8238bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 0); 8248bf80f4bSopenharmony_ci } 8258bf80f4bSopenharmony_ci } 8268bf80f4bSopenharmony_ci 8278bf80f4bSopenharmony_ci // Sheen 8288bf80f4bSopenharmony_ci if (auto meta = 8298bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::SHEEN))) { 8308bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 8318bf80f4bSopenharmony_ci BASE_NS::vector<size_t> slots = { 0, 0, 1, 1, 2, 2 }; 8328bf80f4bSopenharmony_ci BindSlottedChanges<BASE_NS::Math::Vec4, SCENE_NS::Color>(GET_HOLDER(meta), 8338bf80f4bSopenharmony_ci META_NS::Property<SCENE_NS::Color>(prop), meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, slots); 8348bf80f4bSopenharmony_ci } 8358bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_ROUGHNESS)) { 8368bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8378bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 3); 8388bf80f4bSopenharmony_ci } 8398bf80f4bSopenharmony_ci } 8408bf80f4bSopenharmony_ci 8418bf80f4bSopenharmony_ci // TRANSMISSION 8428bf80f4bSopenharmony_ci if (auto meta = interface_pointer_cast<META_NS::IMetadata>( 8438bf80f4bSopenharmony_ci GetTextureInfo(CORE3D_NS::MaterialComponent::TRANSMISSION))) { 8448bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_TRANSMISSION)) { 8458bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8468bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 0); 8478bf80f4bSopenharmony_ci } 8488bf80f4bSopenharmony_ci } 8498bf80f4bSopenharmony_ci 8508bf80f4bSopenharmony_ci // Specular 8518bf80f4bSopenharmony_ci if (auto meta = 8528bf80f4bSopenharmony_ci interface_pointer_cast<META_NS::IMetadata>(GetTextureInfo(CORE3D_NS::MaterialComponent::SPECULAR))) { 8538bf80f4bSopenharmony_ci if (auto color = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_COLOR)) { 8548bf80f4bSopenharmony_ci BASE_NS::vector<size_t> slots = { 0, 0, 1, 1, 2, 2 }; 8558bf80f4bSopenharmony_ci BindSlottedChanges<BASE_NS::Math::Vec4, SCENE_NS::Color>(GET_HOLDER(meta), 8568bf80f4bSopenharmony_ci META_NS::Property<SCENE_NS::Color>(color), meta, SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 8578bf80f4bSopenharmony_ci slots); 8588bf80f4bSopenharmony_ci } 8598bf80f4bSopenharmony_ci if (auto prop = meta->GetPropertyByName(SCENE_NS::IMaterial::MAPPED_INPUTS_STRENGTH)) { 8608bf80f4bSopenharmony_ci BindChanges<BASE_NS::Math::Vec4, float>(GET_HOLDER(meta), META_NS::Property<float>(prop), meta, 8618bf80f4bSopenharmony_ci SCENE_NS::IMaterial::MAPPED_INPUTS_FACTOR, 3); // 3 factor 8628bf80f4bSopenharmony_ci } 8638bf80f4bSopenharmony_ci } 8648bf80f4bSopenharmony_ci } 8658bf80f4bSopenharmony_ci 8668bf80f4bSopenharmony_ci void OnTypeChanged() 8678bf80f4bSopenharmony_ci { 8688bf80f4bSopenharmony_ci UpdateInputProperties(); 8698bf80f4bSopenharmony_ci BindInputProperties(); 8708bf80f4bSopenharmony_ci } 8718bf80f4bSopenharmony_ci 8728bf80f4bSopenharmony_ci // We intend to define the object only on demand 8738bf80f4bSopenharmony_ci // If we have a previous object, we could try to preserve it 8748bf80f4bSopenharmony_ci void UpdateCustomProperties() 8758bf80f4bSopenharmony_ci { 8768bf80f4bSopenharmony_ci // Store and remove old custom properties. 8778bf80f4bSopenharmony_ci BASE_NS::vector<META_NS::IProperty::Ptr> oldCustomProperties; 8788bf80f4bSopenharmony_ci 8798bf80f4bSopenharmony_ci auto properties = interface_pointer_cast<META_NS::IMetadata>(META_ACCESS_PROPERTY(CustomProperties)->GetValue()); 8808bf80f4bSopenharmony_ci if (properties) { 8818bf80f4bSopenharmony_ci oldCustomProperties = properties->GetAllProperties(); 8828bf80f4bSopenharmony_ci properties->GetPropertyContainer()->RemoveAll(); 8838bf80f4bSopenharmony_ci } 8848bf80f4bSopenharmony_ci 8858bf80f4bSopenharmony_ci // Find new custom properties. 8868bf80f4bSopenharmony_ci BASE_NS::vector<META_NS::IProperty::Ptr> newCustomProperties; 8878bf80f4bSopenharmony_ci 8888bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 8898bf80f4bSopenharmony_ci if (meta) { 8908bf80f4bSopenharmony_ci // Collect all custom properties from ECS object. 8918bf80f4bSopenharmony_ci auto metaProps = meta->GetAllProperties(); 8928bf80f4bSopenharmony_ci for (auto&& prop : metaProps) { 8938bf80f4bSopenharmony_ci if (prop->GetName().compare(0, CUSTOM_PREFIX_SIZE, CUSTOM_PREFIX) == 0) { 8948bf80f4bSopenharmony_ci newCustomProperties.push_back(prop); 8958bf80f4bSopenharmony_ci } 8968bf80f4bSopenharmony_ci } 8978bf80f4bSopenharmony_ci } 8988bf80f4bSopenharmony_ci 8998bf80f4bSopenharmony_ci // If there are no custom properties, then reset. 9008bf80f4bSopenharmony_ci if (newCustomProperties.empty()) { 9018bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomProperties)->Reset(); 9028bf80f4bSopenharmony_ci return; 9038bf80f4bSopenharmony_ci } 9048bf80f4bSopenharmony_ci 9058bf80f4bSopenharmony_ci // Otherwise ensure that we have container for the custom properties. 9068bf80f4bSopenharmony_ci if (!properties) { 9078bf80f4bSopenharmony_ci properties = GetObjectRegistry().Create<META_NS::IMetadata>(SCENE_NS::ClassId::CustomPropertiesHolder); 9088bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomProperties)->SetValue(interface_pointer_cast<META_NS::IObject>(properties)); 9098bf80f4bSopenharmony_ci } 9108bf80f4bSopenharmony_ci 9118bf80f4bSopenharmony_ci GET_HOLDER(properties).SetSceneHolder(sceneHolder_.lock()); 9128bf80f4bSopenharmony_ci 9138bf80f4bSopenharmony_ci // Then create and bind all the custom properties. 9148bf80f4bSopenharmony_ci for (auto& prop : newCustomProperties) { 9158bf80f4bSopenharmony_ci // This is the new custom property. 9168bf80f4bSopenharmony_ci META_NS::IProperty::Ptr property; 9178bf80f4bSopenharmony_ci 9188bf80f4bSopenharmony_ci BASE_NS::string propertyName(prop->GetName().substr(CUSTOM_PREFIX_SIZE)); 9198bf80f4bSopenharmony_ci 9208bf80f4bSopenharmony_ci // Try to re-use the old custom property if we have one, it may have a meaningful value set. 9218bf80f4bSopenharmony_ci for (auto& existing : oldCustomProperties) { 9228bf80f4bSopenharmony_ci if (existing->GetName() == propertyName && existing->GetTypeId() == prop->GetTypeId()) { 9238bf80f4bSopenharmony_ci property = existing; 9248bf80f4bSopenharmony_ci break; 9258bf80f4bSopenharmony_ci } 9268bf80f4bSopenharmony_ci } 9278bf80f4bSopenharmony_ci 9288bf80f4bSopenharmony_ci if (!property) { 9298bf80f4bSopenharmony_ci // Clone property. 9308bf80f4bSopenharmony_ci property = META_NS::DuplicatePropertyType(META_NS::GetObjectRegistry(), prop, propertyName); 9318bf80f4bSopenharmony_ci } 9328bf80f4bSopenharmony_ci 9338bf80f4bSopenharmony_ci // Add it to target. 9348bf80f4bSopenharmony_ci properties->AddProperty(property); 9358bf80f4bSopenharmony_ci 9368bf80f4bSopenharmony_ci // Bind it to ecs property. 9378bf80f4bSopenharmony_ci BindMetaProperty(GET_HOLDER(properties), property, prop); 9388bf80f4bSopenharmony_ci } 9398bf80f4bSopenharmony_ci } 9408bf80f4bSopenharmony_ci 9418bf80f4bSopenharmony_ci void UpdateInputs(bool forceRecursive = false, bool forceFullReset = true) 9428bf80f4bSopenharmony_ci { 9438bf80f4bSopenharmony_ci if (updatingInputs_ && !forceRecursive) { 9448bf80f4bSopenharmony_ci return; 9458bf80f4bSopenharmony_ci } 9468bf80f4bSopenharmony_ci 9478bf80f4bSopenharmony_ci if (forceFullReset) { 9488bf80f4bSopenharmony_ci updatingInputs_ = true; 9498bf80f4bSopenharmony_ci 9508bf80f4bSopenharmony_ci propHandler_.Reset(); 9518bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Inputs)->Reset(); 9528bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomProperties)->Reset(); 9538bf80f4bSopenharmony_ci 9548bf80f4bSopenharmony_ci auto entity = EcsObject()->GetEntity(); 9558bf80f4bSopenharmony_ci auto ecs = EcsObject()->GetEcs(); 9568bf80f4bSopenharmony_ci 9578bf80f4bSopenharmony_ci // Reset the object 9588bf80f4bSopenharmony_ci EcsObject()->BindObject(nullptr, entity); 9598bf80f4bSopenharmony_ci 9608bf80f4bSopenharmony_ci auto scene = EcsScene(); 9618bf80f4bSopenharmony_ci auto ecsObject = EcsObject(); 9628bf80f4bSopenharmony_ci 9638bf80f4bSopenharmony_ci Initialize( 9648bf80f4bSopenharmony_ci scene, ecsObject, {}, META_NS::GetValue(Path()), META_NS::GetValue(Name()), sceneHolder_, entity); 9658bf80f4bSopenharmony_ci 9668bf80f4bSopenharmony_ci updatingInputs_ = false; 9678bf80f4bSopenharmony_ci } else { 9688bf80f4bSopenharmony_ci // This will potentially go wrong if the proxy properties contain set values 9698bf80f4bSopenharmony_ci // The values previously set will replace the values from engine 9708bf80f4bSopenharmony_ci if (UpdateAllInputProperties()) { 9718bf80f4bSopenharmony_ci updatingInputs_ = true; 9728bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Inputs)->Reset(); 9738bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(CustomProperties)->Reset(); 9748bf80f4bSopenharmony_ci CompleteInitialization(META_NS::GetValue(Name())); 9758bf80f4bSopenharmony_ci updatingInputs_ = false; 9768bf80f4bSopenharmony_ci } 9778bf80f4bSopenharmony_ci } 9788bf80f4bSopenharmony_ci } 9798bf80f4bSopenharmony_ci 9808bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view MATERIAL_SHADER_NAME { "MaterialComponent.materialShader.shader" }; 9818bf80f4bSopenharmony_ci static constexpr BASE_NS::string_view DEPTH_SHADER_NAME { "MaterialComponent.depthShader.shader" }; 9828bf80f4bSopenharmony_ci 9838bf80f4bSopenharmony_ci SCENE_NS::ITextureInfo::Ptr FindTextureInfo(BASE_NS::string_view name) 9848bf80f4bSopenharmony_ci { 9858bf80f4bSopenharmony_ci if (META_ACCESS_PROPERTY(Inputs)) { 9868bf80f4bSopenharmony_ci for (auto& info : Inputs()->GetValue()) { 9878bf80f4bSopenharmony_ci if (META_NS::GetValue(info->Name()) == name) { 9888bf80f4bSopenharmony_ci return info; 9898bf80f4bSopenharmony_ci } 9908bf80f4bSopenharmony_ci } 9918bf80f4bSopenharmony_ci } 9928bf80f4bSopenharmony_ci return {}; 9938bf80f4bSopenharmony_ci } 9948bf80f4bSopenharmony_ci 9958bf80f4bSopenharmony_ci void CopyTextureInfoProperties(SCENE_NS::ITextureInfo::Ptr from, SCENE_NS::ITextureInfo::Ptr to) 9968bf80f4bSopenharmony_ci { 9978bf80f4bSopenharmony_ci if (from->Factor()->IsValueSet()) { 9988bf80f4bSopenharmony_ci to->Factor()->SetValue(from->Factor()->GetValue()); 9998bf80f4bSopenharmony_ci } 10008bf80f4bSopenharmony_ci 10018bf80f4bSopenharmony_ci if (from->Rotation()->IsValueSet()) { 10028bf80f4bSopenharmony_ci to->Rotation()->SetValue(from->Rotation()->GetValue()); 10038bf80f4bSopenharmony_ci } 10048bf80f4bSopenharmony_ci 10058bf80f4bSopenharmony_ci if (from->Scale()->IsValueSet()) { 10068bf80f4bSopenharmony_ci to->Scale()->SetValue(from->Scale()->GetValue()); 10078bf80f4bSopenharmony_ci } 10088bf80f4bSopenharmony_ci 10098bf80f4bSopenharmony_ci if (from->Translation()->IsValueSet()) { 10108bf80f4bSopenharmony_ci to->Translation()->SetValue(from->Translation()->GetValue()); 10118bf80f4bSopenharmony_ci } 10128bf80f4bSopenharmony_ci 10138bf80f4bSopenharmony_ci // Sampler enumeration works now using enums, it should follow uri 10148bf80f4bSopenharmony_ci // but uri information is not available from engine yet 10158bf80f4bSopenharmony_ci if (from->Sampler()->IsValueSet()) { 10168bf80f4bSopenharmony_ci to->Sampler()->SetValue(from->Sampler()->GetValue()); 10178bf80f4bSopenharmony_ci } 10188bf80f4bSopenharmony_ci 10198bf80f4bSopenharmony_ci // image goes through uri implementation 10208bf80f4bSopenharmony_ci if (auto data = META_NS::GetValue(from->Image())) { 10218bf80f4bSopenharmony_ci to->Image()->SetValue(from->Image()->GetValue()); 10228bf80f4bSopenharmony_ci } 10238bf80f4bSopenharmony_ci } 10248bf80f4bSopenharmony_ci 10258bf80f4bSopenharmony_ci bool SynchronizeInputsFromMetadata() 10268bf80f4bSopenharmony_ci { 10278bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 10288bf80f4bSopenharmony_ci if (!meta) { 10298bf80f4bSopenharmony_ci return false; 10308bf80f4bSopenharmony_ci } 10318bf80f4bSopenharmony_ci // Texture slots need to be bound before other properties 10328bf80f4bSopenharmony_ci BASE_NS::vector<SCENE_NS::ITextureInfo::Ptr> textures; 10338bf80f4bSopenharmony_ci auto prop = 10348bf80f4bSopenharmony_ci meta->GetArrayPropertyByName<CORE3D_NS::MaterialComponent::TextureInfo>("MaterialComponent.textures"); 10358bf80f4bSopenharmony_ci // slot names (unsure-what-they-were-before-but-matches-core3d-enum) 10368bf80f4bSopenharmony_ci const char* TextureIndexName[] = { "BASE_COLOR", "NORMAL", "MATERIAL", "EMISSIVE", "AO", "CLEARCOAT", 10378bf80f4bSopenharmony_ci "CLEARCOAT_ROUGHNESS", "CLEARCOAT_NORMAL", "SHEEN", "TRANSMISSION", "SPECULAR" }; 10388bf80f4bSopenharmony_ci auto v = prop->GetValue(); 10398bf80f4bSopenharmony_ci auto shp = SceneHolder(); 10408bf80f4bSopenharmony_ci for (auto t : v) { 10418bf80f4bSopenharmony_ci int textureSlotIndex = textures.size(); 10428bf80f4bSopenharmony_ci // create wrapping things.. 10438bf80f4bSopenharmony_ci auto info = GetTextureInfoByIndex(textureSlotIndex, textures); 10448bf80f4bSopenharmony_ci if (!info) { 10458bf80f4bSopenharmony_ci auto& obr = GetObjectRegistry(); 10468bf80f4bSopenharmony_ci auto params = obr.ConstructMetadata(); 10478bf80f4bSopenharmony_ci using IntfPtr = META_NS::SharedPtrIInterface; 10488bf80f4bSopenharmony_ci params->AddProperty(META_NS::ConstructProperty<META_NS::IProperty::Ptr>( 10498bf80f4bSopenharmony_ci "textureInfoArray", nullptr, META_NS::ObjectFlagBits::INTERNAL | META_NS::ObjectFlagBits::NATIVE)); 10508bf80f4bSopenharmony_ci params->AddProperty(META_NS::ConstructProperty<uint32_t>( 10518bf80f4bSopenharmony_ci "textureSlotIndex", 0, META_NS::ObjectFlagBits::INTERNAL | META_NS::ObjectFlagBits::NATIVE)); 10528bf80f4bSopenharmony_ci params->AddProperty(META_NS::ConstructProperty<uintptr_t>( 10538bf80f4bSopenharmony_ci "sceneHolder", 0, META_NS::ObjectFlagBits::INTERNAL | META_NS::ObjectFlagBits::NATIVE)); 10548bf80f4bSopenharmony_ci 10558bf80f4bSopenharmony_ci // yes this is ugly. 10568bf80f4bSopenharmony_ci params->GetPropertyByName<uintptr_t>("sceneHolder")->SetValue((uintptr_t)&shp); 10578bf80f4bSopenharmony_ci params->GetPropertyByName<IntfPtr>("textureInfoArray") 10588bf80f4bSopenharmony_ci ->SetValue(interface_pointer_cast<CORE_NS::IInterface>(prop.GetProperty())); 10598bf80f4bSopenharmony_ci params->GetPropertyByName<uint32_t>("textureSlotIndex")->SetValue(textureSlotIndex); 10608bf80f4bSopenharmony_ci info = obr.Create<SCENE_NS::ITextureInfo>(SCENE_NS::ClassId::TextureInfo, params); 10618bf80f4bSopenharmony_ci if (!info) { 10628bf80f4bSopenharmony_ci return {}; 10638bf80f4bSopenharmony_ci } 10648bf80f4bSopenharmony_ci 10658bf80f4bSopenharmony_ci info->SetTextureSlotIndex(textureSlotIndex); 10668bf80f4bSopenharmony_ci textures.push_back(info); 10678bf80f4bSopenharmony_ci } else { 10688bf80f4bSopenharmony_ci textures.push_back(nullptr); 10698bf80f4bSopenharmony_ci } 10708bf80f4bSopenharmony_ci } 10718bf80f4bSopenharmony_ci 10728bf80f4bSopenharmony_ci BASE_NS::vector<SCENE_NS::ITextureInfo::Ptr> prevInputs; 10738bf80f4bSopenharmony_ci if (META_ACCESS_PROPERTY(Inputs)) { 10748bf80f4bSopenharmony_ci auto size = META_ACCESS_PROPERTY(Inputs)->GetSize(); 10758bf80f4bSopenharmony_ci for (size_t ii = 0; ii < size; ii++) { 10768bf80f4bSopenharmony_ci prevInputs.push_back(META_ACCESS_PROPERTY(Inputs)->GetValueAt(ii)); 10778bf80f4bSopenharmony_ci } 10788bf80f4bSopenharmony_ci } 10798bf80f4bSopenharmony_ci 10808bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Inputs)->Reset(); 10818bf80f4bSopenharmony_ci 10828bf80f4bSopenharmony_ci // Sort texture infos. 10838bf80f4bSopenharmony_ci std::sort(textures.begin(), textures.end(), [](const auto& a, const auto& b) { 10848bf80f4bSopenharmony_ci // Sort based on texture-slot index. 10858bf80f4bSopenharmony_ci return a->GetTextureSlotIndex() < b->GetTextureSlotIndex(); 10868bf80f4bSopenharmony_ci }); 10878bf80f4bSopenharmony_ci 10888bf80f4bSopenharmony_ci // Assign to property. 10898bf80f4bSopenharmony_ci Inputs()->SetValue(textures); 10908bf80f4bSopenharmony_ci 10918bf80f4bSopenharmony_ci // Copy values from old inputs to new ones. 10928bf80f4bSopenharmony_ci for (auto& from : prevInputs) { 10938bf80f4bSopenharmony_ci if (auto to = FindTextureInfo(META_NS::GetValue(from->Name()))) { 10948bf80f4bSopenharmony_ci CopyTextureInfoProperties(from, to); 10958bf80f4bSopenharmony_ci } 10968bf80f4bSopenharmony_ci } 10978bf80f4bSopenharmony_ci 10988bf80f4bSopenharmony_ci return true; 10998bf80f4bSopenharmony_ci } 11008bf80f4bSopenharmony_ci 11018bf80f4bSopenharmony_ci // return true if something changes 11028bf80f4bSopenharmony_ci bool UpdateAllInputProperties() 11038bf80f4bSopenharmony_ci { 11048bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(EcsObject()); 11058bf80f4bSopenharmony_ci if (!meta) { 11068bf80f4bSopenharmony_ci return false; 11078bf80f4bSopenharmony_ci } 11088bf80f4bSopenharmony_ci 11098bf80f4bSopenharmony_ci auto oldCount = meta->GetPropertyContainer()->GetSize(); 11108bf80f4bSopenharmony_ci 11118bf80f4bSopenharmony_ci // This updates all properties from ecs and detaches properties that do not exist any more. 11128bf80f4bSopenharmony_ci EcsObject()->DefineTargetProperties(PropertyNameMask()); 11138bf80f4bSopenharmony_ci 11148bf80f4bSopenharmony_ci auto newCount = meta->GetPropertyContainer()->GetSize(); 11158bf80f4bSopenharmony_ci 11168bf80f4bSopenharmony_ci auto allProperties = meta->GetAllProperties(); 11178bf80f4bSopenharmony_ci 11188bf80f4bSopenharmony_ci // if we add or remove something these all cannot match 11198bf80f4bSopenharmony_ci return !((newCount == oldCount) && (oldCount != meta->GetPropertyContainer()->GetSize())); 11208bf80f4bSopenharmony_ci } 11218bf80f4bSopenharmony_ci 11228bf80f4bSopenharmony_ci bool CompleteInitialization(const BASE_NS::string& path) override 11238bf80f4bSopenharmony_ci { 11248bf80f4bSopenharmony_ci if (!NodeImpl::CompleteInitialization(path)) { 11258bf80f4bSopenharmony_ci return false; 11268bf80f4bSopenharmony_ci } 11278bf80f4bSopenharmony_ci 11288bf80f4bSopenharmony_ci auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_); 11298bf80f4bSopenharmony_ci if (!meta) { 11308bf80f4bSopenharmony_ci return false; 11318bf80f4bSopenharmony_ci } 11328bf80f4bSopenharmony_ci 11338bf80f4bSopenharmony_ci 11348bf80f4bSopenharmony_ci if (DepthShader()->GetValue()) { 11358bf80f4bSopenharmony_ci SceneHolder()->SetShader( 11368bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER, DepthShader()->GetValue()); 11378bf80f4bSopenharmony_ci } else { 11388bf80f4bSopenharmony_ci // Try to introspect depth shader from material. 11398bf80f4bSopenharmony_ci auto shader = SceneHolder()->GetShader(EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER); 11408bf80f4bSopenharmony_ci if (shader) { 11418bf80f4bSopenharmony_ci DepthShader()->SetValue(shader); 11428bf80f4bSopenharmony_ci } 11438bf80f4bSopenharmony_ci } 11448bf80f4bSopenharmony_ci 11458bf80f4bSopenharmony_ci if (DepthShaderState()->GetValue()) { 11468bf80f4bSopenharmony_ci SceneHolder()->SetGraphicsState( 11478bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER, DepthShaderState()->GetValue()); 11488bf80f4bSopenharmony_ci } else { 11498bf80f4bSopenharmony_ci // Try to introspect depth shader from material. 11508bf80f4bSopenharmony_ci auto state = 11518bf80f4bSopenharmony_ci SceneHolder()->GetGraphicsState(EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER); 11528bf80f4bSopenharmony_ci if (state) { 11538bf80f4bSopenharmony_ci DepthShaderState()->SetValue(state); 11548bf80f4bSopenharmony_ci } 11558bf80f4bSopenharmony_ci } 11568bf80f4bSopenharmony_ci 11578bf80f4bSopenharmony_ci if (MaterialShader()->GetValue()) { 11588bf80f4bSopenharmony_ci SceneHolder()->SetShader( 11598bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER, MaterialShader()->GetValue()); 11608bf80f4bSopenharmony_ci } else { 11618bf80f4bSopenharmony_ci // Try to introspect material shader from material. 11628bf80f4bSopenharmony_ci auto shader = SceneHolder()->GetShader(EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER); 11638bf80f4bSopenharmony_ci if (shader) { 11648bf80f4bSopenharmony_ci MaterialShader()->SetValue(shader); 11658bf80f4bSopenharmony_ci } 11668bf80f4bSopenharmony_ci } 11678bf80f4bSopenharmony_ci 11688bf80f4bSopenharmony_ci if (MaterialShaderState()->GetValue()) { 11698bf80f4bSopenharmony_ci SceneHolder()->SetGraphicsState( 11708bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER, MaterialShaderState()->GetValue()); 11718bf80f4bSopenharmony_ci } else { 11728bf80f4bSopenharmony_ci // Try to introspect depth shader from material. 11738bf80f4bSopenharmony_ci auto state = 11748bf80f4bSopenharmony_ci SceneHolder()->GetGraphicsState(EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER); 11758bf80f4bSopenharmony_ci if (state) { 11768bf80f4bSopenharmony_ci MaterialShaderState()->SetValue(state); 11778bf80f4bSopenharmony_ci } 11788bf80f4bSopenharmony_ci } 11798bf80f4bSopenharmony_ci 11808bf80f4bSopenharmony_ci // Shader may have changed, so update all properties. 11818bf80f4bSopenharmony_ci UpdateAllInputProperties(); 11828bf80f4bSopenharmony_ci 11838bf80f4bSopenharmony_ci // Properties up-to-date, synchronize all inputs. 11848bf80f4bSopenharmony_ci SynchronizeInputsFromMetadata(); 11858bf80f4bSopenharmony_ci 11868bf80f4bSopenharmony_ci propHandler_.NewHandler(nullptr, nullptr).Subscribe(META_ACCESS_PROPERTY(Type), [this]() { OnTypeChanged(); }); 11878bf80f4bSopenharmony_ci 11888bf80f4bSopenharmony_ci BindChanges(propHandler_, META_ACCESS_PROPERTY(Type), meta, "MaterialComponent.type"); 11898bf80f4bSopenharmony_ci 11908bf80f4bSopenharmony_ci // Shader will either come as an entity ref from the engine, or from serialized info. have a listener 11918bf80f4bSopenharmony_ci // that attaches the new ecs object to entity if one appears 11928bf80f4bSopenharmony_ci propHandler_.NewHandler(nullptr, nullptr).Subscribe(DepthShader(), [this]() { 11938bf80f4bSopenharmony_ci SceneHolder()->SetShader( 11948bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER, DepthShader()->GetValue()); 11958bf80f4bSopenharmony_ci UpdateInputs(); 11968bf80f4bSopenharmony_ci }); 11978bf80f4bSopenharmony_ci 11988bf80f4bSopenharmony_ci propHandler_.NewHandler(nullptr, nullptr).Subscribe(MaterialShader(), [this]() { 11998bf80f4bSopenharmony_ci // Material shader has changed. 12008bf80f4bSopenharmony_ci SceneHolder()->SetShader( 12018bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER, MaterialShader()->GetValue()); 12028bf80f4bSopenharmony_ci UpdateInputs(); 12038bf80f4bSopenharmony_ci }); 12048bf80f4bSopenharmony_ci 12058bf80f4bSopenharmony_ci propHandler_.NewHandler(nullptr, nullptr).Subscribe(DepthShaderState(), [this]() { 12068bf80f4bSopenharmony_ci SceneHolder()->SetGraphicsState( 12078bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::DEPTH_SHADER, DepthShaderState()->GetValue()); 12088bf80f4bSopenharmony_ci }); 12098bf80f4bSopenharmony_ci 12108bf80f4bSopenharmony_ci propHandler_.NewHandler(nullptr, nullptr).Subscribe(MaterialShaderState(), [this]() { 12118bf80f4bSopenharmony_ci // Material shader has changed. 12128bf80f4bSopenharmony_ci SceneHolder()->SetGraphicsState( 12138bf80f4bSopenharmony_ci EcsObject()->GetEntity(), SceneHolder::ShaderType::MATERIAL_SHADER, MaterialShaderState()->GetValue()); 12148bf80f4bSopenharmony_ci }); 12158bf80f4bSopenharmony_ci 12168bf80f4bSopenharmony_ci propHandler_.MarkRelated(MaterialShader(), meta->GetPropertyByName("MaterialComponent.materialShader.shader")); 12178bf80f4bSopenharmony_ci propHandler_.MarkRelated(DepthShader(), meta->GetPropertyByName("MaterialComponent.depthShader.shader")); 12188bf80f4bSopenharmony_ci propHandler_.MarkRelated( 12198bf80f4bSopenharmony_ci MaterialShaderState(), meta->GetPropertyByName("MaterialComponent.materialShader.graphicsState")); 12208bf80f4bSopenharmony_ci propHandler_.MarkRelated( 12218bf80f4bSopenharmony_ci DepthShaderState(), meta->GetPropertyByName("MaterialComponent.depthShader.graphicsState")); 12228bf80f4bSopenharmony_ci 12238bf80f4bSopenharmony_ci // make sure that inputs are up to date 12248bf80f4bSopenharmony_ci OnTypeChanged(); 12258bf80f4bSopenharmony_ci 12268bf80f4bSopenharmony_ci // Update custom properties. 12278bf80f4bSopenharmony_ci UpdateCustomProperties(); 12288bf80f4bSopenharmony_ci 12298bf80f4bSopenharmony_ci BindChanges(propHandler_, META_ACCESS_PROPERTY(AlphaCutoff), meta, "MaterialComponent.alphaCutoff"); 12308bf80f4bSopenharmony_ci BindChanges(propHandler_, META_ACCESS_PROPERTY(LightingFlags), meta, "MaterialComponent.materialLightingFlags"); 12318bf80f4bSopenharmony_ci return true; 12328bf80f4bSopenharmony_ci } 12338bf80f4bSopenharmony_ci 12348bf80f4bSopenharmony_ci bool BuildChildren(SCENE_NS::INode::BuildBehavior) override 12358bf80f4bSopenharmony_ci { 12368bf80f4bSopenharmony_ci // in typical cases we should not have children 12378bf80f4bSopenharmony_ci if (META_NS::GetValue(META_ACCESS_PROPERTY(Status)) == SCENE_NS::INode::NODE_STATUS_CONNECTED) { 12388bf80f4bSopenharmony_ci SetStatus(SCENE_NS::INode::NODE_STATUS_FULLY_CONNECTED); 12398bf80f4bSopenharmony_ci META_NS::Invoke<META_NS::IOnChanged>(OnBound()); 12408bf80f4bSopenharmony_ci bound_ = true; 12418bf80f4bSopenharmony_ci } 12428bf80f4bSopenharmony_ci return true; 12438bf80f4bSopenharmony_ci } 12448bf80f4bSopenharmony_ci 12458bf80f4bSopenharmony_ci void SetImage(SCENE_NS::IBitmap::Ptr bitmap, BASE_NS::string_view textureSlot) override 12468bf80f4bSopenharmony_ci { 12478bf80f4bSopenharmony_ci auto size = Inputs()->GetSize(); 12488bf80f4bSopenharmony_ci for (size_t ii = 0; ii < size; ii++) { 12498bf80f4bSopenharmony_ci if (META_NS::GetValue(Inputs()->GetValueAt(ii)->Name()).compare(textureSlot) == 0) { 12508bf80f4bSopenharmony_ci SetImage(bitmap, ii); 12518bf80f4bSopenharmony_ci break; 12528bf80f4bSopenharmony_ci } 12538bf80f4bSopenharmony_ci } 12548bf80f4bSopenharmony_ci } 12558bf80f4bSopenharmony_ci 12568bf80f4bSopenharmony_ci void SetImage(SCENE_NS::IBitmap::Ptr bitmap, size_t index) override 12578bf80f4bSopenharmony_ci { 12588bf80f4bSopenharmony_ci if (bitmap) { 12598bf80f4bSopenharmony_ci auto status = META_NS::GetValue(bitmap->Status()); 12608bf80f4bSopenharmony_ci if (status == SCENE_NS::IBitmap::BitmapStatus::COMPLETED) { 12618bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 12628bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask( 12638bf80f4bSopenharmony_ci MakeTask( 12648bf80f4bSopenharmony_ci [bitmap, index, weakSelf = BASE_NS::weak_ptr(GetSelf())](auto sh) { 12658bf80f4bSopenharmony_ci CORE_NS::Entity imageEntity = sh->BindUIBitmap(bitmap, true); 12668bf80f4bSopenharmony_ci auto image = sh->GetEcs()->GetEntityManager().GetReferenceCounted(imageEntity); 12678bf80f4bSopenharmony_ci sh->SetTexture(index, 12688bf80f4bSopenharmony_ci interface_pointer_cast<INodeEcsInterfacePrivate>(weakSelf) 12698bf80f4bSopenharmony_ci ->EcsObject() 12708bf80f4bSopenharmony_ci ->GetEntity(), 12718bf80f4bSopenharmony_ci image); 12728bf80f4bSopenharmony_ci sh->QueueApplicationTask(MakeTask([bitmap, index, weakSelf]() { 12738bf80f4bSopenharmony_ci if (auto me = interface_pointer_cast<SCENE_NS::IMaterial>(weakSelf)) { 12748bf80f4bSopenharmony_ci if (auto input = me->Inputs()->GetValueAt(index)) { 12758bf80f4bSopenharmony_ci input->Image()->SetValue(bitmap); 12768bf80f4bSopenharmony_ci } 12778bf80f4bSopenharmony_ci } 12788bf80f4bSopenharmony_ci return false; 12798bf80f4bSopenharmony_ci }), 12808bf80f4bSopenharmony_ci false); 12818bf80f4bSopenharmony_ci 12828bf80f4bSopenharmony_ci return false; 12838bf80f4bSopenharmony_ci }, 12848bf80f4bSopenharmony_ci sceneHolder), 12858bf80f4bSopenharmony_ci false); 12868bf80f4bSopenharmony_ci } 12878bf80f4bSopenharmony_ci 12888bf80f4bSopenharmony_ci } else { 12898bf80f4bSopenharmony_ci // should basically subscribe to dynamic content instead 12908bf80f4bSopenharmony_ci // Give uri based loading a shot 12918bf80f4bSopenharmony_ci if (auto input = Inputs()->GetValueAt(index)) { 12928bf80f4bSopenharmony_ci input->Image()->SetValue(bitmap); 12938bf80f4bSopenharmony_ci } 12948bf80f4bSopenharmony_ci } 12958bf80f4bSopenharmony_ci } else { // reset existing image if there is one 12968bf80f4bSopenharmony_ci if (auto sceneHolder = SceneHolder()) { 12978bf80f4bSopenharmony_ci sceneHolder->QueueEngineTask(MakeTask( 12988bf80f4bSopenharmony_ci [entityId = EcsObject()->GetEntity().id](auto sh) { 12998bf80f4bSopenharmony_ci CORE_NS::Entity target { entityId }; 13008bf80f4bSopenharmony_ci // The assumption is that using base color ix is correct thing to 13018bf80f4bSopenharmony_ci // do 13028bf80f4bSopenharmony_ci sh->SetTexture( 13038bf80f4bSopenharmony_ci CORE3D_NS::MaterialComponent::BASE_COLOR, target, {}); 13048bf80f4bSopenharmony_ci 13058bf80f4bSopenharmony_ci return false; 13068bf80f4bSopenharmony_ci }, 13078bf80f4bSopenharmony_ci sceneHolder), 13088bf80f4bSopenharmony_ci false); 13098bf80f4bSopenharmony_ci } 13108bf80f4bSopenharmony_ci } 13118bf80f4bSopenharmony_ci } 13128bf80f4bSopenharmony_ci}; 13138bf80f4bSopenharmony_ci} // namespace 13148bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 13158bf80f4bSopenharmony_ci 13168bf80f4bSopenharmony_civoid RegisterMaterialImpl() 13178bf80f4bSopenharmony_ci{ 13188bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().RegisterObjectType<MaterialImpl>(); 13198bf80f4bSopenharmony_ci} 13208bf80f4bSopenharmony_civoid UnregisterMaterialImpl() 13218bf80f4bSopenharmony_ci{ 13228bf80f4bSopenharmony_ci META_NS::GetObjectRegistry().UnregisterObjectType<MaterialImpl>(); 13238bf80f4bSopenharmony_ci} 13248bf80f4bSopenharmony_ci 13258bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 1326