2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
24 namespace Dali::Internal
29 * @brief Get the Viewport Extents from RenderTask
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
35 bool GetViewportExtentsFromRenderTask(const RenderTask& renderTask, Rect<float>& viewportExtent)
37 if(renderTask.GetFrameBuffer())
39 Dali::Actor mappingActor = renderTask.GetScreenToFrameBufferMappingActor();
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;
60 renderTask.GetViewport(viewport);
61 viewportExtent.x = viewport.x;
62 viewportExtent.y = viewport.y;
63 viewportExtent.width = viewport.width;
64 viewportExtent.height = viewport.height;
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
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.
78 Quaternion GetOrientationFromForwardAndUpVector(Vector3 forward, Vector3 up)
83 Vector3 vX = up.Cross(vZ);
86 // If something invalid input comes, vX length become zero.
87 if(DALI_UNLIKELY(Dali::EqualsZero(vX.Length())))
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);
93 Vector3 vY = vZ.Cross(vX);
96 return Quaternion(vX, vY, vZ);
99 bool ConvertScreenToLocal(
100 const Matrix& viewMatrix,
101 const Matrix& projectionMatrix,
102 const Matrix& worldMatrix,
103 const Vector3& currentSize,
104 const Viewport& viewport,
110 // Get the ModelView matrix
112 MatrixUtils::MultiplyTransformMatrix(modelView, worldMatrix, viewMatrix);
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();
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);
125 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
132 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
138 if(XyPlaneIntersect(nearPos, farPos, local))
140 Vector3 size = currentSize;
141 localX = local.x + size.x * 0.5f;
142 localY = local.y + size.y * 0.5f;
153 bool ConvertScreenToLocalRenderTask(
154 const RenderTask& renderTask,
155 const Matrix& worldMatrix,
156 const Vector3& currentSize,
162 bool success = false;
163 CameraActor* camera = renderTask.GetCameraActor();
167 renderTask.GetViewport(viewport);
169 // need to translate coordinates to render tasks coordinate space
170 Vector2 converted(screenX, screenY);
171 if(renderTask.TranslateCoordinates(converted))
173 success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
179 bool ConvertScreenToLocalRenderTaskList(
180 const RenderTaskList& renderTaskList,
181 const Matrix& worldMatrix,
182 const Vector3& currentSize,
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)
192 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
193 if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
195 // found a task where this conversion was ok so return
202 const Vector2 CalculateActorScreenPosition(const Actor& actor)
205 Scene& scene = actor.GetScene();
208 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
209 auto worldTransformMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
211 Vector3 worldPosition = worldTransformMatrix.GetTranslation3();
212 Vector3 cameraPosition = Dali::Internal::CalculateActorWorldTransform(scene.GetDefaultCameraActor()).GetTranslation3();
213 worldPosition -= cameraPosition;
215 Vector3 actorSize = actor.GetTargetSize() * worldTransformMatrix.GetScale();
216 auto sceneSize = scene.GetSize();
217 Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
218 Vector3 halfActorSize(actorSize * 0.5f);
219 Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
221 result = Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
222 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
227 const Vector2 CalculateCurrentActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
230 Scene& scene = actor.GetScene();
233 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
234 const auto& node = actor.GetNode();
235 Vector3 worldPosition = node.GetWorldPosition(bufferIndex);
236 Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
237 worldPosition -= cameraPosition;
239 Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
240 const auto& sceneSize = scene.GetCurrentSurfaceRect(); // Use the update object's size
241 Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
242 Vector3 halfActorSize(actorSize * 0.5f);
243 Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
245 result = Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
246 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
251 Rect<> CalculateActorScreenExtents(const Actor& actor)
253 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
254 const Vector2 screenPosition = CalculateActorScreenPosition(actor);
256 auto worldTransformMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
258 Vector3 size = actor.GetTargetSize() * worldTransformMatrix.GetScale();
259 Vector3 anchorPointOffSet = size * actor.GetAnchorPointForPosition();
260 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
261 return {position.x, position.y, size.x, size.y};
264 Rect<> CalculateCurrentActorScreenExtents(const Actor& actor, BufferIndex bufferIndex)
266 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
267 const Vector2 screenPosition = CalculateCurrentActorScreenPosition(actor, bufferIndex);
269 const auto& node = actor.GetNode();
270 Vector3 size = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
271 Vector3 anchorPointOffSet = size * actor.GetAnchorPointForPosition();
272 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
273 return {position.x, position.y, size.x, size.y};
276 bool ConvertLocalToScreen(
277 const Matrix& viewMatrix,
278 const Matrix& projectionMatrix,
279 const Matrix& worldMatrix,
280 const Rect<>& viewportExtent,
281 const Vector3& localPosition,
285 bool success = false;
287 // Convert local to projection coordinates
288 // note, P*(V*(M*pos))) is faster than (P*V*M)*pos
289 Vector4 mvpPos(localPosition.x, localPosition.y, localPosition.z, 1.0f);
291 mvpPos = worldMatrix * mvpPos;
292 mvpPos = viewMatrix * mvpPos;
293 mvpPos = projectionMatrix * mvpPos;
295 if(DALI_LIKELY(!EqualsZero(mvpPos.w)))
298 screenX = viewportExtent.x + (mvpPos.x + mvpPos.w) * viewportExtent.width * 0.5f / mvpPos.w;
299 screenY = viewportExtent.y + (-mvpPos.y + mvpPos.w) * viewportExtent.height * 0.5f / mvpPos.w;
304 bool ConvertLocalToScreenRenderTask(
305 const RenderTask& renderTask,
307 const Matrix& worldMatrix,
308 const Vector3& localPosition,
312 bool success = false;
313 const Actor* sourceActor = renderTask.GetSourceActor();
314 if(sourceActor == nullptr)
319 // Check whether current actor is in this rendertask.
320 bool actorInRendertask = false;
321 const Actor* targetActor = &actor;
324 if(sourceActor == targetActor)
326 actorInRendertask = true;
329 targetActor = targetActor->GetParent();
331 if(!actorInRendertask)
336 CameraActor* camera = renderTask.GetCameraActor();
339 Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
340 if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
345 if(ConvertLocalToScreen(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, viewportExtent, localPosition, screenX, screenY))
353 bool ConvertLocalToScreenRenderTaskList(
354 const RenderTaskList& renderTaskList,
356 const Matrix& worldMatrix,
357 const Vector3& localPosition,
361 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
362 uint32_t taskCount = renderTaskList.GetTaskCount();
363 for(uint32_t i = taskCount; i > 0; --i)
365 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
366 if(ConvertLocalToScreenRenderTask(*task, actor, worldMatrix, localPosition, screenX, screenY))
368 // found a task where this conversion was ok so return
375 const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor)
380 Scene& scene = actor.GetScene();
382 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
383 auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
384 const auto& renderTaskList = scene.GetRenderTaskList();
385 ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize() * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
390 const Vector2 CalculateCurrentActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
395 // TODO : Need to find way that we don't increase duplicated code, and did the same job.
396 const auto& node = actor.GetNode();
397 Scene& scene = actor.GetScene();
399 const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
400 const auto& renderTaskList = scene.GetRenderTaskList();
401 ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex) * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
406 bool ConvertLocalToScreenExtentRenderTask(
407 const RenderTask& renderTask,
409 const Matrix& worldMatrix,
410 const Vector3& currentSize,
411 Rect<>& screenExtent)
413 bool success = false;
414 const Actor* sourceActor = renderTask.GetSourceActor();
415 if(sourceActor == nullptr)
420 // Check whether current actor is in this rendertask.
421 bool actorInRendertask = false;
422 const Actor* targetActor = &actor;
425 if(sourceActor == targetActor)
427 actorInRendertask = true;
430 targetActor = targetActor->GetParent();
432 if(!actorInRendertask)
437 CameraActor* camera = renderTask.GetCameraActor();
440 Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
441 if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
446 constexpr uint32_t BOX_POINT_COUNT = 8;
447 const Vector3 BBOffset[BOX_POINT_COUNT] = {
448 Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
449 Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
450 Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
451 Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
452 Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
453 Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
454 Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
455 Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
458 float minScreenX = 0.0f;
459 float minScreenY = 0.0f;
460 float maxScreenX = 0.0f;
461 float maxScreenY = 0.0f;
463 const auto& viewMatrix = camera->GetViewMatrix();
464 const auto& projectionMatrix = camera->GetProjectionMatrix();
466 success = ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, BBOffset[0], minScreenX, minScreenY);
469 maxScreenX = minScreenX;
470 maxScreenY = minScreenY;
471 for(uint32_t i = 1; i < BOX_POINT_COUNT; ++i)
473 float screenX = 0.0f;
474 float screenY = 0.0f;
475 Vector3 localPosition = BBOffset[i];
476 if(DALI_UNLIKELY(!ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, localPosition, screenX, screenY)))
481 minScreenX = std::min(minScreenX, screenX);
482 maxScreenX = std::max(maxScreenX, screenX);
483 minScreenY = std::min(minScreenY, screenY);
484 maxScreenY = std::max(maxScreenY, screenY);
488 screenExtent.x = minScreenX;
489 screenExtent.y = minScreenY;
490 screenExtent.width = maxScreenX - minScreenX;
491 screenExtent.height = maxScreenY - minScreenY;
498 bool ConvertLocalToScreenExtentRenderTaskList(
499 const RenderTaskList& renderTaskList,
501 const Matrix& worldMatrix,
502 const Vector3& currentSize,
503 Rect<>& screenExtent)
505 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
506 uint32_t taskCount = renderTaskList.GetTaskCount();
507 for(uint32_t i = taskCount; i > 0; --i)
509 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
510 if(ConvertLocalToScreenExtentRenderTask(*task, actor, worldMatrix, currentSize, screenExtent))
512 // found a task where this conversion was ok so return
519 Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor)
521 Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
525 Scene& scene = actor.GetScene();
527 auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
528 const auto& renderTaskList = scene.GetRenderTaskList();
529 ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize(), result);
534 Rect<> CalculateCurrentActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
536 Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
540 const auto& node = actor.GetNode();
541 Scene& scene = actor.GetScene();
543 const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
544 const auto& renderTaskList = scene.GetRenderTaskList();
545 ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result);
551 * @brief Computes and center position by using transform properties.
552 * @param[in] anchorPoint anchorPoint of an actor.
553 * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
554 * @param[in] size size of an actor.
555 * @param[in] scale scale of an actor.
556 * @param[in] orientation orientation of an actor.
558 Vector3 CalculateCenterPosition(
559 const Vector3& anchorPoint,
560 const bool positionUsesAnchorPoint,
562 const Vector3& scale,
563 const Quaternion& orientation)
565 Vector3 centerPosition;
566 const Vector3 half(0.5f, 0.5f, 0.5f);
567 const Vector3 topLeft(0.0f, 0.0f, 0.5f);
568 // Calculate the center-point by applying the scale and rotation on the anchor point.
569 centerPosition = (half - anchorPoint) * size * scale;
570 centerPosition *= orientation;
572 // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
573 if(!positionUsesAnchorPoint)
575 centerPosition -= (topLeft - anchorPoint) * size;
577 return centerPosition;
580 Matrix CalculateActorWorldTransform(const Actor& actor)
584 DONT_INHERIT_TRANSFORM = 0,
585 INHERIT_POSITION = 1,
587 INHERIT_ORIENTATION = 4,
588 INHERIT_ALL = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
591 std::vector<Dali::Actor> descentList;
592 std::vector<InheritanceMode> inheritanceModeList;
593 Dali::Actor currentActor(const_cast<Actor*>(&actor));
597 inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
598 (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
599 static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
600 inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
601 descentList.push_back(currentActor);
602 currentActor = currentActor.GetParent();
603 } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
606 Vector3 localPosition;
608 // descentList is leaf first, so traverse from root (end) to leaf (beginning)
609 const size_t descentCount = descentList.size();
610 for(size_t iter = 0u; iter < descentCount; ++iter)
612 auto i = descentCount - iter - 1u;
613 Vector3 anchorPoint = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
614 Vector3 parentOrigin = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
615 bool positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
616 Vector3 size = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
617 Vector3 actorPosition = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
618 Quaternion localOrientation = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
619 Vector3 localScale = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
621 Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
622 if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
625 Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
626 if(inheritanceModeList[i] == INHERIT_ALL)
628 localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
629 localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
631 //Update the world matrix
633 MatrixUtils::MultiplyTransformMatrix(tempMatrix, localMatrix, worldMatrix);
634 worldMatrix = tempMatrix;
638 // Get Parent information.
639 Vector3 parentPosition, parentScale;
640 Quaternion parentOrientation;
641 const Matrix& parentMatrix = worldMatrix;
642 parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
644 // Compute intermediate Local information
645 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
646 Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
647 Matrix intermediateLocalMatrix;
648 intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
650 // Compute intermediate world information
651 Matrix intermediateWorldMatrix;
652 MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
654 Vector3 intermediateWorldPosition, intermediateWorldScale;
655 Quaternion intermediateWorldOrientation;
656 intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
658 // Compute final world information
659 Vector3 finalWorldPosition = intermediateWorldPosition;
660 Vector3 finalWorldScale = intermediateWorldScale;
661 Quaternion finalWorldOrientation = intermediateWorldOrientation;
662 // worldScale includes the influence of local scale, local rotation, and parent scale.
663 // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
664 // If not, use local scale for the final world matrix.
665 if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
667 finalWorldScale = localScale;
670 // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
671 // If not, use local orientation for the final world matrix.
672 if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
674 finalWorldOrientation = localOrientation;
677 // The final world position of this node is computed as a sum of
678 // parent origin position in world space and relative position of center from parent origin.
679 // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
680 Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
681 finalWorldPosition = actorPosition * finalWorldScale;
682 finalWorldPosition *= finalWorldOrientation;
683 finalWorldPosition += localCenterPosition;
684 if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
686 Vector4 parentOriginPosition((parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize);
687 parentOriginPosition.w = 1.0f;
688 finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
691 worldMatrix.SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
696 localPosition = actorPosition + centerPosition;
697 worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
704 Vector4 CalculateActorWorldColor(const Actor& actor)
706 std::vector<Dali::Actor> descentList;
707 std::vector<Dali::ColorMode> inheritanceModeList;
708 Dali::Actor currentActor(const_cast<Actor*>(&actor));
709 Dali::ColorMode inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
712 inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
713 inheritanceModeList.push_back(inheritance);
714 descentList.push_back(currentActor);
715 currentActor = currentActor.GetParent();
716 } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
719 const size_t descentCount = descentList.size();
720 for(size_t iter = 0u; iter < descentCount; ++iter)
722 auto i = descentCount - iter - 1u;
723 if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
725 worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
727 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
729 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
730 worldColor = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
732 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
734 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
735 worldColor *= ownColor;
742 Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
744 Vector3 currentWorldPosition = Dali::Internal::CalculateActorWorldTransform(actor).GetTranslation3();
746 Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
747 Quaternion worldToLocal = GetOrientationFromForwardAndUpVector(localForward, localUp);
749 // Rotate by this order : Local --> World --> Target
750 Quaternion ret = worldToTarget / worldToLocal;
752 // If we inherit orientation, get parent's world orientation, and revert it.
753 if(actor.IsOrientationInherited() && actor.GetParent())
755 // Get Parent information.
756 Vector3 parentPosition, parentScale;
757 Quaternion parentOrientation;
758 const Matrix& parentMatrix = Dali::Internal::CalculateActorWorldTransform(*actor.GetParent());
759 parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
761 ret = ret / parentOrientation;
767 } // namespace Dali::Internal