[Tizen] LookAt API for actor
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-coords.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 #include <dali/internal/common/matrix-utils.h>
18 #include <dali/internal/event/actors/actor-coords.h>
19 #include <dali/internal/event/common/event-thread-services.h>
20 #include <dali/internal/event/common/projection.h>
21 #include <dali/internal/event/common/scene-impl.h>
22 #include <dali/internal/update/nodes/node.h>
23
24 namespace Dali::Internal
25 {
26 namespace
27 {
28 /**
29  * @brief Get the Viewport Extents from RenderTask
30  *
31  * @param[in] renderTask RenderTask what we want to get viewport.
32  * @param[out] viewportExtent Calculated extent by renderTask.
33  * @return True if we success to get viewports. False otherwise
34  */
35 bool GetViewportExtentsFromRenderTask(const RenderTask& renderTask, Rect<float>& viewportExtent)
36 {
37   if(renderTask.GetFrameBuffer())
38   {
39     Dali::Actor mappingActor = renderTask.GetScreenToFrameBufferMappingActor();
40     if(mappingActor)
41     {
42       // NOTE : We will assume that mapping actor always use default camera.
43       Vector2 screenPosition    = mappingActor.GetProperty<Vector2>(Dali::Actor::Property::SCREEN_POSITION);
44       Vector3 size              = mappingActor.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE) * mappingActor.GetCurrentProperty<Vector3>(Dali::Actor::Property::WORLD_SCALE);
45       Vector3 anchorPointOffSet = size * GetImplementation(mappingActor).GetAnchorPointForPosition();
46       Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
47       viewportExtent.x          = position.x;
48       viewportExtent.y          = position.y;
49       viewportExtent.width      = size.x;
50       viewportExtent.height     = size.y;
51     }
52     else
53     {
54       return false;
55     }
56   }
57   else
58   {
59     Viewport viewport;
60     renderTask.GetViewport(viewport);
61     viewportExtent.x      = viewport.x;
62     viewportExtent.y      = viewport.y;
63     viewportExtent.width  = viewport.width;
64     viewportExtent.height = viewport.height;
65   }
66   return true;
67 }
68
69 /**
70  * @brief Get the Orientation from Forward vector and Up vector
71  * If vectors are valid, return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
72  * If some invalid vector inputed (like Zero length, or parallel vector), return identity quaternion
73  *
74  * @param[in] forward The vector that want to be +Z axis.
75  * @param[in] up The vector that want to be -Y axis.
76  * @return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
77  */
78 Quaternion GetOrientationFromForwardAndUpVector(Vector3 forward, Vector3 up)
79 {
80   Vector3 vZ = forward;
81   vZ.Normalize();
82
83   Vector3 vX = up.Cross(vZ);
84   vX.Normalize();
85
86   // If something invalid input comes, vX length become zero.
87   if(DALI_UNLIKELY(Dali::EqualsZero(vX.Length())))
88   {
89     DALI_LOG_ERROR("Invalid value inputed, forward : %f %f %f ,  up : %f %f %f\n", forward.x, forward.y, forward.z, up.x, up.y, up.z);
90     return Quaternion();
91   }
92
93   Vector3 vY = vZ.Cross(vX);
94   vY.Normalize();
95
96   return Quaternion(vX, vY, vZ);
97 }
98 } // namespace
99 bool ConvertScreenToLocal(
100   const Matrix&   viewMatrix,
101   const Matrix&   projectionMatrix,
102   const Matrix&   worldMatrix,
103   const Vector3&  currentSize,
104   const Viewport& viewport,
105   float&          localX,
106   float&          localY,
107   float           screenX,
108   float           screenY)
109 {
110   // Get the ModelView matrix
111   Matrix modelView;
112   MatrixUtils::MultiplyTransformMatrix(modelView, worldMatrix, viewMatrix);
113
114   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
115   Matrix invertedMvp(false /*don't init*/);
116   MatrixUtils::MultiplyProjectionMatrix(invertedMvp, modelView, projectionMatrix);
117   bool success = invertedMvp.Invert();
118
119   // Convert to GL coordinates
120   Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
121
122   Vector4 nearPos;
123   if(success)
124   {
125     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
126   }
127
128   Vector4 farPos;
129   if(success)
130   {
131     screenPos.z = 1.0f;
132     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
133   }
134
135   if(success)
136   {
137     Vector4 local;
138     if(XyPlaneIntersect(nearPos, farPos, local))
139     {
140       Vector3 size = currentSize;
141       localX       = local.x + size.x * 0.5f;
142       localY       = local.y + size.y * 0.5f;
143     }
144     else
145     {
146       success = false;
147     }
148   }
149
150   return success;
151 }
152
153 bool ConvertScreenToLocalRenderTask(
154   const RenderTask& renderTask,
155   const Matrix&     worldMatrix,
156   const Vector3&    currentSize,
157   float&            localX,
158   float&            localY,
159   float             screenX,
160   float             screenY)
161 {
162   bool         success = false;
163   CameraActor* camera  = renderTask.GetCameraActor();
164   if(camera)
165   {
166     Viewport viewport;
167     renderTask.GetViewport(viewport);
168
169     // need to translate coordinates to render tasks coordinate space
170     Vector2 converted(screenX, screenY);
171     if(renderTask.TranslateCoordinates(converted))
172     {
173       success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
174     }
175   }
176   return success;
177 }
178
179 bool ConvertScreenToLocalRenderTaskList(
180   const RenderTaskList& renderTaskList,
181   const Matrix&         worldMatrix,
182   const Vector3&        currentSize,
183   float&                localX,
184   float&                localY,
185   float                 screenX,
186   float                 screenY)
187 {
188   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
189   uint32_t taskCount = renderTaskList.GetTaskCount();
190   for(uint32_t i = taskCount; i > 0; --i)
191   {
192     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
193     if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
194     {
195       // found a task where this conversion was ok so return
196       return true;
197     }
198   }
199   return false;
200 };
201
202 const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
203 {
204   Scene& scene = actor.GetScene();
205   if(actor.OnScene())
206   {
207     const auto& node           = actor.GetNode();
208     Vector3     worldPosition  = node.GetWorldPosition(bufferIndex);
209     Vector3     cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
210     worldPosition -= cameraPosition;
211
212     Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
213     auto    sceneSize = scene.GetCurrentSurfaceRect();                      // Use the update object's size
214     Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
215     Vector3 halfActorSize(actorSize * 0.5f);
216     Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
217     return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
218                    halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
219   }
220   return Vector2::ZERO;
221 }
222
223 Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosition, BufferIndex bufferIndex)
224 {
225   const auto& node              = actor.GetNode();
226   Vector3     size              = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
227   Vector3     anchorPointOffSet = size * actor.GetAnchorPointForPosition();
228   Vector2     position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
229   return {position.x, position.y, size.x, size.y};
230 }
231
232 bool ConvertLocalToScreen(
233   const Matrix&  viewMatrix,
234   const Matrix&  projectionMatrix,
235   const Matrix&  worldMatrix,
236   const Rect<>&  viewportExtent,
237   const Vector3& localPosition,
238   float&         screenX,
239   float&         screenY)
240 {
241   bool success = false;
242
243   // Convert local to projection coordinates
244   // note, P*(V*(M*pos))) is faster than (P*V*M)*pos
245   Vector4 mvpPos(localPosition.x, localPosition.y, localPosition.z, 1.0f);
246
247   mvpPos = worldMatrix * mvpPos;
248   mvpPos = viewMatrix * mvpPos;
249   mvpPos = projectionMatrix * mvpPos;
250
251   if(DALI_LIKELY(!EqualsZero(mvpPos.w)))
252   {
253     success = true;
254     screenX = viewportExtent.x + (mvpPos.x + mvpPos.w) * viewportExtent.width * 0.5f / mvpPos.w;
255     screenY = viewportExtent.y + (-mvpPos.y + mvpPos.w) * viewportExtent.height * 0.5f / mvpPos.w;
256   }
257   return success;
258 }
259
260 bool ConvertLocalToScreenRenderTask(
261   const RenderTask& renderTask,
262   const Actor&      actor,
263   const Matrix&     worldMatrix,
264   const Vector3&    localPosition,
265   float&            screenX,
266   float&            screenY)
267 {
268   bool         success     = false;
269   const Actor* sourceActor = renderTask.GetSourceActor();
270   if(sourceActor == nullptr)
271   {
272     return success;
273   }
274
275   // Check whether current actor is in this rendertask.
276   bool         actorInRendertask = false;
277   const Actor* targetActor       = &actor;
278   while(targetActor)
279   {
280     if(sourceActor == targetActor)
281     {
282       actorInRendertask = true;
283       break;
284     }
285     targetActor = targetActor->GetParent();
286   }
287   if(!actorInRendertask)
288   {
289     return success;
290   }
291
292   CameraActor* camera = renderTask.GetCameraActor();
293   if(camera)
294   {
295     Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
296     if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
297     {
298       return success;
299     }
300
301     if(ConvertLocalToScreen(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, viewportExtent, localPosition, screenX, screenY))
302     {
303       success = true;
304     }
305   }
306   return success;
307 }
308
309 bool ConvertLocalToScreenRenderTaskList(
310   const RenderTaskList& renderTaskList,
311   const Actor&          actor,
312   const Matrix&         worldMatrix,
313   const Vector3&        localPosition,
314   float&                screenX,
315   float&                screenY)
316 {
317   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
318   uint32_t taskCount = renderTaskList.GetTaskCount();
319   for(uint32_t i = taskCount; i > 0; --i)
320   {
321     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
322     if(ConvertLocalToScreenRenderTask(*task, actor, worldMatrix, localPosition, screenX, screenY))
323     {
324       // found a task where this conversion was ok so return
325       return true;
326     }
327   }
328   return false;
329 }
330
331 const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
332 {
333   if(actor.OnScene())
334   {
335     const auto& node  = actor.GetNode();
336     Scene&      scene = actor.GetScene();
337
338     Vector2 result;
339
340     auto        worldMatrix    = node.GetWorldMatrix(bufferIndex);
341     const auto& renderTaskList = scene.GetRenderTaskList();
342     ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex) * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
343
344     return result;
345   }
346   return Vector2::ZERO;
347 }
348
349 bool ConvertLocalToScreenExtentRenderTask(
350   const RenderTask& renderTask,
351   const Actor&      actor,
352   const Matrix&     worldMatrix,
353   const Vector3&    currentSize,
354   Rect<>&           screenExtent)
355 {
356   bool         success     = false;
357   const Actor* sourceActor = renderTask.GetSourceActor();
358   if(sourceActor == nullptr)
359   {
360     return success;
361   }
362
363   // Check whether current actor is in this rendertask.
364   bool         actorInRendertask = false;
365   const Actor* targetActor       = &actor;
366   while(targetActor)
367   {
368     if(sourceActor == targetActor)
369     {
370       actorInRendertask = true;
371       break;
372     }
373     targetActor = targetActor->GetParent();
374   }
375   if(!actorInRendertask)
376   {
377     return success;
378   }
379
380   CameraActor* camera = renderTask.GetCameraActor();
381   if(camera)
382   {
383     Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
384     if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
385     {
386       return success;
387     }
388
389     constexpr uint32_t BOX_POINT_COUNT           = 8;
390     const Vector3      BBOffset[BOX_POINT_COUNT] = {
391       Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
392       Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
393       Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
394       Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
395       Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
396       Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
397       Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
398       Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
399     };
400
401     float minScreenX = 0.0f;
402     float minScreenY = 0.0f;
403     float maxScreenX = 0.0f;
404     float maxScreenY = 0.0f;
405
406     const auto& viewMatrix       = camera->GetViewMatrix();
407     const auto& projectionMatrix = camera->GetProjectionMatrix();
408
409     success = ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, BBOffset[0], minScreenX, minScreenY);
410     if(success)
411     {
412       maxScreenX = minScreenX;
413       maxScreenY = minScreenY;
414       for(uint32_t i = 1; i < BOX_POINT_COUNT; ++i)
415       {
416         float   screenX       = 0.0f;
417         float   screenY       = 0.0f;
418         Vector3 localPosition = BBOffset[i];
419         if(DALI_UNLIKELY(!ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, localPosition, screenX, screenY)))
420         {
421           success = false;
422           break;
423         }
424         minScreenX = std::min(minScreenX, screenX);
425         maxScreenX = std::max(maxScreenX, screenX);
426         minScreenY = std::min(minScreenY, screenY);
427         maxScreenY = std::max(maxScreenY, screenY);
428       }
429       if(success)
430       {
431         screenExtent.x      = minScreenX;
432         screenExtent.y      = minScreenY;
433         screenExtent.width  = maxScreenX - minScreenX;
434         screenExtent.height = maxScreenY - minScreenY;
435       }
436     }
437   }
438   return success;
439 }
440
441 bool ConvertLocalToScreenExtentRenderTaskList(
442   const RenderTaskList& renderTaskList,
443   const Actor&          actor,
444   const Matrix&         worldMatrix,
445   const Vector3&        currentSize,
446   Rect<>&               screenExtent)
447 {
448   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
449   uint32_t taskCount = renderTaskList.GetTaskCount();
450   for(uint32_t i = taskCount; i > 0; --i)
451   {
452     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
453     if(ConvertLocalToScreenExtentRenderTask(*task, actor, worldMatrix, currentSize, screenExtent))
454     {
455       // found a task where this conversion was ok so return
456       return true;
457     }
458   }
459   return false;
460 }
461
462 Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
463 {
464   Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
465
466   if(actor.OnScene())
467   {
468     const auto& node  = actor.GetNode();
469     Scene&      scene = actor.GetScene();
470
471     auto        worldMatrix    = node.GetWorldMatrix(bufferIndex);
472     const auto& renderTaskList = scene.GetRenderTaskList();
473     ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result);
474   }
475   return result;
476 }
477
478 /**
479  * @brief Computes and center position by using transform properties.
480  * @param[in] anchorPoint anchorPoint of an actor.
481  * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
482  * @param[in] size size of an actor.
483  * @param[in] scale scale of an actor.
484  * @param[in] orientation orientation of an actor.
485  */
486 Vector3 CalculateCenterPosition(
487   const Vector3&    anchorPoint,
488   const bool        positionUsesAnchorPoint,
489   const Vector3&    size,
490   const Vector3&    scale,
491   const Quaternion& orientation)
492 {
493   Vector3       centerPosition;
494   const Vector3 half(0.5f, 0.5f, 0.5f);
495   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
496   // Calculate the center-point by applying the scale and rotation on the anchor point.
497   centerPosition = (half - anchorPoint) * size * scale;
498   centerPosition *= orientation;
499
500   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
501   if(!positionUsesAnchorPoint)
502   {
503     centerPosition -= (topLeft - anchorPoint) * size;
504   }
505   return centerPosition;
506 }
507
508 Matrix CalculateActorWorldTransform(const Actor& actor)
509 {
510   enum InheritanceMode
511   {
512     DONT_INHERIT_TRANSFORM = 0,
513     INHERIT_POSITION       = 1,
514     INHERIT_SCALE          = 2,
515     INHERIT_ORIENTATION    = 4,
516     INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
517   };
518
519   std::vector<Dali::Actor>     descentList;
520   std::vector<InheritanceMode> inheritanceModeList;
521   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
522   int                          inheritance = 0;
523   do
524   {
525     inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
526                   (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
527                   static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
528     inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
529     descentList.push_back(currentActor);
530     currentActor = currentActor.GetParent();
531   } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
532
533   Matrix  worldMatrix;
534   Vector3 localPosition;
535
536   // descentList is leaf first, so traverse from root (end) to leaf (beginning)
537   const size_t descentCount = descentList.size();
538   for(size_t iter = 0u; iter < descentCount; ++iter)
539   {
540     auto       i                       = descentCount - iter - 1u;
541     Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
542     Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
543     bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
544     Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
545     Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
546     Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
547     Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
548
549     Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
550     if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
551     {
552       Matrix  localMatrix;
553       Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
554       if(inheritanceModeList[i] == INHERIT_ALL)
555       {
556         localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
557         localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
558
559         //Update the world matrix
560         Matrix tempMatrix;
561         MatrixUtils::MultiplyTransformMatrix(tempMatrix, localMatrix, worldMatrix);
562         worldMatrix = tempMatrix;
563       }
564       else
565       {
566         Vector3    parentPosition, parentScale;
567         Quaternion parentOrientation;
568         worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
569
570         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
571         {
572           //Don't inherit scale
573           localScale /= parentScale;
574         }
575
576         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
577         {
578           //Don't inherit orientation
579           parentOrientation.Invert();
580           localOrientation = parentOrientation * localOrientation;
581         }
582
583         if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
584         {
585           localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
586           Matrix tempMatrix;
587           MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
588           worldMatrix = tempMatrix;
589           worldMatrix.SetTranslation(actorPosition + centerPosition);
590         }
591         else
592         {
593           localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
594           localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
595           Matrix tempMatrix;
596           MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
597           worldMatrix = tempMatrix;
598         }
599       }
600     }
601     else
602     {
603       localPosition = actorPosition + centerPosition;
604       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
605     }
606   }
607
608   return worldMatrix;
609 }
610
611 Vector4 CalculateActorWorldColor(const Actor& actor)
612 {
613   std::vector<Dali::Actor>     descentList;
614   std::vector<Dali::ColorMode> inheritanceModeList;
615   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
616   Dali::ColorMode              inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
617   do
618   {
619     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
620     inheritanceModeList.push_back(inheritance);
621     descentList.push_back(currentActor);
622     currentActor = currentActor.GetParent();
623   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
624
625   Vector4      worldColor;
626   const size_t descentCount = descentList.size();
627   for(size_t iter = 0u; iter < descentCount; ++iter)
628   {
629     auto i = descentCount - iter - 1u;
630     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
631     {
632       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
633     }
634     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
635     {
636       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
637       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
638     }
639     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
640     {
641       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
642       worldColor *= ownColor;
643     }
644   }
645
646   return worldColor;
647 }
648
649 Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
650 {
651   Vector3 currentWorldPosition = CalculateActorWorldTransform(actor).GetTranslation3();
652
653   Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
654   Quaternion worldToLocal  = GetOrientationFromForwardAndUpVector(localForward, localUp);
655
656   // Rotate by this order : Local --> World --> Target
657   Quaternion ret = worldToTarget / worldToLocal;
658
659   // If we inherit orientation, get parent's world orientation, and revert it.
660   if(actor.IsOrientationInherited() && actor.GetParent())
661   {
662     // Get Parent information.
663     Vector3       parentPosition, parentScale;
664     Quaternion    parentOrientation;
665     const Matrix& parentMatrix = CalculateActorWorldTransform(*actor.GetParent());
666     parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
667
668     ret = ret / parentOrientation;
669   }
670
671   return ret;
672 }
673
674 } // namespace Dali::Internal