Moved event side actor world calculation
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-coords.cpp
index 9d1010e..ce8b7a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -136,7 +136,7 @@ const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex buffe
     worldPosition -= cameraPosition;
 
     Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
-    auto    sceneSize = scene.GetCurrentSurfaceRect();  // Use the update object's size
+    auto    sceneSize = scene.GetCurrentSurfaceRect();                      // Use the update object's size
     Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
     Vector3 halfActorSize(actorSize * 0.5f);
     Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
@@ -155,4 +155,170 @@ Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosi
   return {position.x, position.y, size.x, size.y};
 }
 
+/**
+ * @brief Computes and center position by using transform properties.
+ * @param[in] anchorPoint anchorPoint of an actor.
+ * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
+ * @param[in] size size of an actor.
+ * @param[in] scale scale of an actor.
+ * @param[in] orientation orientation of an actor.
+ */
+Vector3 CalculateCenterPosition(
+  const Vector3&    anchorPoint,
+  const bool        positionUsesAnchorPoint,
+  const Vector3&    size,
+  const Vector3&    scale,
+  const Quaternion& orientation)
+{
+  Vector3       centerPosition;
+  const Vector3 half(0.5f, 0.5f, 0.5f);
+  const Vector3 topLeft(0.0f, 0.0f, 0.5f);
+  // Calculate the center-point by applying the scale and rotation on the anchor point.
+  centerPosition = (half - anchorPoint) * size * scale;
+  centerPosition *= orientation;
+
+  // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
+  if(!positionUsesAnchorPoint)
+  {
+    centerPosition -= (topLeft - anchorPoint) * size;
+  }
+  return centerPosition;
+}
+
+Matrix CalculateActorWorldTransform(const Actor& actor)
+{
+  enum InheritanceMode
+  {
+    DONT_INHERIT_TRANSFORM = 0,
+    INHERIT_POSITION       = 1,
+    INHERIT_SCALE          = 2,
+    INHERIT_ORIENTATION    = 4,
+    INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
+  };
+
+  std::vector<Dali::Actor>     descentList;
+  std::vector<InheritanceMode> inheritanceModeList;
+  Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
+  int                          inheritance = 0;
+  do
+  {
+    inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
+                  (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
+                  static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
+    inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
+    descentList.push_back(currentActor);
+    currentActor = currentActor.GetParent();
+  } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
+
+  Matrix  worldMatrix;
+  Vector3 localPosition;
+  // descentList is leaf first, so traverse from root (end) to leaf (beginning)
+  for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
+  {
+    Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
+    Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
+    bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
+    Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+    Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
+    Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
+    Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
+
+    Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
+    if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
+    {
+      Matrix  localMatrix;
+      Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+      if(inheritanceModeList[i] == INHERIT_ALL)
+      {
+        localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
+        localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
+
+        //Update the world matrix
+        Matrix tempMatrix;
+        Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+        worldMatrix = tempMatrix;
+      }
+      else
+      {
+        Vector3    parentPosition, parentScale;
+        Quaternion parentOrientation;
+        worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
+
+        if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
+        {
+          //Don't inherit scale
+          localScale /= parentScale;
+        }
+
+        if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
+        {
+          //Don't inherit orientation
+          parentOrientation.Invert();
+          localOrientation = parentOrientation * localOrientation;
+        }
+
+        if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
+        {
+          localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
+          Matrix tempMatrix;
+          Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+          worldMatrix = tempMatrix;
+          worldMatrix.SetTranslation(actorPosition + centerPosition);
+        }
+        else
+        {
+          localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
+          localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
+          Matrix tempMatrix;
+          Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+          worldMatrix = tempMatrix;
+        }
+      }
+    }
+    else
+    {
+      localPosition = actorPosition + centerPosition;
+      worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
+    }
+  }
+
+  return worldMatrix;
+}
+
+Vector4 CalculateActorWorldColor(const Actor& actor)
+{
+  std::vector<Dali::Actor>     descentList;
+  std::vector<Dali::ColorMode> inheritanceModeList;
+  Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
+  Dali::ColorMode              inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
+  do
+  {
+    inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
+    inheritanceModeList.push_back(inheritance);
+    descentList.push_back(currentActor);
+    currentActor = currentActor.GetParent();
+  } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
+
+  Vector4 worldColor;
+  for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
+  {
+    if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
+    {
+      worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
+    }
+    else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
+    {
+      Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
+      worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
+    }
+    else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
+    {
+      Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
+      worldColor *= ownColor;
+    }
+  }
+
+  return worldColor;
+}
+
 } // namespace Dali::Internal