2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-scene3d/internal/model-components/material-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/rendering/sampler.h>
28 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
29 #include <dali-scene3d/internal/light/light-impl.h>
30 #include <dali-scene3d/internal/model-components/material-modify-observer.h>
31 #include <dali-scene3d/public-api/loader/node-definition.h>
32 #include <dali-scene3d/public-api/loader/renderer-state.h>
33 #include <dali-scene3d/public-api/loader/utils.h>
44 * Creates Material through type registry
48 return Scene3D::Material::New();
51 // Setup properties, signals and actions using the type-registry.
52 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Material, Dali::BaseHandle, Create);
53 DALI_TYPE_REGISTRATION_END()
55 static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u;
56 static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
57 static constexpr uint32_t INVALID_INDEX = 0u;
58 static constexpr uint32_t ALPHA_CUTOFF_FLAG = Scene3D::Loader::MaterialDefinition::Flags::SUBSURFACE << 1;
59 static constexpr std::string_view THREE_TEX_KEYWORD = "THREE_TEX";
60 static constexpr std::string_view GLTF_CHANNELS_KEYWORD = "GLTF_CHANNELS";
74 } // unnamed namespace
76 MaterialPtr Material::New()
78 MaterialPtr material = new Material();
80 material->Initialize();
87 mModifyFlag(MaterialModifyObserver::ModifyFlag::NONE),
88 mObserverNotifying(false)
90 mAsyncImageLoader = Dali::Toolkit::AsyncImageLoader::New();
91 mAsyncImageLoader.ImageLoadedSignal().Connect(this, &Material::TextureLoadComplete);
92 mTextureInformations.assign(TEXTURE_TYPE_NUMBER, TextureInformation());
93 mTextureInformations[BASE_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::ALBEDO;
94 // TODO : How we support dli manner
95 mTextureInformations[METALLIC_ROUGHNESS].mSemantic = Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS |
96 Scene3D::Loader::MaterialDefinition::GLTF_CHANNELS;
97 mTextureInformations[NORMAL].mSemantic = Scene3D::Loader::MaterialDefinition::NORMAL;
98 mTextureInformations[OCCLUSION].mSemantic = Scene3D::Loader::MaterialDefinition::OCCLUSION;
99 mTextureInformations[EMISSIVE].mSemantic = Scene3D::Loader::MaterialDefinition::EMISSIVE;
100 mTextureInformations[SPECULAR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR;
101 mTextureInformations[SPECULAR_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR;
103 mTextureInformations[BASE_COLOR].mDefineKeyword = "BASECOLOR_TEX";
104 mTextureInformations[METALLIC_ROUGHNESS].mDefineKeyword = "METALLIC_ROUGHNESS_TEX";
105 mTextureInformations[NORMAL].mDefineKeyword = "NORMAL_TEX";
106 mTextureInformations[OCCLUSION].mDefineKeyword = "OCCLUSION";
107 mTextureInformations[EMISSIVE].mDefineKeyword = "EMISSIVE";
108 mTextureInformations[SPECULAR].mDefineKeyword = "MATERIAL_SPECULAR_TEXTURE";
109 mTextureInformations[SPECULAR_COLOR].mDefineKeyword = "MATERIAL_SPECULAR_COLOR_TEXTURE";
111 mTextureInformations[TextureIndex::EMISSIVE].mFactor = Vector4::ZERO;
114 Material::~Material() = default;
116 void Material::Initialize()
120 void Material::SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue)
122 bool needToApply = true;
125 case Dali::Scene3D::Material::Property::NAME:
128 if(propertyValue.Get(name))
135 case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
137 std::string baseColorUrl;
138 if(propertyValue.Get(baseColorUrl))
140 RequestTextureLoad(mTextureInformations[TextureIndex::BASE_COLOR], baseColorUrl);
145 case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
147 Vector4 baseColorFactor;
148 if(propertyValue.Get(baseColorFactor))
150 mTextureInformations[TextureIndex::BASE_COLOR].mFactor = baseColorFactor;
151 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
155 case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
157 std::string metallicRoughnessUrl;
158 if(propertyValue.Get(metallicRoughnessUrl))
160 RequestTextureLoad(mTextureInformations[TextureIndex::METALLIC_ROUGHNESS], metallicRoughnessUrl);
165 case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
167 float metallicFactor;
168 if(propertyValue.Get(metallicFactor))
170 mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x = metallicFactor;
171 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
175 case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
177 float roughnessFactor;
178 if(propertyValue.Get(roughnessFactor))
180 mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y = roughnessFactor;
181 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
185 case Dali::Scene3D::Material::Property::NORMAL_URL:
187 std::string normalUrl;
188 if(propertyValue.Get(normalUrl))
190 RequestTextureLoad(mTextureInformations[TextureIndex::NORMAL], normalUrl);
195 case Dali::Scene3D::Material::Property::NORMAL_SCALE:
198 if(propertyValue.Get(normalScale))
200 mTextureInformations[TextureIndex::NORMAL].mFactor.x = normalScale;
201 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
205 case Dali::Scene3D::Material::Property::OCCLUSION_URL:
207 std::string occlusionUrl;
208 if(propertyValue.Get(occlusionUrl))
210 RequestTextureLoad(mTextureInformations[TextureIndex::OCCLUSION], occlusionUrl);
215 case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
217 float occlusionStrength;
218 if(propertyValue.Get(occlusionStrength))
220 mTextureInformations[TextureIndex::OCCLUSION].mFactor.x = occlusionStrength;
221 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
225 case Dali::Scene3D::Material::Property::EMISSIVE_URL:
227 std::string emissiveUrl;
228 if(propertyValue.Get(emissiveUrl))
230 RequestTextureLoad(mTextureInformations[TextureIndex::EMISSIVE], emissiveUrl);
235 case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
237 Vector3 emissiveFactor;
238 if(propertyValue.Get(emissiveFactor))
240 mTextureInformations[TextureIndex::EMISSIVE].mFactor = emissiveFactor;
241 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
245 case Dali::Scene3D::Material::Property::ALPHA_MODE:
247 Dali::Scene3D::Material::AlphaModeType alphaMode;
248 if(propertyValue.Get(alphaMode))
250 mAlphaMode = alphaMode;
251 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
255 case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
258 if(propertyValue.Get(alphaCutoff))
260 mAlphaCutoff = alphaCutoff;
261 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
265 case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
268 if(propertyValue.Get(doubleSided))
270 mDoubleSided = doubleSided;
271 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
275 case Dali::Scene3D::Material::Property::IOR:
278 if(propertyValue.Get(ior))
281 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
285 case Dali::Scene3D::Material::Property::SPECULAR_URL:
287 std::string specularUrl;
288 if(propertyValue.Get(specularUrl))
290 RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR], specularUrl);
295 case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
297 float specularFactor;
298 if(propertyValue.Get(specularFactor))
300 mTextureInformations[TextureIndex::SPECULAR].mFactor.x = specularFactor;
301 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
305 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
307 std::string specularColorUrl;
308 if(propertyValue.Get(specularColorUrl))
310 RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR_COLOR], specularColorUrl);
315 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
317 Vector3 specularColorFactor;
318 if(propertyValue.Get(specularColorFactor))
320 mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor = specularColorFactor;
321 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
333 Dali::Property::Value Material::GetProperty(Dali::Property::Index index) const
335 Dali::Property::Value value;
338 case Dali::Scene3D::Material::Property::NAME:
343 case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
345 value = mTextureInformations[TextureIndex::BASE_COLOR].mUrl;
348 case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
350 value = mTextureInformations[TextureIndex::BASE_COLOR].mFactor;
353 case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
355 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mUrl;
358 case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
360 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x;
363 case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
365 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y;
368 case Dali::Scene3D::Material::Property::NORMAL_URL:
370 value = mTextureInformations[TextureIndex::NORMAL].mUrl;
373 case Dali::Scene3D::Material::Property::NORMAL_SCALE:
375 value = mTextureInformations[TextureIndex::NORMAL].mFactor.x;
378 case Dali::Scene3D::Material::Property::OCCLUSION_URL:
380 value = mTextureInformations[TextureIndex::OCCLUSION].mUrl;
383 case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
385 value = mTextureInformations[TextureIndex::OCCLUSION].mFactor.x;
388 case Dali::Scene3D::Material::Property::EMISSIVE_URL:
390 value = mTextureInformations[TextureIndex::EMISSIVE].mUrl;
393 case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
395 value = Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor);
398 case Dali::Scene3D::Material::Property::ALPHA_MODE:
403 case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
405 value = mAlphaCutoff;
408 case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
410 value = mDoubleSided;
413 case Dali::Scene3D::Material::Property::IOR:
418 case Dali::Scene3D::Material::Property::SPECULAR_URL:
420 value = mTextureInformations[TextureIndex::SPECULAR].mUrl;
423 case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
425 value = mTextureInformations[TextureIndex::SPECULAR].mFactor.x;
428 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
430 value = mTextureInformations[TextureIndex::SPECULAR_COLOR].mUrl;
433 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
435 value = Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor);
442 void Material::SetTextureInformation(Scene3D::Material::TextureType index, TextureInformation&& textureInformation)
444 mTextureInformations[index].mFactor = textureInformation.mFactor;
445 mTextureInformations[index].mSampler = textureInformation.mSampler;
446 mTextureInformations[index].mTexture = textureInformation.mTexture;
447 mTextureInformations[index].mUrl = std::move(textureInformation.mUrl);
450 void Material::SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture)
452 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
454 if(mTextureInformations[index].mTexture != texture)
456 if(mTextureInformations[index].mLoadingTaskId != INVALID_INDEX)
458 mAsyncImageLoader.Cancel(mTextureInformations[index].mLoadingTaskId);
459 mTextureInformations[index].mLoadingTaskId = INVALID_INDEX;
461 mTextureInformations[index].mTexture = texture;
462 if(IsResourceReady())
464 ResourcesLoadComplete();
470 Dali::Texture Material::GetTexture(Scene3D::Material::TextureType index)
472 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
474 return mTextureInformations[index].mTexture;
476 return Dali::Texture();
479 TextureSet Material::GetTextureSet()
481 TextureSet textures = TextureSet::New();
482 for(uint32_t i = 0, count = 0; i < TEXTURE_TYPE_NUMBER; ++i)
484 if(!mTextureInformations[i].mTexture)
488 textures.SetTexture(count, mTextureInformations[i].mTexture);
489 Sampler sampler = mTextureInformations[i].mSampler;
492 auto samplerFlag = Scene3D::Loader::SamplerFlags::FILTER_LINEAR | (Scene3D::Loader::SamplerFlags::FILTER_LINEAR << Scene3D::Loader::SamplerFlags::FILTER_MAG_SHIFT) |
493 (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_S_SHIFT) | (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_T_SHIFT);
494 sampler = Scene3D::Loader::SamplerFlags::MakeSampler(samplerFlag);
496 textures.SetSampler(count, sampler);
502 void Material::SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler)
504 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
506 mTextureInformations[index].mSampler = sampler;
510 Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index)
512 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
514 return mTextureInformations[index].mSampler;
516 return Dali::Sampler();
519 std::string Material::GetVertexShader()
521 return mShaderData.mVertexShaderSource;
524 std::string Material::GetFragmentShader()
526 return mShaderData.mFragmentShaderSource;
529 void Material::Apply()
531 if(IsResourceReady())
533 UpdateMaterialData();
537 // The cases this material is applied to primitive are,
538 // 1. material is added on Primitive.
539 // When material is added on Primitive (1 case)
540 // 1-1. when IsResourceReady() returns true,
541 // Primitive can takes information from Material
543 // Material will noti to primitives when all resources are ready.
544 // 2. Some properties are changed
545 // 2-1. when IsResourceReady() returns true,
546 // Call NotifyObserver directly.
548 // Material will noti to primitives when all resources are ready.
551 void Material::AddObserver(MaterialModifyObserver* observer)
553 for(auto& observerEntity : mObservers)
555 if(observerEntity.first == observer)
557 observerEntity.second = true;
561 mObservers.push_back({observer, true});
564 void Material::RemoveObserver(MaterialModifyObserver* observer)
566 // Block during notifying to observer
567 if(mObserverNotifying)
569 for(uint32_t i = 0; i < mObservers.size(); ++i)
571 if(mObservers[i].first == observer)
573 mObservers[i].second = false;
580 for(uint32_t i = 0; i < mObservers.size(); ++i)
582 if(mObservers[i].first == observer)
584 mObservers.erase(mObservers.begin() + i);
591 void Material::UpdateMaterialData()
593 uint32_t materialFlag = 0u;
594 if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::BLEND)
598 materialFlag |= Scene3D::Loader::MaterialDefinition::TRANSPARENCY;
600 else if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::MASK)
605 const bool hasTransparency = MaskMatch(materialFlag, Scene3D::Loader::MaterialDefinition::TRANSPARENCY);
607 for(auto&& textureInformation : mTextureInformations)
609 if(!textureInformation.mTexture)
613 materialFlag |= textureInformation.mSemantic;
616 if(mMaterialFlag != materialFlag || mShaderData.mVertexShaderSource.empty() || mShaderData.mFragmentShaderSource.empty())
618 mModifyFlag |= MaterialModifyObserver::ModifyFlag::SHADER;
620 mMaterialFlag = materialFlag;
621 mShaderData.mVertexShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
622 mShaderData.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
624 std::vector<std::string> defines;
625 defines.push_back(THREE_TEX_KEYWORD.data());
626 for(auto&& textureInformation : mTextureInformations)
628 if(!textureInformation.mTexture)
632 defines.push_back(textureInformation.mDefineKeyword);
634 defines.push_back(GLTF_CHANNELS_KEYWORD.data());
636 for(const auto& define : defines)
638 Scene3D::Loader::ShaderDefinition::ApplyDefine(mShaderData.mFragmentShaderSource, define);
642 // Finish to make all the material flag according to the gltf2-util.
643 // Then make defines as fallowing shader-definition-factory.
645 // The renderer State below can be used in primitive to set renderer properties.
647 // for renderer setting
648 mRendererState = Scene3D::Loader::RendererState::DEPTH_TEST;
651 mRendererState |= Scene3D::Loader::RendererState::CULL_BACK;
656 mRendererState = (mRendererState | Scene3D::Loader::RendererState::ALPHA_BLEND);
660 bool Material::IsResourceReady()
662 for(auto&& textureInformation : mTextureInformations)
664 if(!textureInformation.IsReady())
672 void Material::SetRendererUniform(Dali::Renderer renderer)
674 renderer.RegisterProperty("uColorFactor", mTextureInformations[TextureIndex::BASE_COLOR].mFactor);
675 renderer.RegisterProperty("uMetallicFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x);
676 renderer.RegisterProperty("uRoughnessFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y);
677 renderer.RegisterProperty("uNormalScale", mTextureInformations[TextureIndex::NORMAL].mFactor.x);
678 if(mTextureInformations[TextureIndex::OCCLUSION].mTexture)
680 renderer.RegisterProperty("uOcclusionStrength", mTextureInformations[TextureIndex::OCCLUSION].mFactor.x);
682 renderer.RegisterProperty("uEmissiveFactor", Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor));
683 float dielectricSpecular = (Dali::Equals(mIor, -1.0)) ? 0.04f : powf((mIor - 1.0f) / (mIor + 1.0f), 2.0f);
684 renderer.RegisterProperty("uDielectricSpecular", dielectricSpecular);
685 renderer.RegisterProperty("uSpecularFactor", mTextureInformations[TextureIndex::SPECULAR].mFactor.x);
686 renderer.RegisterProperty("uSpecularColorFactor", Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor));
688 float opaque = mIsOpaque ? 1.0f : 0.0f;
689 float mask = mIsMask ? 1.0f : 0.0f;
690 renderer.RegisterProperty("uOpaque", opaque);
691 renderer.RegisterProperty("uMask", mask);
692 renderer.RegisterProperty("uAlphaThreshold", mAlphaCutoff);
694 renderer.RegisterProperty("uCubeMatrix", Matrix::IDENTITY);
696 renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), 6.f);
697 renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), 1.0f);
698 renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName().data(), Vector3(1.0f, -1.0, 1.0));
700 std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
701 renderer.RegisterProperty(lightCountPropertyName, 0);
703 uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
704 for(uint32_t i = 0; i < maxLightCount; ++i)
706 std::string lightDirectionPropertyName(Scene3D::Internal::Light::GetLightDirectionUniformName());
707 lightDirectionPropertyName += "[" + std::to_string(i) + "]";
708 renderer.RegisterProperty(lightDirectionPropertyName, Vector3::ZAXIS);
710 std::string lightColorPropertyName(Scene3D::Internal::Light::GetLightColorUniformName());
711 lightColorPropertyName += "[" + std::to_string(i) + "]";
712 renderer.RegisterProperty(lightColorPropertyName, Vector3(Color::WHITE));
715 Scene3D::Loader::RendererState::Apply(mRendererState, renderer);
718 uint32_t Material::GetSpecularImageBasedLightTextureOffset()
720 return OFFSET_FOR_SPECULAR_CUBE_TEXTURE;
723 uint32_t Material::GetDiffuseImageBasedLightTextureOffset()
725 return OFFSET_FOR_DIFFUSE_CUBE_TEXTURE;
728 std::string_view Material::GetImageBasedLightScaleFactorName()
730 return Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName();
733 std::string_view Material::GetImageBasedLightMaxLodUniformName()
735 return Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName();
738 void Material::ResetFlag()
740 mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
743 void Material::NotifyObserver()
745 if(mModifyFlag != MaterialModifyObserver::ModifyFlag::NONE && IsResourceReady())
747 if(mObserverNotifying)
749 DALI_LOG_ERROR("Notify during observing is not allowed.");
753 Dali::Scene3D::Material handle(this); // Keep itself's life during notify
755 // Copy the flag due to the flag can be changed during observe.
756 MaterialModifyObserver::ModifyFlag copiedFlag = mModifyFlag;
757 mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
759 // Need to block mObserver container change during observe
760 mObserverNotifying = true;
761 for(uint32_t i = 0; i < mObservers.size(); ++i)
763 if(mObservers[i].second)
765 mObservers[i].first->OnMaterialModified(handle, copiedFlag);
768 mObserverNotifying = false;
770 // Resolve observer queue during notify
771 mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e) { return !e.second; }), mObservers.end());
775 void Material::RequestTextureLoad(TextureInformation& textureInformation, const std::string& url)
777 if(textureInformation.mUrl == url)
782 textureInformation.mUrl = url;
783 if(textureInformation.mLoadingTaskId != INVALID_INDEX)
785 mAsyncImageLoader.Cancel(textureInformation.mLoadingTaskId);
786 textureInformation.mLoadingTaskId = INVALID_INDEX;
791 textureInformation.mTexture.Reset();
794 textureInformation.mLoadingTaskId = mAsyncImageLoader.Load(url);
797 void Material::TextureLoadComplete(uint32_t loadedTaskId, PixelData pixelData)
799 for(auto&& textureInformation : mTextureInformations)
801 if(textureInformation.mLoadingTaskId != loadedTaskId)
808 textureInformation.mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
809 textureInformation.mTexture.Upload(pixelData);
811 textureInformation.mLoadingTaskId = INVALID_INDEX;
815 if(IsResourceReady())
817 ResourcesLoadComplete();
821 void Material::ResourcesLoadComplete()
823 mModifyFlag |= MaterialModifyObserver::ModifyFlag::TEXTURE;
827 } // namespace Internal
829 } // namespace Scene3D