Merge branch 'devel/master' into tizen
[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         // Get Parent information.
567         Vector3       parentPosition, parentScale;
568         Quaternion    parentOrientation;
569         const Matrix& parentMatrix = worldMatrix;
570         parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
571
572         // Compute intermediate Local information
573         centerPosition                    = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
574         Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
575         Matrix  intermediateLocalMatrix;
576         intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
577
578         // Compute intermediate world information
579         Matrix intermediateWorldMatrix;
580         MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
581
582         Vector3    intermediateWorldPosition, intermediateWorldScale;
583         Quaternion intermediateWorldOrientation;
584         intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
585
586         // Compute final world information
587         Vector3    finalWorldPosition    = intermediateWorldPosition;
588         Vector3    finalWorldScale       = intermediateWorldScale;
589         Quaternion finalWorldOrientation = intermediateWorldOrientation;
590         // worldScale includes the influence of local scale, local rotation, and parent scale.
591         // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
592         // If not, use local scale for the final world matrix.
593         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
594         {
595           finalWorldScale = localScale;
596         }
597
598         // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
599         // If not, use local orientation for the final world matrix.
600         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
601         {
602           finalWorldOrientation = localOrientation;
603         }
604
605         // The final world position of this node is computed as a sum of
606         // parent origin position in world space and relative position of center from parent origin.
607         // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
608         Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
609         finalWorldPosition          = actorPosition * finalWorldScale;
610         finalWorldPosition *= finalWorldOrientation;
611         finalWorldPosition += localCenterPosition;
612         if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
613         {
614           Vector4 parentOriginPosition((parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize);
615           parentOriginPosition.w = 1.0f;
616           finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
617         }
618
619         worldMatrix.SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
620       }
621     }
622     else
623     {
624       localPosition = actorPosition + centerPosition;
625       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
626     }
627   }
628
629   return worldMatrix;
630 }
631
632 Vector4 CalculateActorWorldColor(const Actor& actor)
633 {
634   std::vector<Dali::Actor>     descentList;
635   std::vector<Dali::ColorMode> inheritanceModeList;
636   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
637   Dali::ColorMode              inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
638   do
639   {
640     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
641     inheritanceModeList.push_back(inheritance);
642     descentList.push_back(currentActor);
643     currentActor = currentActor.GetParent();
644   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
645
646   Vector4      worldColor;
647   const size_t descentCount = descentList.size();
648   for(size_t iter = 0u; iter < descentCount; ++iter)
649   {
650     auto i = descentCount - iter - 1u;
651     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
652     {
653       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
654     }
655     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
656     {
657       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
658       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
659     }
660     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
661     {
662       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
663       worldColor *= ownColor;
664     }
665   }
666
667   return worldColor;
668 }
669
670 Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
671 {
672   Vector3 currentWorldPosition = CalculateActorWorldTransform(actor).GetTranslation3();
673
674   Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
675   Quaternion worldToLocal  = GetOrientationFromForwardAndUpVector(localForward, localUp);
676
677   // Rotate by this order : Local --> World --> Target
678   Quaternion ret = worldToTarget / worldToLocal;
679
680   // If we inherit orientation, get parent's world orientation, and revert it.
681   if(actor.IsOrientationInherited() && actor.GetParent())
682   {
683     // Get Parent information.
684     Vector3       parentPosition, parentScale;
685     Quaternion    parentOrientation;
686     const Matrix& parentMatrix = CalculateActorWorldTransform(*actor.GetParent());
687     parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
688
689     ret = ret / parentOrientation;
690   }
691
692   return ret;
693 }
694
695 } // namespace Dali::Internal