Fix hit-test bug when overlay2D child is not overlayed 58/272958/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 28 Mar 2022 10:44:34 +0000 (19:44 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Mon, 28 Mar 2022 11:48:03 +0000 (20:48 +0900)
Let's image some case like below scene tree.
root --- A (overlay2D)  --- A1 (normal)
      |- B (normal)

When A1 and B is overlaped, B will be drawn under the A1. (Because A is overlay)
But, in hit-test-algorithm, overlay2D information doesn't propagated.

This patch make hit-test can propagate overlay2D property,
so the hit test result return reasonable as what we can see.

Change-Id: I123d3bbc2c6ba27df3f10829ebaf16b80eb0f987
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp
dali/internal/event/events/hit-test-algorithm-impl.cpp

index 1bac5af..2229015 100644 (file)
@@ -379,6 +379,77 @@ int UtcDaliHitTestAlgorithmOverlay(void)
   HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
   DALI_TEST_CHECK(results.actor == green);
   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
+
+  // Create new actor child as blue. It will be shown over the blue, and green.
+  Actor red = Actor::New();
+  red.SetProperty(Actor::Property::NAME, "Red");
+  red.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  red.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  red.SetProperty(Actor::Property::POSITION, Vector2(actorSize.x * 5.0f / 6.0f, -actorSize.y * 1.0f / 6.0f));
+  red.SetProperty(Actor::Property::SIZE, actorSize);
+
+  blue.Add(red);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+  application.Render(10);
+
+  //Hit in the intersection red, green, blue. Should pick the red actor since it is an child of overlay.
+  HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == red);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 11.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection red, blue. Should pick the red actor since it is an child of blue.
+  HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 9.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == red);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 9.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection red, green. Should pick the red actor since it is an child of overlay.
+  HitTest(stage, Vector2(stageSize.x * 15.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == red);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 3.0f / 12.0f, actorSize.y * 11.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection blue, green. Should pick the blue actor since it is an overlay.
+  HitTest(stage, Vector2(stageSize.x * 11.0f / 24.0f, stageSize.y * 13.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == blue);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 9.0f / 12.0f, actorSize.y * 11.0f / 12.0f), TEST_LOCATION);
+
+  // Change blue's draw mode as normal. now blue < red < green
+  blue.SetProperty(Actor::Property::DRAW_MODE, DrawMode::NORMAL);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+  application.Render(10);
+
+  //Hit in the intersection red, green, blue. Should pick the green actor since it is latest ordered actor.
+  HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == green);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 3.0f / 12.0f, actorSize.y * 1.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection red, blue. Should pick the red actor since it is an child of blue.
+  HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 9.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == red);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 9.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection red, green. Should pick the green actor since it is latest ordered actor.
+  HitTest(stage, Vector2(stageSize.x * 15.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == green);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 5.0f / 12.0f, actorSize.y * 1.0f / 12.0f), TEST_LOCATION);
+
+  //Hit in the intersection blue, green. Should pick the green actor since it is latest ordered actor.
+  HitTest(stage, Vector2(stageSize.x * 11.0f / 24.0f, stageSize.y * 13.0f / 24.0f), results, &DefaultIsActorTouchableFunction);
+  tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+  DALI_TEST_CHECK(results.actor == green);
+  DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 3.0f / 12.0f), TEST_LOCATION);
   END_TEST;
 }
 
index 5330fe3..045b390 100644 (file)
@@ -161,9 +161,10 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
                             const RenderTaskList::ExclusivesContainer& exclusives,
                             const Vector4&                             rayOrigin,
                             const Vector4&                             rayDir,
-                            float&                                     nearClippingPlane,
-                            float&                                     farClippingPlane,
+                            const float&                               nearClippingPlane,
+                            const float&                               farClippingPlane,
                             HitTestInterface&                          hitCheck,
+                            const bool&                                overlayed,
                             bool&                                      overlayHit,
                             bool                                       layerIs3d,
                             uint32_t                                   clippingDepth,
@@ -185,6 +186,7 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
   // all clipping actors also for them to be counted as hit.
   uint32_t newClippingDepth = clippingDepth;
   bool     clippingActor    = actor.GetClippingMode() != ClippingMode::DISABLED;
+  bool     overlayedActor   = overlayed || actor.IsOverlay();
   if(clippingActor)
   {
     ++newClippingDepth;
@@ -220,13 +222,13 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
             clippingBitPlaneMask |= 1u << clippingDepth;
           }
 
-          if(overlayHit && !actor.IsOverlay())
+          if(overlayHit && !overlayedActor)
           {
             // If we have already hit an overlay and current actor is not an overlay ignore current actor.
           }
           else
           {
-            if(actor.IsOverlay())
+            if(overlayedActor)
             {
               overlayHit = true;
             }
@@ -318,6 +320,7 @@ HitActor HitTestWithinLayer(Actor&                                     actor,
                                                nearClippingPlane,
                                                farClippingPlane,
                                                hitCheck,
+                                               overlayedActor,
                                                overlayHit,
                                                layerIs3d,
                                                newClippingDepth,
@@ -507,6 +510,7 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives,
                                        farClippingPlane,
                                        hitCheck,
                                        overlayHit,
+                                       overlayHit,
                                        layer->GetBehavior() == Dali::Layer::LAYER_3D,
                                        0u,
                                        0u,
@@ -526,6 +530,7 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives,
                                        farClippingPlane,
                                        hitCheck,
                                        overlayHit,
+                                       overlayHit,
                                        layer->GetBehavior() == Dali::Layer::LAYER_3D,
                                        0u,
                                        0u,