Moved event side actor world calculation 66/281866/1
authorDavid Steele <david.steele@samsung.com>
Thu, 22 Sep 2022 15:10:47 +0000 (16:10 +0100)
committerDavid Steele <david.steele@samsung.com>
Thu, 22 Sep 2022 15:10:47 +0000 (16:10 +0100)
Transition effects used event side calculation of world
transform and color. These are more useful in devel core
than internally in toolkit.

Change-Id: I1a86cee588e3c7beecf5ba1665b1464c5e54939f
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/utc-Dali-Actor.cpp
dali/devel-api/actors/actor-devel.cpp
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-coords.cpp
dali/internal/event/actors/actor-coords.h

index 33fcdd9..33d9536 100644 (file)
@@ -10630,3 +10630,489 @@ int UtcDaliActorAllowOnlyOwnTouchPropertyN(void)
   }
   END_TEST;
 }
+
+int UtcDaliActorCalculateWorldTransform01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor position inheritance produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]   = Vector3(0.0f, 0.0f, 0.0f);
+  branchActor[Actor::Property::POSITION] = Vector3(100.0f, 100.0f, 0.0f);
+  leafActor[Actor::Property::POSITION]   = Vector3(100.0f, 50.0f, 30.0f);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::PARENT_ORIGIN]   = ParentOrigin::TOP_LEFT;
+  branchActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::TOP_LEFT;
+  leafActor[Actor::Property::PARENT_ORIGIN]   = ParentOrigin::TOP_LEFT;
+
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  Vector3    worldPos;
+  Vector3    worldScale;
+  Quaternion worldRotation;
+  m.GetTransformComponents(worldPos, worldRotation, worldScale);
+  DALI_TEST_EQUALS(worldPos, Vector3(200.0f, 150.0f, 30.0f), 0.0001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor position produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]   = Vector3(0.0f, 0.0f, 0.0f);
+  branchActor[Actor::Property::POSITION] = Vector3(100.0f, 100.0f, 0.0f);
+  leafActor[Actor::Property::POSITION]   = Vector3(100.0f, 50.0f, 30.0f);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  leafActor[Actor::Property::INHERIT_POSITION]    = false;
+  leafActor[Actor::Property::INHERIT_ORIENTATION] = false;
+  leafActor[Actor::Property::INHERIT_SCALE]       = false;
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor position produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]   = Vector3(0.0f, 0.0f, 0.0f);
+  branchActor[Actor::Property::POSITION] = Vector3(100.0f, 100.0f, 0.0f);
+  leafActor[Actor::Property::POSITION]   = Vector3(100.0f, 50.0f, 30.0f);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  leafActor[Actor::Property::INHERIT_POSITION]    = true;
+  leafActor[Actor::Property::INHERIT_ORIENTATION] = false;
+  leafActor[Actor::Property::INHERIT_SCALE]       = false;
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor inheritance scale/orientation produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::CENTER;
+  rootActor[Actor::Property::PARENT_ORIGIN]  = ParentOrigin::CENTER;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  branchActor[Actor::Property::POSITION] = Vector3(100.0f, 100.0f, 0.0f);
+  leafActor[Actor::Property::POSITION]   = Vector3(100.0f, 50.0f, 30.0f);
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor inheritance of scale produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::CENTER;
+  rootActor[Actor::Property::PARENT_ORIGIN]  = ParentOrigin::CENTER;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  branchActor[Actor::Property::POSITION] = Vector3(100.0f, 100.0f, 0.0f);
+  leafActor[Actor::Property::POSITION]   = Vector3(100.0f, 50.0f, 30.0f);
+
+  leafActor[Actor::Property::INHERIT_POSITION]    = false;
+  leafActor[Actor::Property::INHERIT_ORIENTATION] = false;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor inheritance of scale produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::CENTER;
+  rootActor[Actor::Property::PARENT_ORIGIN]  = ParentOrigin::CENTER;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  leafActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::TOP_LEFT;
+
+  branchActor[Actor::Property::POSITION]    = Vector3(100.0f, 30.0f, -50.0f);
+  branchActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(45.0f), Vector3::XAXIS);
+  leafActor[Actor::Property::POSITION]      = Vector3(100.0f, 50.0f, 30.0f);
+
+  leafActor[Actor::Property::INHERIT_POSITION] = false;
+  leafActor[Actor::Property::INHERIT_SCALE]    = false;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldTransform07(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor inheritance of scale produces right transform matrix");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  // Set anchor point to the same value as parent origin
+  rootActor[Actor::Property::ANCHOR_POINT]   = AnchorPoint::CENTER;
+  rootActor[Actor::Property::PARENT_ORIGIN]  = ParentOrigin::CENTER;
+  branchActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+
+  // This should be ignored.
+  leafActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+  leafActor[Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
+
+  branchActor[Actor::Property::POSITION]    = Vector3(100.0f, 30.0f, -50.0f);
+  branchActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(45.0f), Vector3::XAXIS);
+  leafActor[Actor::Property::POSITION]      = Vector3(100.0f, 50.0f, 30.0f);
+
+  leafActor[Actor::Property::INHERIT_POSITION]           = false;
+  leafActor[Actor::Property::INHERIT_SCALE]              = false;
+  leafActor[Actor::Property::POSITION_USES_ANCHOR_POINT] = false;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  application.Render(0);
+
+  Matrix m = DevelActor::GetWorldTransform(leafActor);
+
+  Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+  DALI_TEST_EQUALS(m, actualMatrix, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldColor01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor inheritance of color produces right final color");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  rootActor[Actor::Property::COLOR]   = Color::WHITE;
+  branchActor[Actor::Property::COLOR] = Vector4(1.0f, 1.0f, 0.5f, 0.8f);
+  leafActor[Actor::Property::COLOR]   = Vector4(0.1f, 0.5f, 0.5f, 0.8f);
+
+  // Default is to inherit:
+  leafActor[Actor::Property::COLOR_MODE] = ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 color = DevelActor::GetWorldColor(leafActor);
+
+  Vector4 actualColor = leafActor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR);
+  DALI_TEST_EQUALS(color, actualColor, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldColor02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor uses own color");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  rootActor[Actor::Property::COLOR]   = Color::WHITE;
+  branchActor[Actor::Property::COLOR] = Vector4(1.0f, 1.0f, 0.5f, 0.8f);
+  leafActor[Actor::Property::COLOR]   = Vector4(0.1f, 0.5f, 0.5f, 0.8f);
+
+  leafActor[Actor::Property::COLOR_MODE] = ColorMode::USE_OWN_COLOR;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 color = DevelActor::GetWorldColor(leafActor);
+
+  Vector4 actualColor = leafActor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR);
+  DALI_TEST_EQUALS(color, actualColor, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(color, Vector4(0.1f, 0.5f, 0.5f, 0.8f), 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldColor03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor uses parent color");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  rootActor[Actor::Property::COLOR]   = Color::WHITE * 0.9f;
+  branchActor[Actor::Property::COLOR] = Vector4(1.0f, 1.0f, 0.5f, 0.8f);
+  leafActor[Actor::Property::COLOR]   = Vector4(0.1f, 0.5f, 0.5f, 0.8f);
+
+  leafActor[Actor::Property::COLOR_MODE] = ColorMode::USE_PARENT_COLOR;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 color = DevelActor::GetWorldColor(leafActor);
+
+  Vector4 actualColor = leafActor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR);
+  DALI_TEST_EQUALS(color, actualColor, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(color, Vector4(1.0f, 1.0f, 0.5f, 0.72f), 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorCalculateWorldColor04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actor blends with parent color");
+
+  Actor rootActor   = Actor::New();
+  Actor branchActor = Actor::New();
+  Actor leafActor   = Actor::New();
+
+  rootActor[Actor::Property::POSITION]    = Vector3(100.0f, 0.0f, 0.0f);
+  rootActor[Actor::Property::SCALE]       = Vector3(2.0f, 2.0f, 2.0f);
+  rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+
+  rootActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  branchActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+  leafActor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+
+  rootActor[Actor::Property::COLOR]   = Color::WHITE * 0.9f;
+  branchActor[Actor::Property::COLOR] = Vector4(1.0f, 1.0f, 0.5f, 0.8f);
+  leafActor[Actor::Property::COLOR]   = Vector4(0.1f, 0.5f, 0.5f, 0.8f);
+
+  leafActor[Actor::Property::COLOR_MODE] = ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR;
+
+  application.GetScene().Add(rootActor);
+  rootActor.Add(branchActor);
+  branchActor.Add(leafActor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 color = DevelActor::GetWorldColor(leafActor);
+
+  Vector4 actualColor = leafActor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR);
+  DALI_TEST_EQUALS(color, actualColor, 0.001f, TEST_LOCATION);
+
+  END_TEST;
+}
index 37fa3fb..fc54e89 100644 (file)
@@ -17,6 +17,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/internal/event/actors/actor-coords.h>
 #include <dali/internal/event/actors/actor-impl.h>
 
 namespace Dali
@@ -68,6 +69,16 @@ Actor::TouchEventSignalType& HitTestResultSignal(Actor actor)
   return GetImplementation(actor).HitTestResultSignal();
 }
 
+Matrix GetWorldTransform(Actor actor)
+{
+  return CalculateActorWorldTransform(GetImplementation(actor));
+}
+
+Vector4 GetWorldColor(Actor actor)
+{
+  return CalculateActorWorldColor(GetImplementation(actor));
+}
+
 } // namespace DevelActor
 
 } // namespace Dali
index 80b52dc..7b985a0 100644 (file)
@@ -389,6 +389,30 @@ DALI_CORE_API void SwitchParent(Actor actor, Actor newParent);
  */
 DALI_CORE_API Actor::TouchEventSignalType& HitTestResultSignal(Actor actor);
 
+/**
+ * Get the world transform of the actor.
+ *
+ * This calculates the world transform from scratch using only event
+ * side properties - it does not rely on the update thread to have
+ * already calculated the transform.
+ *
+ * @param[in] actor The actor for which to calculate the world transform
+ * @return The world transform matrix
+ */
+DALI_CORE_API Matrix GetWorldTransform(Actor actor);
+
+/**
+ * Get the world color of the actor.
+ *
+ * This calcualtes the world color of the actor from scratch using
+ * only event side properties. It does not rely on the update thread
+ * to have already calculated the color.
+ *
+ * @param[in] actor The actor to calculate the world color for
+ * @return the world color
+ */
+DALI_CORE_API Vector4 GetWorldColor(Actor actor);
+
 } // namespace DevelActor
 
 } // namespace Dali
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
index d6ebd36..1c7d092 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_EVENT_ACTORS_ACTOR_COORDS_H
 
 /*
- * 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.
@@ -112,6 +112,30 @@ const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex buffe
  */
 Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosition, BufferIndex bufferIndex);
 
+/**
+ * Get the world transform of the actor.
+ *
+ * This calculates the world transform from scratch using only event
+ * side properties - it does not rely on the update thread to have
+ * already calculated the transform.
+ *
+ * @param[in] actor The actor to calculate the world matrix for
+ * @return The world transform matrix
+ */
+Matrix CalculateActorWorldTransform(const Actor& actor);
+
+/**
+ * Get the world color of the actor.
+ *
+ * This calcualtes the world color of the actor from scratch using
+ * only event side properties. It does not rely on the update thread
+ * to have already calculated the color.
+ *
+ * @param[in] actor The actor to calculate the world color for
+ * @return the world color
+ */
+Vector4 CalculateActorWorldColor(const Actor& actor);
+
 } // namespace Dali::Internal
 
 #endif // DALI_INTERNAL_EVENT_ACTORS_ACTOR_COORDS_H