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