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 // Common API for calculating screen position
102 * @brief Retrieve actor's world position by Event related properties after calculating the world transform matrix.
104 * @param[in] actor The actor that wants to get WorldPosition
105 * @param[out] worldTransformMatrix Calculated world matrix as output. We can reuse this value in other logics.
106 * @return Calculated world position
108 Vector3 RetrieveCalculatedWorldPosition(const Actor& actor, Matrix& worldTransformMatrix)
110 worldTransformMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
112 Scene& scene = actor.GetScene();
114 Vector3 worldPosition = worldTransformMatrix.GetTranslation3();
115 Vector3 cameraPosition = Dali::Internal::CalculateActorWorldTransform(scene.GetDefaultCameraActor()).GetTranslation3();
116 worldPosition -= cameraPosition;
118 return worldPosition;
122 * @brief Calculate actor's current world position by Update related properties.
124 * @param[in] actor The actor that wants to get WorldPosition
125 * @param[in] bufferIndex Buffer index of update
126 * @return Calculated world position
128 Vector3 CalculateCurrentWorldPosition(const Actor& actor, BufferIndex bufferIndex)
130 Scene& scene = actor.GetScene();
132 Vector3 worldPosition = actor.GetNode().GetWorldPosition(bufferIndex);
133 Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
134 worldPosition -= cameraPosition;
136 return worldPosition;
140 * @brief Calculate actor's scaled size by world scale.
142 * @param[in] actor The actor that wants to get scaled size
143 * @param[in] worldTransformMatrix The actor's world matrix
144 * @return The size scaled by world scale
146 Vector3 CalculateScaledActorSize(const Actor& actor, const Matrix& worldTransformMatrix)
148 return actor.GetTargetSize() * worldTransformMatrix.GetScale();
152 * @brief Calculate actor's current scaled size by world scale.
154 * @param[in] actor The actor that wants to get scaled size
155 * @param[in] bufferIndex Buffer index of update
156 * @return The size scaled by world scale
158 Vector3 CalculateCurrentScaledActorSize(const Actor& actor, BufferIndex bufferIndex)
160 auto& node = actor.GetNode();
161 return node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
165 * @brief Calculate screen extents top-left point position
167 * @param[in] sceneSize The scene size
168 * @param[in] actorSize The actor size
169 * @param[in] worldPosition The actor's world position
170 * @return The size scaled by world scale
172 template<typename SceneSizeType, typename ActorSizeType, typename WorldPositionType>
173 Vector2 CalculateActorTopLeftScreenPosition(const SceneSizeType& sceneSize, const ActorSizeType& actorSize, const WorldPositionType& worldPosition)
175 const Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f);
176 const Vector2 halfActorSize(actorSize.width * 0.5f, actorSize.height * 0.5f);
178 return Vector2(halfSceneSize.width - halfActorSize.width + worldPosition.x, halfSceneSize.height - halfActorSize.height + worldPosition.y);
182 bool ConvertScreenToLocal(
183 const Matrix& viewMatrix,
184 const Matrix& projectionMatrix,
185 const Matrix& worldMatrix,
186 const Vector3& currentSize,
187 const Viewport& viewport,
193 // Get the ModelView matrix
195 MatrixUtils::MultiplyTransformMatrix(modelView, worldMatrix, viewMatrix);
197 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
198 Matrix invertedMvp(false /*don't init*/);
199 MatrixUtils::MultiplyProjectionMatrix(invertedMvp, modelView, projectionMatrix);
200 bool success = invertedMvp.Invert();
202 // Convert to GL coordinates
203 Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
208 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
215 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
221 if(XyPlaneIntersect(nearPos, farPos, local))
223 Vector3 size = currentSize;
224 localX = local.x + size.x * 0.5f;
225 localY = local.y + size.y * 0.5f;
236 bool ConvertScreenToLocalRenderTask(
237 const RenderTask& renderTask,
238 const Matrix& worldMatrix,
239 const Vector3& currentSize,
245 bool success = false;
246 CameraActor* camera = renderTask.GetCameraActor();
250 renderTask.GetViewport(viewport);
252 // need to translate coordinates to render tasks coordinate space
253 Vector2 converted(screenX, screenY);
254 if(renderTask.TranslateCoordinates(converted))
256 success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
262 bool ConvertScreenToLocalRenderTaskList(
263 const RenderTaskList& renderTaskList,
264 const Matrix& worldMatrix,
265 const Vector3& currentSize,
271 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
272 uint32_t taskCount = renderTaskList.GetTaskCount();
273 for(uint32_t i = taskCount; i > 0; --i)
275 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
276 if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
278 // found a task where this conversion was ok so return
285 const Vector2 CalculateActorScreenPosition(const Actor& actor)
290 Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
292 Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
293 Vector3 actorSize = CalculateScaledActorSize(actor, worldTransformMatrix);
295 auto sceneSize = actor.GetScene().GetSize();
297 Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
298 Vector2 anchorPointOffSet = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
300 result = screenPositionTopLeft + anchorPointOffSet;
305 const Vector2 CalculateCurrentActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
310 Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
311 Vector3 actorSize = CalculateCurrentScaledActorSize(actor, bufferIndex);
313 auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
315 Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
316 Vector2 anchorPointOffSet = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
318 result = screenPositionTopLeft + anchorPointOffSet;
323 Rect<> CalculateActorScreenExtents(const Actor& actor)
329 Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
331 Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
332 Vector3 actorSize = CalculateScaledActorSize(actor, worldTransformMatrix);
334 auto sceneSize = actor.GetScene().GetSize();
336 position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
337 size2 = Vector2(actorSize.width, actorSize.height);
339 return {position2.x, position2.y, size2.x, size2.y};
342 Rect<> CalculateCurrentActorScreenExtents(const Actor& actor, BufferIndex bufferIndex)
348 Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
349 Vector3 actorSize = CalculateCurrentScaledActorSize(actor, bufferIndex);
351 auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
353 position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
354 size2 = Vector2(actorSize.width, actorSize.height);
356 return {position2.x, position2.y, size2.x, size2.y};
359 bool ConvertLocalToScreen(
360 const Matrix& viewMatrix,
361 const Matrix& projectionMatrix,
362 const Matrix& worldMatrix,
363 const Rect<>& viewportExtent,
364 const Vector3& localPosition,
368 bool success = false;
370 // Convert local to projection coordinates
371 // note, P*(V*(M*pos))) is faster than (P*V*M)*pos
372 Vector4 mvpPos(localPosition.x, localPosition.y, localPosition.z, 1.0f);
374 mvpPos = worldMatrix * mvpPos;
375 mvpPos = viewMatrix * mvpPos;
376 mvpPos = projectionMatrix * mvpPos;
378 if(DALI_LIKELY(!EqualsZero(mvpPos.w)))
381 screenX = viewportExtent.x + (mvpPos.x + mvpPos.w) * viewportExtent.width * 0.5f / mvpPos.w;
382 screenY = viewportExtent.y + (-mvpPos.y + mvpPos.w) * viewportExtent.height * 0.5f / mvpPos.w;
387 bool ConvertLocalToScreenRenderTask(
388 const RenderTask& renderTask,
390 const Matrix& worldMatrix,
391 const Vector3& localPosition,
395 bool success = false;
396 const Actor* sourceActor = renderTask.GetSourceActor();
397 if(sourceActor == nullptr)
402 // Check whether current actor is in this rendertask.
403 bool actorInRendertask = false;
404 const Actor* targetActor = &actor;
407 if(sourceActor == targetActor)
409 actorInRendertask = true;
412 targetActor = targetActor->GetParent();
414 if(!actorInRendertask)
419 CameraActor* camera = renderTask.GetCameraActor();
422 Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
423 if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
428 if(ConvertLocalToScreen(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, viewportExtent, localPosition, screenX, screenY))
436 bool ConvertLocalToScreenRenderTaskList(
437 const RenderTaskList& renderTaskList,
439 const Matrix& worldMatrix,
440 const Vector3& localPosition,
444 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
445 uint32_t taskCount = renderTaskList.GetTaskCount();
446 for(uint32_t i = taskCount; i > 0; --i)
448 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
449 if(ConvertLocalToScreenRenderTask(*task, actor, worldMatrix, localPosition, screenX, screenY))
451 // found a task where this conversion was ok so return
458 const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor)
463 auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
464 const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
466 ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize() * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
471 const Vector2 CalculateCurrentActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
476 const auto& node = actor.GetNode();
477 const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
478 const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
480 ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex) * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
485 bool ConvertLocalToScreenExtentRenderTask(
486 const RenderTask& renderTask,
488 const Matrix& worldMatrix,
489 const Vector3& currentSize,
490 Rect<>& screenExtent)
492 bool success = false;
493 const Actor* sourceActor = renderTask.GetSourceActor();
494 if(sourceActor == nullptr)
499 // Check whether current actor is in this rendertask.
500 bool actorInRendertask = false;
501 const Actor* targetActor = &actor;
504 if(sourceActor == targetActor)
506 actorInRendertask = true;
509 targetActor = targetActor->GetParent();
511 if(!actorInRendertask)
516 CameraActor* camera = renderTask.GetCameraActor();
519 Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
520 if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
525 constexpr uint32_t BOX_POINT_COUNT = 8;
526 const Vector3 BBOffset[BOX_POINT_COUNT] = {
527 Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
528 Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
529 Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
530 Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
531 Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
532 Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
533 Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
534 Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
537 float minScreenX = 0.0f;
538 float minScreenY = 0.0f;
539 float maxScreenX = 0.0f;
540 float maxScreenY = 0.0f;
542 const auto& viewMatrix = camera->GetViewMatrix();
543 const auto& projectionMatrix = camera->GetProjectionMatrix();
545 success = ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, BBOffset[0], minScreenX, minScreenY);
548 maxScreenX = minScreenX;
549 maxScreenY = minScreenY;
550 for(uint32_t i = 1; i < BOX_POINT_COUNT; ++i)
552 float screenX = 0.0f;
553 float screenY = 0.0f;
554 Vector3 localPosition = BBOffset[i];
555 if(DALI_UNLIKELY(!ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, localPosition, screenX, screenY)))
560 minScreenX = std::min(minScreenX, screenX);
561 maxScreenX = std::max(maxScreenX, screenX);
562 minScreenY = std::min(minScreenY, screenY);
563 maxScreenY = std::max(maxScreenY, screenY);
567 screenExtent.x = minScreenX;
568 screenExtent.y = minScreenY;
569 screenExtent.width = maxScreenX - minScreenX;
570 screenExtent.height = maxScreenY - minScreenY;
577 bool ConvertLocalToScreenExtentRenderTaskList(
578 const RenderTaskList& renderTaskList,
580 const Matrix& worldMatrix,
581 const Vector3& currentSize,
582 Rect<>& screenExtent)
584 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
585 uint32_t taskCount = renderTaskList.GetTaskCount();
586 for(uint32_t i = taskCount; i > 0; --i)
588 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
589 if(ConvertLocalToScreenExtentRenderTask(*task, actor, worldMatrix, currentSize, screenExtent))
591 // found a task where this conversion was ok so return
598 Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor)
600 Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
604 Scene& scene = actor.GetScene();
606 auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
607 const auto& renderTaskList = scene.GetRenderTaskList();
608 ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize(), result);
613 Rect<> CalculateCurrentActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
615 Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
619 const auto& node = actor.GetNode();
620 const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
621 const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
623 ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result);
629 * @brief Computes and center position by using transform properties.
630 * @param[in] anchorPoint anchorPoint of an actor.
631 * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
632 * @param[in] size size of an actor.
633 * @param[in] scale scale of an actor.
634 * @param[in] orientation orientation of an actor.
636 Vector3 CalculateCenterPosition(
637 const Vector3& anchorPoint,
638 const bool positionUsesAnchorPoint,
640 const Vector3& scale,
641 const Quaternion& orientation)
643 Vector3 centerPosition;
644 const Vector3 half(0.5f, 0.5f, 0.5f);
645 const Vector3 topLeft(0.0f, 0.0f, 0.5f);
646 // Calculate the center-point by applying the scale and rotation on the anchor point.
647 centerPosition = (half - anchorPoint) * size * scale;
648 centerPosition *= orientation;
650 // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
651 if(!positionUsesAnchorPoint)
653 centerPosition -= (topLeft - anchorPoint) * size;
655 return centerPosition;
658 Matrix CalculateActorWorldTransform(const Actor& actor)
662 DONT_INHERIT_TRANSFORM = 0,
663 INHERIT_POSITION = 1,
665 INHERIT_ORIENTATION = 4,
666 INHERIT_ALL = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
669 std::vector<Dali::Actor> descentList;
670 std::vector<InheritanceMode> inheritanceModeList;
671 Dali::Actor currentActor(const_cast<Actor*>(&actor));
675 inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
676 (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
677 static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
678 inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
679 descentList.push_back(currentActor);
680 currentActor = currentActor.GetParent();
681 } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
684 Vector3 localPosition;
686 // descentList is leaf first, so traverse from root (end) to leaf (beginning)
687 const size_t descentCount = descentList.size();
688 for(size_t iter = 0u; iter < descentCount; ++iter)
690 auto i = descentCount - iter - 1u;
691 Vector3 anchorPoint = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
692 Vector3 parentOrigin = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
693 bool positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
694 Vector3 size = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
695 Vector3 actorPosition = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
696 Quaternion localOrientation = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
697 Vector3 localScale = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
699 Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
700 if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
703 Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
704 if(inheritanceModeList[i] == INHERIT_ALL)
706 localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
707 localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
709 //Update the world matrix
711 MatrixUtils::MultiplyTransformMatrix(tempMatrix, localMatrix, worldMatrix);
712 worldMatrix = tempMatrix;
716 // Get Parent information.
717 Vector3 parentPosition, parentScale;
718 Quaternion parentOrientation;
719 const Matrix& parentMatrix = worldMatrix;
720 parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
722 // Compute intermediate Local information
723 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
724 Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
725 Matrix intermediateLocalMatrix;
726 intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
728 // Compute intermediate world information
729 Matrix intermediateWorldMatrix;
730 MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
732 Vector3 intermediateWorldPosition, intermediateWorldScale;
733 Quaternion intermediateWorldOrientation;
734 intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
736 // Compute final world information
737 Vector3 finalWorldPosition = intermediateWorldPosition;
738 Vector3 finalWorldScale = intermediateWorldScale;
739 Quaternion finalWorldOrientation = intermediateWorldOrientation;
740 // worldScale includes the influence of local scale, local rotation, and parent scale.
741 // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
742 // If not, use local scale for the final world matrix.
743 if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
745 finalWorldScale = localScale;
748 // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
749 // If not, use local orientation for the final world matrix.
750 if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
752 finalWorldOrientation = localOrientation;
755 // The final world position of this node is computed as a sum of
756 // parent origin position in world space and relative position of center from parent origin.
757 // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
758 Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
759 finalWorldPosition = actorPosition * finalWorldScale;
760 finalWorldPosition *= finalWorldOrientation;
761 finalWorldPosition += localCenterPosition;
762 if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
764 Vector4 parentOriginPosition((parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize);
765 parentOriginPosition.w = 1.0f;
766 finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
769 worldMatrix.SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
774 localPosition = actorPosition + centerPosition;
775 worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
782 Vector4 CalculateActorWorldColor(const Actor& actor)
784 std::vector<Dali::Actor> descentList;
785 std::vector<Dali::ColorMode> inheritanceModeList;
786 Dali::Actor currentActor(const_cast<Actor*>(&actor));
787 Dali::ColorMode inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
790 inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
791 inheritanceModeList.push_back(inheritance);
792 descentList.push_back(currentActor);
793 currentActor = currentActor.GetParent();
794 } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
797 const size_t descentCount = descentList.size();
798 for(size_t iter = 0u; iter < descentCount; ++iter)
800 auto i = descentCount - iter - 1u;
801 if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
803 worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
805 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
807 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
808 worldColor = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
810 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
812 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
813 worldColor *= ownColor;
820 Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
822 Vector3 currentWorldPosition = Dali::Internal::CalculateActorWorldTransform(actor).GetTranslation3();
824 Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
825 Quaternion worldToLocal = GetOrientationFromForwardAndUpVector(localForward, localUp);
827 // Rotate by this order : Local --> World --> Target
828 Quaternion ret = worldToTarget / worldToLocal;
830 // If we inherit orientation, get parent's world orientation, and revert it.
831 if(actor.IsOrientationInherited() && actor.GetParent())
833 // Get Parent information.
834 Vector3 parentPosition, parentScale;
835 Quaternion parentOrientation;
836 const Matrix& parentMatrix = Dali::Internal::CalculateActorWorldTransform(*actor.GetParent());
837 parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
839 ret = ret / parentOrientation;
845 } // namespace Dali::Internal