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