Merge "Add color tag for text markup anchor" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / controls / model / model-impl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-scene3d/internal/controls/model/model-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
24 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/integration-api/adaptor-framework/adaptor.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/math/math-utils.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/object/type-registry.h>
31 #include <filesystem>
32
33 // INTERNAL INCLUDES
34 #include <dali-scene3d/internal/common/model-cache-manager.h>
35 #include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>
36 #include <dali-scene3d/internal/light/light-impl.h>
37 #include <dali-scene3d/internal/model-components/model-node-impl.h>
38 #include <dali-scene3d/public-api/controls/model/model.h>
39 #include <dali-scene3d/public-api/loader/animation-definition.h>
40 #include <dali-scene3d/public-api/loader/camera-parameters.h>
41 #include <dali-scene3d/public-api/loader/light-parameters.h>
42 #include <dali-scene3d/public-api/loader/load-result.h>
43 #include <dali-scene3d/public-api/loader/node-definition.h>
44 #include <dali-scene3d/public-api/loader/scene-definition.h>
45 #include <dali-scene3d/public-api/loader/shader-manager.h>
46 #include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
47
48 using namespace Dali;
49
50 namespace Dali
51 {
52 namespace Scene3D
53 {
54 namespace Internal
55 {
56 namespace
57 {
58 /**
59  * Creates control through type registry
60  */
61 BaseHandle Create()
62 {
63   return Scene3D::Model::New(std::string());
64 }
65
66 // Setup properties, signals and actions using the type-registry.
67 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create);
68 DALI_TYPE_REGISTRATION_END()
69
70 static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
71 static constexpr float   SIZE_STEP_CONDITION = 0.1f;
72
73 static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
74 static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
75
76 struct BoundingVolume
77 {
78   void Init()
79   {
80     pointMin = Vector3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
81     pointMax = Vector3(std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min());
82   }
83
84   void ConsiderNewPointInVolume(const Vector3& position)
85   {
86     pointMin.x = std::min(position.x, pointMin.x);
87     pointMin.y = std::min(position.y, pointMin.y);
88     pointMin.z = std::min(position.z, pointMin.z);
89
90     pointMax.x = std::max(position.x, pointMax.x);
91     pointMax.y = std::max(position.y, pointMax.y);
92     pointMax.z = std::max(position.z, pointMax.z);
93   }
94
95   Vector3 CalculateSize()
96   {
97     return pointMax - pointMin;
98   }
99
100   Vector3 CalculatePivot()
101   {
102     Vector3 pivot = pointMin / (pointMin - pointMax);
103     for(uint32_t i = 0; i < 3; ++i)
104     {
105       // To avoid divid by zero
106       if(Dali::Equals(pointMin[i], pointMax[i]))
107       {
108         pivot[i] = 0.5f;
109       }
110     }
111     return pivot;
112   }
113
114   Vector3 pointMin;
115   Vector3 pointMax;
116 };
117
118 void ConfigureBlendShapeShaders(
119   Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
120 {
121   std::vector<std::string> errors;
122   auto                     onError = [&errors](const std::string& msg) { errors.push_back(msg); };
123   if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
124   {
125     Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION);
126     for(auto& msg : errors)
127     {
128       flinger << msg << '\n';
129     }
130   }
131 }
132
133 void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::SceneDefinition& scene, const Dali::Scene3D::Loader::Customization::Choices& choices, Dali::Scene3D::Loader::Index iNode, Dali::Scene3D::Loader::NodeDefinition::CreateParams& nodeParams, Matrix parentMatrix)
134 {
135   static constexpr uint32_t BOX_POINT_COUNT             = 8;
136   static uint32_t           BBIndex[BOX_POINT_COUNT][3] = {{0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1}};
137
138   Matrix                                       nodeMatrix;
139   const Dali::Scene3D::Loader::NodeDefinition* node        = scene.GetNode(iNode);
140   Matrix                                       localMatrix = node->GetLocalSpace();
141   Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix);
142
143   Vector3 volume[2];
144   if(node->GetExtents(nodeParams.mResources, volume[0], volume[1]))
145   {
146     for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i)
147     {
148       Vector4 position       = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f);
149       Vector4 objectPosition = nodeMatrix * position;
150       objectPosition /= objectPosition.w;
151
152       AABB.ConsiderNewPointInVolume(Vector3(objectPosition));
153     }
154   }
155
156   if(node->mCustomization)
157   {
158     if(!node->mChildren.empty())
159     {
160       auto                         choice = choices.Get(node->mCustomization->mTag);
161       Dali::Scene3D::Loader::Index i      = std::min(choice != Dali::Scene3D::Loader::Customization::NONE ? choice : 0, static_cast<Dali::Scene3D::Loader::Index>(node->mChildren.size() - 1));
162
163       AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix);
164     }
165   }
166   else
167   {
168     for(auto i : node->mChildren)
169     {
170       AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix);
171     }
172   }
173 }
174
175 void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
176 {
177   if(!node)
178   {
179     return;
180   }
181   const auto childCount = node.GetChildCount();
182   for(auto i = 0u; i < childCount; ++i)
183   {
184     UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
185   }
186
187   std::vector<std::string> blendShapeNames;
188   node.RetrieveBlendShapeNames(blendShapeNames);
189   for(const auto& iter : blendShapeNames)
190   {
191     // Append or create new list.
192     resultMap[iter].push_back(node);
193   }
194 }
195
196 void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderManagerPtr shaderManager)
197 {
198   if(!node)
199   {
200     return;
201   }
202
203   GetImplementation(node).UpdateShader(shaderManager);
204
205   uint32_t childrenCount = node.GetChildCount();
206   for(uint32_t i = 0; i < childrenCount; ++i)
207   {
208     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
209     if(childNode)
210     {
211       UpdateShaderRecursively(childNode, shaderManager);
212     }
213   }
214 }
215
216 void UpdateShadowMapTextureRecursively(Scene3D::ModelNode node, Dali::Texture shadowMapTexture)
217 {
218   if(!node)
219   {
220     return;
221   }
222
223   GetImplementation(node).SetShadowMapTexture(shadowMapTexture);
224
225   uint32_t childrenCount = node.GetChildCount();
226   for(uint32_t i = 0; i < childrenCount; ++i)
227   {
228     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
229     if(childNode)
230     {
231       UpdateShadowMapTextureRecursively(childNode, shadowMapTexture);
232     }
233   }
234 }
235
236 } // anonymous namespace
237
238 Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
239 : Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)),
240   mModelUrl(modelUrl),
241   mResourceDirectoryUrl(resourceDirectoryUrl),
242   mModelRoot(),
243   mShaderManager(new Scene3D::Loader::ShaderManager()),
244   mNaturalSize(Vector3::ZERO),
245   mModelPivot(AnchorPoint::CENTER),
246   mSceneIblScaleFactor(1.0f),
247   mIblScaleFactor(1.0f),
248   mSceneSpecularMipmapLevels(1u),
249   mSpecularMipmapLevels(1u),
250   mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
251   mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
252   mModelResourceReady(false),
253   mIblDiffuseResourceReady(true),
254   mIblSpecularResourceReady(true),
255   mIblDiffuseDirty(false),
256   mIblSpecularDirty(false)
257 {
258 }
259
260 Model::~Model()
261 {
262   ResetResourceTasks();
263
264   if(ModelCacheManager::Get() && !mModelUrl.empty())
265   {
266     ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
267   }
268 }
269
270 Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
271 {
272   Model* impl = new Model(modelUrl, resourceDirectoryUrl);
273
274   Dali::Scene3D::Model handle = Dali::Scene3D::Model(*impl);
275
276   // Second-phase init of the implementation
277   // This can only be done after the CustomActor connection has been made...
278   impl->Initialize();
279
280   return handle;
281 }
282
283 const Scene3D::ModelNode Model::GetModelRoot() const
284 {
285   return mModelRoot;
286 }
287
288 void Model::AddModelNode(Scene3D::ModelNode modelNode)
289 {
290   if(!mModelRoot)
291   {
292     CreateModelRoot();
293   }
294
295   mModelRoot.Add(modelNode);
296   if(mModelUrl.empty())
297   {
298     mModelResourceReady = true;
299   }
300
301   UpdateShaderRecursively(modelNode, mShaderManager);
302
303   if(mShadowMapTexture)
304   {
305     UpdateShadowMapTextureRecursively(modelNode, mShadowMapTexture);
306   }
307
308   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
309   {
310     UpdateImageBasedLightTexture();
311     UpdateImageBasedLightScaleFactor();
312   }
313
314   if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
315   {
316     NotifyResourceReady();
317   }
318 }
319
320 void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
321 {
322   if(mModelRoot)
323   {
324     UpdateShaderRecursively(modelNode, nullptr);
325     mModelRoot.Remove(modelNode);
326   }
327 }
328
329 void Model::SetChildrenSensitive(bool enable)
330 {
331   if(mModelChildrenSensitive != enable)
332   {
333     mModelChildrenSensitive = enable;
334     if(mModelRoot)
335     {
336       mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
337     }
338   }
339 }
340
341 bool Model::GetChildrenSensitive() const
342 {
343   return mModelChildrenSensitive;
344 }
345
346 void Model::SetChildrenFocusable(bool enable)
347 {
348   if(mModelChildrenFocusable != enable)
349   {
350     mModelChildrenFocusable = enable;
351     if(mModelRoot)
352     {
353       mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
354       mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
355     }
356   }
357 }
358
359 bool Model::GetChildrenFocusable() const
360 {
361   return mModelChildrenFocusable;
362 }
363
364 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
365 {
366   bool needIblReset = false;
367   bool isOnScene    = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
368   if(mDiffuseIblUrl != diffuseUrl)
369   {
370     mDiffuseIblUrl = diffuseUrl;
371     if(mDiffuseIblUrl.empty())
372     {
373       needIblReset = true;
374     }
375     else
376     {
377       mIblDiffuseDirty         = true;
378       mIblDiffuseResourceReady = false;
379     }
380   }
381
382   if(mSpecularIblUrl != specularUrl)
383   {
384     mSpecularIblUrl = specularUrl;
385     if(mSpecularIblUrl.empty())
386     {
387       needIblReset = true;
388     }
389     else
390     {
391       mIblSpecularDirty         = true;
392       mIblSpecularResourceReady = false;
393     }
394   }
395
396   // If one or both of diffuse url and specular url are empty,
397   // we don't need to request to load texture.
398   if(needIblReset)
399   {
400     ResetResourceTask(mIblDiffuseLoadTask);
401     ResetResourceTask(mIblSpecularLoadTask);
402
403     mIblDiffuseDirty          = false;
404     mIblSpecularDirty         = false;
405     mIblDiffuseResourceReady  = true;
406     mIblSpecularResourceReady = true;
407
408     mDiffuseTexture.Reset();
409     mSpecularTexture.Reset();
410     UpdateImageBasedLightTexture();
411   }
412   else
413   {
414     if(isOnScene && mIblDiffuseDirty)
415     {
416       ResetResourceTask(mIblDiffuseLoadTask);
417       mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
418       Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
419       mIblDiffuseDirty = false;
420     }
421
422     if(isOnScene && mIblSpecularDirty)
423     {
424       ResetResourceTask(mIblSpecularLoadTask);
425       mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
426       Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
427       mIblSpecularDirty = false;
428     }
429   }
430
431   if(!Dali::Equals(mIblScaleFactor, scaleFactor))
432   {
433     mIblScaleFactor = scaleFactor;
434     UpdateImageBasedLightScaleFactor();
435   }
436
437   // If diffuse and specular textures are already loaded, emits resource ready signal here.
438   NotifyResourceReady();
439 }
440
441 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
442 {
443   mIblScaleFactor = scaleFactor;
444   if(mDiffuseTexture && mSpecularTexture)
445   {
446     UpdateImageBasedLightScaleFactor();
447   }
448 }
449
450 float Model::GetImageBasedLightScaleFactor() const
451 {
452   return mIblScaleFactor;
453 }
454
455 uint32_t Model::GetAnimationCount() const
456 {
457   return mAnimations.size();
458 }
459
460 Dali::Animation Model::GetAnimation(uint32_t index) const
461 {
462   Dali::Animation animation;
463   if(mAnimations.size() > index)
464   {
465     animation = mAnimations[index].second;
466   }
467   return animation;
468 }
469
470 Dali::Animation Model::GetAnimation(const std::string& name) const
471 {
472   Dali::Animation animation;
473   if(!name.empty())
474   {
475     for(auto&& animationData : mAnimations)
476     {
477       if(animationData.first == name)
478       {
479         animation = animationData.second;
480         break;
481       }
482     }
483   }
484   return animation;
485 }
486
487 uint32_t Model::GetCameraCount() const
488 {
489   return mCameraParameters.size();
490 }
491
492 Dali::CameraActor Model::GenerateCamera(uint32_t index) const
493 {
494   Dali::CameraActor camera;
495   if(mCameraParameters.size() > index)
496   {
497     camera = Dali::CameraActor::New3DCamera();
498     if(!mCameraParameters[index].ConfigureCamera(camera, false))
499     {
500       DALI_LOG_ERROR("Fail to generate %u's camera actor : Some property was not defined. Please check model file.\n", index);
501       camera.Reset();
502       return camera;
503     }
504
505     ApplyCameraTransform(camera);
506   }
507   return camera;
508 }
509
510 bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const
511 {
512   if(camera && mCameraParameters.size() > index)
513   {
514     if(!mCameraParameters[index].ConfigureCamera(camera, false))
515     {
516       DALI_LOG_ERROR("Fail to apply %u's camera actor : Some property was not defined. Please check model file.\n", index);
517       return false;
518     }
519
520     ApplyCameraTransform(camera);
521     return true;
522   }
523   return false;
524 }
525
526 Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName)
527 {
528   Actor childActor = Self().FindChildByName(nodeName);
529   return Scene3D::ModelNode::DownCast(childActor);
530 }
531
532 void Model::RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const
533 {
534   blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeModelNodeMap.size());
535   for(const auto& iter : mBlendShapeModelNodeMap)
536   {
537     blendShapeNames.push_back(iter.first);
538   }
539 }
540
541 void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<Scene3D::ModelNode>& modelNodes) const
542 {
543   auto iter = mBlendShapeModelNodeMap.find(std::string(blendShapeName));
544   if(iter != mBlendShapeModelNodeMap.end())
545   {
546     const auto& modelNodeList = iter->second;
547     modelNodes.reserve(modelNodes.size() + modelNodeList.size());
548     for(const auto& nodeIter : modelNodeList)
549     {
550       modelNodes.push_back(nodeIter);
551     }
552   }
553 }
554
555 Dali::Animation Model::GenerateMotionDataAnimation(Scene3D::MotionData motionData)
556 {
557   Dali::Animation animation;
558
559   // TODO : Need to collect duplicated codes with SetMotionData()
560
561   if(motionData)
562   {
563     const uint32_t motionCount = motionData.GetMotionCount();
564     for(uint32_t i = 0u; i < motionCount; ++i)
565     {
566       auto motionIndex = motionData.GetIndex(i);
567       auto motionValue = motionData.GetValue(i);
568       if(motionIndex && motionValue)
569       {
570         if(motionIndex.GetModelNodeId() != Property::INVALID_KEY)
571         {
572           Scene3D::ModelNode modelNode;
573           if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING)
574           {
575             modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey);
576           }
577           else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX)
578           {
579             // TODO : Not implement yet.
580           }
581
582           if(modelNode)
583           {
584             KeyFrames keyFrames = motionValue.GetKeyFrames();
585
586             if(keyFrames)
587             {
588               // Try to use index first. If failed, try to use name
589               Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode);
590               if(animatedPropertyIndex != Property::INVALID_INDEX)
591               {
592                 if(DALI_UNLIKELY(!animation))
593                 {
594                   animation = Animation::New(motionData.GetDuration());
595                 }
596                 animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames);
597               }
598               else
599               {
600                 std::string    animatedPropertyName = motionIndex.GetPropertyName(modelNode);
601                 Dali::Property property(modelNode, animatedPropertyName);
602                 if(property.propertyIndex != Property::INVALID_INDEX)
603                 {
604                   if(DALI_UNLIKELY(!animation))
605                   {
606                     animation = Animation::New(motionData.GetDuration());
607                   }
608                   animation.AnimateBetween(property, keyFrames);
609                 }
610               }
611             }
612           }
613         }
614         else
615         {
616           Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex);
617           if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING)
618           {
619             // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId,
620             // we need to animate all kind of blendshapes
621
622             KeyFrames keyFrames = motionValue.GetKeyFrames();
623
624             if(keyFrames)
625             {
626               std::vector<Scene3D::ModelNode> modelNodes;
627               RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes);
628
629               for(auto& modelNode : modelNodes)
630               {
631                 // Try to use index first. If failed, try to use name
632                 Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode);
633                 if(animatedPropertyIndex != Property::INVALID_INDEX)
634                 {
635                   if(DALI_UNLIKELY(!animation))
636                   {
637                     animation = Animation::New(motionData.GetDuration());
638                   }
639                   animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames);
640                 }
641                 else
642                 {
643                   std::string    animatedPropertyName = motionIndex.GetPropertyName(modelNode);
644                   Dali::Property property(modelNode, animatedPropertyName);
645
646                   if(property.propertyIndex != Property::INVALID_INDEX)
647                   {
648                     if(DALI_UNLIKELY(!animation))
649                     {
650                       animation = Animation::New(motionData.GetDuration());
651                     }
652                     animation.AnimateBetween(property, keyFrames);
653                   }
654                 }
655               }
656             }
657           }
658         }
659       }
660     }
661   }
662
663   return animation;
664 }
665
666 void Model::SetMotionData(Scene3D::MotionData motionData)
667 {
668   // TODO : Need to collect duplicated codes with GenerateMotionDataAnimation()
669
670   if(motionData)
671   {
672     const uint32_t motionCount = motionData.GetMotionCount();
673     for(uint32_t i = 0u; i < motionCount; ++i)
674     {
675       auto motionIndex = motionData.GetIndex(i);
676       auto motionValue = motionData.GetValue(i);
677       if(motionIndex && motionValue)
678       {
679         if(motionIndex.GetModelNodeId() != Property::INVALID_KEY)
680         {
681           Scene3D::ModelNode modelNode;
682           if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING)
683           {
684             modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey);
685           }
686           else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX)
687           {
688             // TODO : Not implement yet.
689           }
690
691           if(modelNode)
692           {
693             Property::Value value = motionValue.GetPropertyValue();
694
695             if(value.GetType() != Property::Type::NONE)
696             {
697               // Try to use index first. If failed, try to use name
698               Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode);
699               if(propertyIndex != Property::INVALID_INDEX)
700               {
701                 modelNode.SetProperty(propertyIndex, value);
702               }
703               else
704               {
705                 std::string    propertyName = motionIndex.GetPropertyName(modelNode);
706                 Dali::Property property(modelNode, propertyName);
707                 if(property.propertyIndex != Property::INVALID_INDEX)
708                 {
709                   modelNode.SetProperty(property.propertyIndex, value);
710                 }
711               }
712             }
713           }
714         }
715         else
716         {
717           Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex);
718           if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING)
719           {
720             // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId,
721             // we need to animate all kind of blendshapes
722
723             Property::Value value = motionValue.GetPropertyValue();
724
725             if(value.GetType() != Property::Type::NONE)
726             {
727               std::vector<Scene3D::ModelNode> modelNodes;
728               RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes);
729
730               for(auto& modelNode : modelNodes)
731               {
732                 // Try to use index first. If failed, try to use name
733                 Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode);
734                 if(propertyIndex != Property::INVALID_INDEX)
735                 {
736                   modelNode.SetProperty(propertyIndex, value);
737                 }
738                 else
739                 {
740                   std::string    propertyName = motionIndex.GetPropertyName(modelNode);
741                   Dali::Property property(modelNode, propertyName);
742                   if(property.propertyIndex != Property::INVALID_INDEX)
743                   {
744                     modelNode.SetProperty(property.propertyIndex, value);
745                   }
746                 }
747               }
748             }
749           }
750         }
751       }
752     }
753   }
754 }
755
756 ///////////////////////////////////////////////////////////
757 //
758 // Private methods
759 //
760
761 void Model::OnInitialize()
762 {
763   // Make ParentOrigin as Center.
764   Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
765 }
766
767 void Model::OnSceneConnection(int depth)
768 {
769   Actor parent = Self().GetParent();
770   while(parent)
771   {
772     // If this Model has parent SceneView and the its ShaderManager is same with privious ShaderManager,
773     // this Model don't need to update shader.
774     Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
775     if(sceneView)
776     {
777       mParentSceneView = sceneView;
778       GetImpl(sceneView).RegisterSceneItem(this);
779       Scene3D::Loader::ShaderManagerPtr shaderManager = GetImpl(sceneView).GetShaderManager();
780       if(mShaderManager != shaderManager)
781       {
782         mShaderManager = shaderManager;
783         UpdateShaderRecursively(mModelRoot, mShaderManager);
784       }
785       break;
786     }
787     parent = parent.GetParent();
788   }
789
790   // Model can be added on Dali::Scene directly without SceneView.
791   // So, Model's mShaderManager and shaders of child ModelNodes are needed to be reset when this Model has not parent SceneView.
792   Scene3D::SceneView parentSceneView = mParentSceneView.GetHandle();
793   if(!parentSceneView)
794   {
795     mShaderManager = new Dali::Scene3D::Loader::ShaderManager();
796     UpdateShaderRecursively(mModelRoot, mShaderManager);
797   }
798
799   if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
800   {
801     // Request model load only if we setup url.
802     if(ModelCacheManager::Get())
803     {
804       ModelCacheManager::Get().ReferenceModelCache(mModelUrl);
805     }
806     mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete));
807     Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask);
808   }
809
810   // If diffuse and specular url is not valid, IBL does not need to be loaded.
811   if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
812   {
813     SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
814   }
815
816   NotifyResourceReady();
817
818   mSizeNotification = Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
819   mSizeNotification.NotifySignal().Connect(this, &Model::OnSizeNotification);
820   Control::OnSceneConnection(depth);
821 }
822
823 void Model::OnSceneDisconnection()
824 {
825   // If mParentSceneView is still onScene, that means this model
826   // is disconnected from mParentSceneView's sub tree.
827   // So, Unregister this Model from SceneView.
828   Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
829   if(sceneView && sceneView.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
830   {
831     GetImpl(sceneView).UnregisterSceneItem(this);
832     mParentSceneView.Reset();
833   }
834
835   mSizeNotification.NotifySignal().Disconnect(this, &Model::OnSizeNotification);
836   Self().RemovePropertyNotification(mSizeNotification);
837   mSizeNotification.Reset();
838
839   Control::OnSceneDisconnection();
840 }
841
842 void Model::OnSizeSet(const Vector3& size)
843 {
844   ScaleModel(false);
845 }
846
847 Vector3 Model::GetNaturalSize()
848 {
849   if(!mModelRoot)
850   {
851     DALI_LOG_ERROR("Model is still not loaded.\n");
852     return Vector3::ZERO;
853   }
854
855   return mNaturalSize;
856 }
857
858 float Model::GetHeightForWidth(float width)
859 {
860   Extents padding;
861   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
862   return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
863 }
864
865 float Model::GetWidthForHeight(float height)
866 {
867   Extents padding;
868   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
869   return Control::GetWidthForHeight(height) + padding.start + padding.end;
870 }
871
872 void Model::OnRelayout(const Vector2& size, RelayoutContainer& container)
873 {
874   Control::OnRelayout(size, container);
875   ScaleModel(false);
876 }
877
878 bool Model::IsResourceReady() const
879 {
880   return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady;
881 }
882
883 void Model::CreateModelRoot()
884 {
885   mModelRoot = Scene3D::ModelNode::New();
886   mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
887   mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION);
888   mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
889   mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
890   mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
891   Self().Add(mModelRoot);
892 }
893
894 void Model::ScaleModel(bool useCurrentSize)
895 {
896   if(!mModelRoot)
897   {
898     return;
899   }
900
901   float   scale = 1.0f;
902   Vector3 size  = (useCurrentSize) ? Self().GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE) : Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
903   if(size.x > 0.0f && size.y > 0.0f)
904   {
905     scale = MAXFLOAT;
906     scale = std::min(size.x / mNaturalSize.x, scale);
907     scale = std::min(size.y / mNaturalSize.y, scale);
908   }
909   // Models in glTF and dli are defined as right hand coordinate system.
910   // DALi uses left hand coordinate system. Scaling negative is for change winding order.
911   mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
912 }
913
914 void Model::FitModelPosition()
915 {
916   if(!mModelRoot)
917   {
918     return;
919   }
920   // Loaded model pivot is not the model center.
921   mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
922   mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
923 }
924
925 void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
926 {
927   if(!node)
928   {
929     return;
930   }
931
932   GetImplementation(node).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
933   uint32_t childrenCount = node.GetChildCount();
934   for(uint32_t i = 0; i < childrenCount; ++i)
935   {
936     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
937     if(!childNode)
938     {
939       continue;
940     }
941     UpdateImageBasedLightTextureRecursively(childNode, diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
942   }
943 }
944
945 void Model::UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor)
946 {
947   if(!node)
948   {
949     return;
950   }
951
952   GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor);
953
954   uint32_t childrenCount = node.GetChildCount();
955   for(uint32_t i = 0; i < childrenCount; ++i)
956   {
957     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
958     if(!childNode)
959     {
960       continue;
961     }
962     UpdateImageBasedLightScaleFactorRecursively(childNode, iblScaleFactor);
963   }
964 }
965
966 void Model::UpdateImageBasedLightTexture()
967 {
968   Dali::Texture currentDiffuseTexture          = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
969   Dali::Texture currentSpecularTexture         = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
970   float         currentIblScaleFactor          = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
971   uint32_t      currentIblSpecularMipmapLevels = (mDiffuseTexture && mSpecularTexture) ? mSpecularMipmapLevels : mSceneSpecularMipmapLevels;
972
973   if(!currentDiffuseTexture || !currentSpecularTexture)
974   {
975     currentDiffuseTexture          = mDefaultDiffuseTexture;
976     currentSpecularTexture         = mDefaultSpecularTexture;
977     currentIblScaleFactor          = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
978     currentIblSpecularMipmapLevels = 1u;
979   }
980
981   UpdateImageBasedLightTextureRecursively(mModelRoot, currentDiffuseTexture, currentSpecularTexture, currentIblScaleFactor, currentIblSpecularMipmapLevels);
982 }
983
984 void Model::UpdateImageBasedLightScaleFactor()
985 {
986   if((!mDiffuseTexture || !mSpecularTexture) &&
987      (!mSceneDiffuseTexture || !mSceneSpecularTexture))
988   {
989     return;
990   }
991
992   float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
993   UpdateImageBasedLightScaleFactorRecursively(mModelRoot, currentIblScaleFactor);
994 }
995
996 void Model::ApplyCameraTransform(Dali::CameraActor camera) const
997 {
998   Vector3    selfPosition    = Self().GetProperty<Vector3>(Actor::Property::POSITION);
999   Quaternion selfOrientation = Self().GetProperty<Quaternion>(Actor::Property::ORIENTATION);
1000   Vector3    selfScale       = Self().GetProperty<Vector3>(Actor::Property::SCALE);
1001
1002   Vector3    cameraPosition    = camera.GetProperty<Vector3>(Actor::Property::POSITION);
1003   Quaternion cameraOrientation = camera.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
1004   Vector3    cameraScale       = camera.GetProperty<Vector3>(Actor::Property::SCALE);
1005
1006   // Models in glTF and dli are defined as right hand coordinate system.
1007   // DALi uses left hand coordinate system. Scaling negative is for change winding order.
1008   if(!Dali::Equals(Y_DIRECTION.Dot(Vector3::YAXIS), 1.0f))
1009   {
1010     // Reflect by XZ plane
1011     cameraPosition.y = -cameraPosition.y;
1012     Quaternion yDirectionQuaternion;
1013     yDirectionQuaternion.mVector = Vector3::YAXIS;
1014     // Reflect orientation
1015     cameraOrientation = yDirectionQuaternion * cameraOrientation * yDirectionQuaternion;
1016   }
1017
1018   Vector3    resultPosition;
1019   Quaternion resultOrientation;
1020   Vector3    resultScale;
1021
1022   Matrix selfMatrix(false);
1023   Matrix cameraMatrix(false);
1024   Matrix resultMatrix(false);
1025   selfMatrix.SetTransformComponents(selfScale, selfOrientation, selfPosition);
1026   cameraMatrix.SetTransformComponents(cameraScale, cameraOrientation, cameraPosition);
1027   Matrix::Multiply(resultMatrix, cameraMatrix, selfMatrix);
1028   resultMatrix.GetTransformComponents(resultPosition, resultOrientation, resultScale);
1029
1030   camera.SetProperty(Actor::Property::POSITION, resultPosition);
1031   camera.SetProperty(Actor::Property::ORIENTATION, resultOrientation);
1032   camera.SetProperty(Actor::Property::SCALE, resultScale);
1033 }
1034
1035 void Model::NotifyShadowMapTexture(Dali::Texture shadowMapTexture)
1036 {
1037   if(mShadowMapTexture != shadowMapTexture)
1038   {
1039     mShadowMapTexture = shadowMapTexture;
1040     UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
1041   }
1042 }
1043
1044 void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
1045 {
1046   if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
1047   {
1048     mSceneDiffuseTexture       = diffuseTexture;
1049     mSceneSpecularTexture      = specularTexture;
1050     mSceneIblScaleFactor       = scaleFactor;
1051     mSceneSpecularMipmapLevels = specularMipmapLevels;
1052     // If Model IBL is not set, use SceneView's IBL.
1053     if(!mDiffuseTexture || !mSpecularTexture)
1054     {
1055       UpdateImageBasedLightTexture();
1056     }
1057   }
1058 }
1059
1060 void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
1061 {
1062   mSceneIblScaleFactor = scaleFactor;
1063   if(mSceneDiffuseTexture && mSceneSpecularTexture)
1064   {
1065     UpdateImageBasedLightScaleFactor();
1066   }
1067 }
1068
1069 void Model::OnModelLoadComplete()
1070 {
1071   IntrusivePtr<Model> self = this; // Keep reference until this API finished
1072
1073   if(!mModelLoadTask->HasSucceeded())
1074   {
1075     ResetResourceTasks();
1076
1077     if(ModelCacheManager::Get() && !mModelUrl.empty())
1078     {
1079       ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
1080     }
1081
1082     return;
1083   }
1084
1085   if(!mModelRoot)
1086   {
1087     CreateModelRoot();
1088   }
1089   CreateModel();
1090
1091   auto& resources = mModelLoadTask->GetResources();
1092   auto& scene     = mModelLoadTask->GetScene();
1093   CreateAnimations(scene);
1094   ResetCameraParameters();
1095   if(!resources.mEnvironmentMaps.empty())
1096   {
1097     mDefaultDiffuseTexture  = resources.mEnvironmentMaps.front().second.mDiffuse;
1098     mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
1099   }
1100
1101   if(mShadowMapTexture)
1102   {
1103     UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
1104   }
1105   UpdateImageBasedLightTexture();
1106   UpdateImageBasedLightScaleFactor();
1107   Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
1108
1109   mModelResourceReady = true;
1110   ResetResourceTask(mModelLoadTask);
1111   NotifyResourceReady();
1112 }
1113
1114 void Model::OnIblDiffuseLoadComplete()
1115 {
1116   mDiffuseTexture = mIblDiffuseLoadTask->GetLoadedTexture();
1117   ResetResourceTask(mIblDiffuseLoadTask);
1118   mIblDiffuseResourceReady = true;
1119   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
1120   {
1121     OnIblLoadComplete();
1122   }
1123 }
1124
1125 void Model::OnIblSpecularLoadComplete()
1126 {
1127   mSpecularTexture      = mIblSpecularLoadTask->GetLoadedTexture();
1128   mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels();
1129   ResetResourceTask(mIblSpecularLoadTask);
1130   mIblSpecularResourceReady = true;
1131   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
1132   {
1133     OnIblLoadComplete();
1134   }
1135 }
1136
1137 void Model::OnIblLoadComplete()
1138 {
1139   UpdateImageBasedLightTexture();
1140   NotifyResourceReady();
1141 }
1142
1143 void Model::OnSizeNotification(Dali::PropertyNotification& source)
1144 {
1145   ScaleModel(true);
1146 }
1147
1148 void Model::ResetResourceTasks()
1149 {
1150   if(!Dali::Adaptor::IsAvailable())
1151   {
1152     return;
1153   }
1154   ResetResourceTask(mModelLoadTask);
1155   ResetResourceTask(mIblDiffuseLoadTask);
1156   ResetResourceTask(mIblSpecularLoadTask);
1157 }
1158
1159 void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
1160 {
1161   if(!asyncTask)
1162   {
1163     return;
1164   }
1165   Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
1166   asyncTask.Reset();
1167 }
1168
1169 void Model::NotifyResourceReady()
1170 {
1171   if(!IsResourceReady())
1172   {
1173     return;
1174   }
1175   Control::SetResourceReady();
1176 }
1177
1178 void Model::CreateModel()
1179 {
1180   BoundingVolume                    AABB;
1181   auto&                             resources       = mModelLoadTask->GetResources();
1182   auto&                             scene           = mModelLoadTask->GetScene();
1183   auto&                             resourceChoices = mModelLoadTask->GetResourceChoices();
1184   Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
1185
1186   Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, mShaderManager, {}, {}, {}};
1187
1188   // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
1189   resources.GenerateResources();
1190   for(auto iRoot : scene.GetRoots())
1191   {
1192     if(auto modelNode = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
1193     {
1194       scene.ConfigureSkinningShaders(resources, modelNode, std::move(nodeParams.mSkinnables));
1195       ConfigureBlendShapeShaders(resources, scene, modelNode, std::move(nodeParams.mBlendshapeRequests));
1196
1197       scene.ApplyConstraints(modelNode, std::move(nodeParams.mConstrainables));
1198
1199       mModelRoot.Add(modelNode);
1200     }
1201
1202     AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
1203   }
1204
1205   UpdateBlendShapeNodeMap();
1206
1207   mNaturalSize = AABB.CalculateSize();
1208   mModelPivot  = AABB.CalculatePivot();
1209   mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
1210   Vector3 controlSize = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
1211   if(Dali::EqualsZero(controlSize.x) || Dali::EqualsZero(controlSize.y))
1212   {
1213     Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
1214   }
1215   FitModelPosition();
1216   ScaleModel(false);
1217 }
1218
1219 void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
1220 {
1221   mAnimations.clear();
1222   if(!mModelLoadTask->GetAnimations().empty())
1223   {
1224     auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) {
1225       if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
1226       {
1227         return mModelRoot.FindChildByName(property.mNodeName);
1228       }
1229       auto* node = scene.GetNode(property.mNodeIndex);
1230       if(node == nullptr)
1231       {
1232         return Dali::Actor();
1233       }
1234       return mModelRoot.FindChildById(node->mNodeId);
1235     };
1236
1237     for(auto&& animation : mModelLoadTask->GetAnimations())
1238     {
1239       Dali::Animation anim = animation.ReAnimate(getActor);
1240       mAnimations.push_back({animation.GetName(), anim});
1241     }
1242   }
1243 }
1244
1245 void Model::ResetCameraParameters()
1246 {
1247   mCameraParameters.clear();
1248   if(!mModelLoadTask->GetCameras().empty())
1249   {
1250     // Copy camera parameters.
1251     std::copy(mModelLoadTask->GetCameras().begin(), mModelLoadTask->GetCameras().end(), std::back_inserter(mCameraParameters));
1252   }
1253 }
1254
1255 void Model::UpdateBlendShapeNodeMap()
1256 {
1257   // Remove privous node map
1258   mBlendShapeModelNodeMap.clear();
1259
1260   UpdateBlendShapeNodeMapRecursively(mBlendShapeModelNodeMap, mModelRoot);
1261 }
1262
1263 } // namespace Internal
1264 } // namespace Scene3D
1265 } // namespace Dali