Removed old context test cases
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-HitTestAlgorithm.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/events/hit-test-algorithm.h>
20 #include <dali/integration-api/events/touch-event-integ.h>
21 #include <dali/public-api/dali-core.h>
22 #include <stdlib.h>
23
24 #include <iostream>
25
26 using namespace Dali;
27
28 namespace
29 {
30 /**
31  * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
32  */
33 bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
34 {
35   bool hittable = false;
36
37   switch(type)
38   {
39     case Dali::HitTestAlgorithm::CHECK_ACTOR:
40     {
41       // Check whether the actor is visible and not fully transparent.
42       if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) && actor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR).a > 0.01f) // not FULLY_TRANSPARENT
43       {
44         // Check whether the actor has the specific name "HittableActor"
45         if(actor.GetProperty<std::string>(Actor::Property::NAME) == "HittableActor")
46         {
47           hittable = true;
48         }
49       }
50       break;
51     }
52     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
53     {
54       if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE)) // Actor is visible, if not visible then none of its children are visible.
55       {
56         hittable = true;
57       }
58       break;
59     }
60     default:
61     {
62       break;
63     }
64   }
65
66   return hittable;
67 };
68
69 bool DefaultIsActorTouchableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
70 {
71   bool hittable = false;
72
73   switch(type)
74   {
75     case Dali::HitTestAlgorithm::CHECK_ACTOR:
76     {
77       if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) &&
78          actor.GetProperty<bool>(Actor::Property::SENSITIVE) &&
79          actor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR).a > 0.01f)
80       {
81         hittable = true;
82       }
83       break;
84     }
85     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
86     {
87       if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) && // Actor is visible, if not visible then none of its children are visible.
88          actor.GetProperty<bool>(Actor::Property::SENSITIVE))        // Actor is sensitive, if insensitive none of its children should be hittable either.
89       {
90         hittable = true;
91       }
92       break;
93     }
94     default:
95     {
96       break;
97     }
98   }
99
100   return hittable;
101 };
102
103 } // anonymous namespace
104
105 // Positive test case for a method
106 int UtcDaliHitTestAlgorithmWithFunctor(void)
107 {
108   TestApplication application;
109   tet_infoline("Testing Dali::HitTestAlgorithm functor");
110
111   Stage stage = Stage::GetCurrent();
112
113   Actor actor = Actor::New();
114   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
115   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
116   actor.SetProperty(Actor::Property::NAME, "NonHittableActor");
117   stage.Add(actor);
118
119   // Render and notify
120   application.SendNotification();
121   application.Render();
122
123   Vector2 screenCoordinates(10.0f, 10.0f);
124   Vector2 localCoordinates;
125   actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
126
127   // Perform a hit-test at the given screen coordinates
128   Dali::HitTestAlgorithm::Results results;
129   Dali::HitTestAlgorithm::HitTest(stage, screenCoordinates, results, IsActorHittableFunction);
130   DALI_TEST_CHECK(results.actor != actor);
131
132   actor.SetProperty(Actor::Property::NAME, "HittableActor");
133
134   results.actor            = Actor();
135   results.actorCoordinates = Vector2::ZERO;
136
137   // Perform a hit-test at the given screen coordinates
138   Dali::HitTestAlgorithm::HitTest(stage, screenCoordinates, results, IsActorHittableFunction);
139   DALI_TEST_CHECK(results.actor == actor);
140   DALI_TEST_EQUALS(localCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION);
141   END_TEST;
142 }
143
144 int UtcDaliHitTestAlgorithmOrtho01(void)
145 {
146   TestApplication application;
147   tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()");
148
149   Stage             stage             = Stage::GetCurrent();
150   RenderTaskList    renderTaskList    = stage.GetRenderTaskList();
151   RenderTask        defaultRenderTask = renderTaskList.GetTask(0u);
152   Dali::CameraActor cameraActor       = defaultRenderTask.GetCameraActor();
153
154   Vector2 stageSize(stage.GetSize());
155   cameraActor.SetOrthographicProjection(stageSize);
156   cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
157
158   Vector2 actorSize(stageSize * 0.5f);
159   // Create two actors with half the size of the stage and set them to be partially overlapping
160   Actor blue = Actor::New();
161   blue.SetProperty(Actor::Property::NAME, "Blue");
162   blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
163   blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(1.0f / 3.0f, 1.0f / 3.0f, 0.5f));
164   blue.SetProperty(Actor::Property::SIZE, actorSize);
165   blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
166
167   Actor green = Actor::New();
168   green.SetProperty(Actor::Property::NAME, "Green");
169   green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
170   green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(2.0f / 3.0f, 2.0f / 3.0f, 0.5f));
171   green.SetProperty(Actor::Property::SIZE, actorSize);
172
173   // Add the actors to the view
174   stage.Add(blue);
175   stage.Add(green);
176
177   // Render and notify
178   application.SendNotification();
179   application.Render(0);
180   application.Render(10);
181
182   HitTestAlgorithm::Results results;
183   HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
184   DALI_TEST_CHECK(results.actor == green);
185   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 1.0f / 6.0f, TEST_LOCATION);
186
187   HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
188   DALI_TEST_CHECK(results.actor == blue);
189   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
190
191   HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
192   DALI_TEST_CHECK(results.actor == green);
193   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
194   END_TEST;
195 }
196
197 int UtcDaliHitTestAlgorithmOrtho02(void)
198 {
199   TestApplication application;
200   tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()");
201
202   Stage             stage             = Stage::GetCurrent();
203   RenderTaskList    renderTaskList    = stage.GetRenderTaskList();
204   RenderTask        defaultRenderTask = renderTaskList.GetTask(0u);
205   Dali::CameraActor cameraActor       = defaultRenderTask.GetCameraActor();
206
207   Vector2 stageSize(stage.GetSize());
208   cameraActor.SetOrthographicProjection(-stageSize.x * 0.3f, stageSize.x * 0.7f, stageSize.y * 0.3f, -stageSize.y * 0.7f, 800.0f, 4895.0f);
209   cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
210
211   Vector2 actorSize(stageSize * 0.5f);
212   // Create two actors with half the size of the stage and set them to be partially overlapping
213   Actor blue = Actor::New();
214   blue.SetProperty(Actor::Property::NAME, "Blue");
215   blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
216   blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.2f, 0.2f, 0.5f));
217   blue.SetProperty(Actor::Property::SIZE, actorSize);
218   blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
219
220   Actor green = Actor::New();
221   green.SetProperty(Actor::Property::NAME, "Green");
222   green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
223   green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.4f, 0.4f, 0.5f));
224   green.SetProperty(Actor::Property::SIZE, actorSize);
225
226   // Add the actors to the view
227   stage.Add(blue);
228   stage.Add(green);
229
230   // Render and notify
231   application.SendNotification();
232   application.Render(0);
233   application.Render(10);
234
235   {
236     HitTestAlgorithm::Results results;
237     HitTest(stage, Vector2(240.0f, 400.0f), results, &DefaultIsActorTouchableFunction);
238     DALI_TEST_CHECK(results.actor == green);
239     DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION);
240   }
241
242   {
243     HitTestAlgorithm::Results results;
244     HitTest(stage, Vector2(0.001f, 0.001f), results, &DefaultIsActorTouchableFunction);
245     DALI_TEST_CHECK(results.actor == blue);
246     DALI_TEST_EQUALS(results.actorCoordinates, Vector2(0.001f, 0.001f), 0.001f, TEST_LOCATION);
247   }
248
249   {
250     HitTestAlgorithm::Results results;
251     HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction);
252     DALI_TEST_CHECK(!results.actor);
253     DALI_TEST_EQUALS(results.actorCoordinates, Vector2::ZERO, TEST_LOCATION);
254   }
255
256   // Just inside green
257   {
258     HitTestAlgorithm::Results results;
259     HitTest(stage, stageSize * 0.69f, results, &DefaultIsActorTouchableFunction);
260     DALI_TEST_CHECK(results.actor == green);
261     DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION);
262   }
263
264   END_TEST;
265 }
266
267 int UtcDaliHitTestAlgorithmClippingActor(void)
268 {
269   TestApplication application;
270   tet_infoline("Testing Dali::HitTestAlgorithm with a stencil");
271
272   Stage stage     = Stage::GetCurrent();
273   Actor rootLayer = stage.GetRootLayer();
274   rootLayer.SetProperty(Actor::Property::NAME, "RootLayer");
275
276   // Create a layer
277   Layer layer = Layer::New();
278   layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
279   layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
280   layer.SetProperty(Actor::Property::NAME, "layer");
281   stage.Add(layer);
282
283   // Create a clipping actor and add it to the layer.
284   Actor clippingActor = CreateRenderableActor();
285   clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
286   clippingActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
287   clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
288   clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
289   clippingActor.SetProperty(Actor::Property::NAME, "clippingActor");
290   layer.Add(clippingActor);
291
292   // Create a renderable actor and add it to the clipping actor.
293   Actor childActor = CreateRenderableActor();
294   childActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
295   childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
296   childActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
297   childActor.SetProperty(Actor::Property::NAME, "childActor");
298   clippingActor.Add(childActor);
299
300   // Render and notify
301   application.SendNotification();
302   application.Render();
303
304   // Hit within clippingActor and childActor.
305   HitTestAlgorithm::Results results;
306   HitTest(stage, Vector2(10.0f, 10.0f), results, &DefaultIsActorTouchableFunction);
307   DALI_TEST_CHECK(results.actor == childActor);
308   tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
309
310   // Hit within childActor but outside of clippingActor, should hit the root-layer instead.
311   HitTest(stage, Vector2(60.0f, 60.0f), results, &DefaultIsActorTouchableFunction);
312   DALI_TEST_CHECK(results.actor == rootLayer);
313   tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
314
315   END_TEST;
316 }
317
318 int UtcDaliHitTestAlgorithmOverlay(void)
319 {
320   TestApplication application;
321   tet_infoline("Testing Dali::HitTestAlgorithm with overlay actors");
322
323   Stage             stage             = Stage::GetCurrent();
324   RenderTaskList    renderTaskList    = stage.GetRenderTaskList();
325   RenderTask        defaultRenderTask = renderTaskList.GetTask(0u);
326   Dali::CameraActor cameraActor       = defaultRenderTask.GetCameraActor();
327
328   Vector2 stageSize(stage.GetSize());
329   cameraActor.SetOrthographicProjection(stageSize);
330   cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
331
332   Vector2 actorSize(stageSize * 0.5f);
333   // Create two actors with half the size of the stage and set them to be partially overlapping
334   Actor blue = Actor::New();
335   blue.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
336   blue.SetProperty(Actor::Property::NAME, "Blue");
337   blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
338   blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(1.0f / 3.0f, 1.0f / 3.0f, 0.5f));
339   blue.SetProperty(Actor::Property::SIZE, actorSize);
340   blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
341
342   Actor green = Actor::New();
343   green.SetProperty(Actor::Property::NAME, "Green");
344   green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
345   green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(2.0f / 3.0f, 2.0f / 3.0f, 0.5f));
346   green.SetProperty(Actor::Property::SIZE, actorSize);
347
348   // Add the actors to the view
349   stage.Add(blue);
350   stage.Add(green);
351
352   // Render and notify
353   application.SendNotification();
354   application.Render(0);
355   application.Render(10);
356
357   HitTestAlgorithm::Results results;
358
359   //Hit in the intersection. Should pick the blue actor since it is an overlay.
360   HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
361   DALI_TEST_CHECK(results.actor == blue);
362   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 5.0f / 6.0f, TEST_LOCATION);
363
364   //Hit in the blue actor
365   HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
366   DALI_TEST_CHECK(results.actor == blue);
367   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
368
369   //Hit in the green actor
370   HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
371   DALI_TEST_CHECK(results.actor == green);
372   DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
373   END_TEST;
374 }