Fix UTCs for EncodedBufferImage & HitTestAlgorithm
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-HitTestAlgorithm.cpp
1 /*
2  * Copyright (c) 2014 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 <iostream>
19
20 #include <stdlib.h>
21 #include <dali/public-api/dali-core.h>
22 #include <dali/devel-api/events/hit-test-algorithm.h>
23 #include <dali/integration-api/events/touch-event-integ.h>
24 #include <dali-test-suite-utils.h>
25
26 using namespace Dali;
27
28 namespace
29 {
30
31 /**
32  * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
33  */
34 bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
35 {
36   bool hittable = false;
37
38   switch (type)
39   {
40     case Dali::HitTestAlgorithm::CHECK_ACTOR:
41     {
42       // Check whether the actor is visible and not fully transparent.
43       if( actor.IsVisible()
44        && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT
45       {
46         // Check whether the actor has the specific name "HittableActor"
47         if(actor.GetName() == "HittableActor")
48         {
49           hittable = true;
50         }
51       }
52       break;
53     }
54     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
55     {
56       if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
57       {
58         hittable = true;
59       }
60       break;
61     }
62     default:
63     {
64       break;
65     }
66   }
67
68   return hittable;
69 };
70
71
72 bool DefaultIsActorTouchableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
73 {
74   bool hittable = false;
75
76   switch (type)
77   {
78     case Dali::HitTestAlgorithm::CHECK_ACTOR:
79     {
80       if( actor.IsVisible() &&
81           actor.IsSensitive() &&
82           actor.GetCurrentWorldColor().a > 0.01f)
83       {
84         hittable = true;
85       }
86       break;
87     }
88     case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
89     {
90       if( actor.IsVisible() && // Actor is visible, if not visible then none of its children are visible.
91           actor.IsSensitive()) // Actor is sensitive, if insensitive none of its children should be hittable either.
92       {
93         hittable = true;
94       }
95       break;
96     }
97     default:
98     {
99       break;
100     }
101   }
102
103   return hittable;
104 };
105
106 } // anonymous namespace
107
108
109 // Positive test case for a method
110 int UtcDaliHitTestAlgorithmWithFunctor(void)
111 {
112   TestApplication application;
113   tet_infoline("Testing Dali::HitTestAlgorithm functor");
114
115   Stage stage = Stage::GetCurrent();
116
117   Actor actor = Actor::New();
118   actor.SetSize(100.0f, 100.0f);
119   actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
120   actor.SetName("NonHittableActor");
121   stage.Add(actor);
122
123   // Render and notify
124   application.SendNotification();
125   application.Render();
126
127   Vector2 screenCoordinates( 10.0f, 10.0f );
128   Vector2 localCoordinates;
129   actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
130
131   // Perform a hit-test at the given screen coordinates
132   Dali::HitTestAlgorithm::Results results;
133   Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction );
134   DALI_TEST_CHECK( results.actor != actor );
135
136   actor.SetName("HittableActor");
137
138   results.actor = Actor();
139   results.actorCoordinates = Vector2::ZERO;
140
141   // Perform a hit-test at the given screen coordinates
142   Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction );
143   DALI_TEST_CHECK( results.actor == actor );
144   DALI_TEST_EQUALS( localCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
145   END_TEST;
146 }
147
148 int UtcDaliHitTestAlgorithmWithFunctorOnRenderTask(void)
149 {
150   TestApplication application;
151   tet_infoline("Testing Dali::HitTestAlgorithm functor, specific to a given render task");
152
153   Stage stage = Stage::GetCurrent();
154   Size stageSize = stage.GetSize();
155   RenderTaskList taskList = stage.GetRenderTaskList();
156
157   Actor actor[2];
158
159   for( int i=0; i<2; i++ )
160   {
161     actor[i] = Actor::New();
162     actor[i].SetSize(100.f, 100.f);
163     actor[i].SetParentOrigin(ParentOrigin::TOP_LEFT);
164     actor[i].SetAnchorPoint(AnchorPoint::TOP_LEFT);
165     actor[i].SetName("HittableActor");
166     stage.Add(actor[i]);
167   }
168   Vector2 position( 50.f, 40.f );
169   actor[1].SetPosition( position.x, position.y );
170
171   RenderTask renderTask[2];
172   renderTask[0] = taskList.GetTask( 0u );
173
174   FrameBufferImage frameBufferImage =  FrameBufferImage::New(stageSize.width, stageSize.height, Pixel::A8, Image::NEVER);
175   renderTask[1] = taskList.CreateTask();
176   renderTask[1].SetSourceActor( actor[1] );
177   renderTask[1].SetExclusive( true );
178   renderTask[1].SetInputEnabled( true );
179   renderTask[1].SetTargetFrameBuffer( frameBufferImage );
180   renderTask[1].SetRefreshRate( RenderTask::REFRESH_ONCE );
181   renderTask[1].SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
182   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
183
184   // Render and notify
185   application.SendNotification();
186   application.Render();
187   application.Render();
188   application.SendNotification();
189
190   // Perform a hit-test at the given screen coordinates with different render tasks
191
192   Dali::HitTestAlgorithm::Results results;
193   Vector2 screenCoordinates( 25.f, 25.f );
194
195   Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
196   DALI_TEST_CHECK( results.actor == actor[0] );
197   DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
198
199   results.actor = Actor();
200   results.actorCoordinates = Vector2::ZERO;
201   Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
202   DALI_TEST_CHECK( !results.actor );
203   DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION );
204
205   screenCoordinates.x = 80.f;
206   screenCoordinates.y = 70.f;
207
208   results.actor = Actor();
209   results.actorCoordinates = Vector2::ZERO;
210   Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
211   DALI_TEST_CHECK( results.actor == actor[0] );
212   DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
213
214   results.actor = Actor();
215   results.actorCoordinates = Vector2::ZERO;
216   Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
217   DALI_TEST_CHECK( results.actor == actor[1]);
218   DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
219
220
221   screenCoordinates.x = 120.f;
222   screenCoordinates.y = 130.f;
223
224   results.actor = Actor();
225   results.actorCoordinates = Vector2::ZERO;
226   Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
227   DALI_TEST_CHECK( results.actor == actor[1] );
228   DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
229
230   results.actor = Actor();
231   results.actorCoordinates = Vector2::ZERO;
232   Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
233   DALI_TEST_CHECK( results.actor == actor[1]);
234   DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
235   END_TEST;
236 }
237
238
239 int UtcDaliHitTestAlgorithmOrtho01(void)
240 {
241   TestApplication application;
242   tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()");
243
244   Stage stage = Stage::GetCurrent();
245   RenderTaskList renderTaskList = stage.GetRenderTaskList();
246   RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
247   Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
248
249   Vector2 stageSize ( stage.GetSize() );
250   cameraActor.SetOrthographicProjection( stageSize );
251   cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
252
253   Vector2 actorSize( stageSize * 0.5f );
254   // Create two actors with half the size of the stage and set them to be partially overlapping
255   Actor blue = Actor::New();
256   blue.SetName( "Blue" );
257   blue.SetAnchorPoint( AnchorPoint::CENTER );
258   blue.SetParentOrigin( Vector3(1.0f/3.0f, 1.0f/3.0f, 0.5f) );
259   blue.SetSize( actorSize );
260   blue.SetZ(30.0f);
261
262   Actor green = Actor::New( );
263   green.SetName( "Green" );
264   green.SetAnchorPoint( AnchorPoint::CENTER );
265   green.SetParentOrigin( Vector3(2.0f/3.0f, 2.0f/3.0f, 0.5f) );
266   green.SetSize( actorSize );
267
268   // Add the actors to the view
269   stage.Add( blue );
270   stage.Add( green );
271
272   // Render and notify
273   application.SendNotification();
274   application.Render(0);
275   application.Render(10);
276
277   HitTestAlgorithm::Results results;
278   HitTest(stage, Vector2( 240.0f, 400.0f ), results, &DefaultIsActorTouchableFunction);
279   DALI_TEST_CHECK( results.actor == blue );
280   DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 5.0f/6.0f, TEST_LOCATION );
281
282   HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
283   DALI_TEST_CHECK( results.actor == blue );
284   DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
285
286   HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
287   DALI_TEST_CHECK( results.actor == green );
288   DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
289   END_TEST;
290 }
291
292
293 int UtcDaliHitTestAlgorithmOrtho02(void)
294 {
295   TestApplication application;
296   tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()");
297
298   Stage stage = Stage::GetCurrent();
299   RenderTaskList renderTaskList = stage.GetRenderTaskList();
300   RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
301   Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
302
303   Vector2 stageSize ( stage.GetSize() );
304   cameraActor.SetOrthographicProjection(-stageSize.x * 0.3f,  stageSize.x * 0.7f,
305                                          stageSize.y * 0.3f, -stageSize.y * 0.7f,
306                                          800.0f, 4895.0f);
307   cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
308
309   Vector2 actorSize( stageSize * 0.5f );
310   // Create two actors with half the size of the stage and set them to be partially overlapping
311   Actor blue = Actor::New();
312   blue.SetName( "Blue" );
313   blue.SetAnchorPoint( AnchorPoint::TOP_LEFT );
314   blue.SetParentOrigin( Vector3(0.2f, 0.2f, 0.5f) );
315   blue.SetSize( actorSize );
316   blue.SetZ(30.0f);
317
318   Actor green = Actor::New( );
319   green.SetName( "Green" );
320   green.SetAnchorPoint( AnchorPoint::TOP_LEFT );
321   green.SetParentOrigin( Vector3(0.4f, 0.4f, 0.5f) );
322   green.SetSize( actorSize );
323
324   // Add the actors to the view
325   stage.Add( blue );
326   stage.Add( green );
327
328   // Render and notify
329   application.SendNotification();
330   application.Render(0);
331   application.Render(10);
332
333   {
334     HitTestAlgorithm::Results results;
335     HitTest(stage, Vector2( 240.0f, 400.0f ), results, &DefaultIsActorTouchableFunction);
336     DALI_TEST_CHECK( results.actor == green );
337     DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION );
338   }
339
340   {
341     HitTestAlgorithm::Results results;
342     HitTest(stage, Vector2( 0.001f, 0.001f ), results, &DefaultIsActorTouchableFunction);
343     DALI_TEST_CHECK( results.actor == blue );
344     DALI_TEST_EQUALS( results.actorCoordinates, Vector2( 0.001f, 0.001f ), 0.001f, TEST_LOCATION );
345   }
346
347   {
348     HitTestAlgorithm::Results results;
349     HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction);
350     DALI_TEST_CHECK( ! results.actor );
351     DALI_TEST_EQUALS( results.actorCoordinates, Vector2::ZERO, TEST_LOCATION );
352   }
353
354   // Just inside green
355   {
356     HitTestAlgorithm::Results results;
357     HitTest(stage, stageSize*0.69f, results, &DefaultIsActorTouchableFunction);
358     DALI_TEST_CHECK( results.actor == green );
359     DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION );
360   }
361
362   END_TEST;
363 }
364
365 int UtcDaliHitTestAlgorithmStencil(void)
366 {
367   TestApplication application;
368   tet_infoline("Testing Dali::HitTestAlgorithm with a stencil");
369
370   Stage stage = Stage::GetCurrent();
371   Actor rootLayer = stage.GetRootLayer();
372   rootLayer.SetName( "RootLayer" );
373
374   // Create a layer
375   Layer layer = Layer::New();
376   layer.SetAnchorPoint( AnchorPoint::TOP_LEFT );
377   layer.SetParentOrigin( ParentOrigin::TOP_LEFT );
378   layer.SetName( "layer" );
379   stage.Add( layer );
380
381   // Create a stencil and add that to the layer
382   Actor stencil = ImageActor::New(Dali::BufferImage::WHITE() );
383   stencil.SetAnchorPoint( AnchorPoint::TOP_LEFT );
384   stencil.SetParentOrigin( ParentOrigin::TOP_LEFT );
385   stencil.SetSize( 50.0f, 50.0f );
386   stencil.SetDrawMode( DrawMode::STENCIL );
387   stencil.SetName( "stencil" );
388   layer.Add( stencil );
389
390   // Create a renderable actor and add that to the layer
391   Actor layerHitActor = ImageActor::New();
392   layerHitActor.SetSize( 100.0f, 100.0f );
393   layerHitActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
394   layerHitActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
395   layerHitActor.SetName( "layerHitActor" );
396   layer.Add( layerHitActor );
397
398   // Render and notify
399   application.SendNotification();
400   application.Render();
401
402   // Hit within stencil and actor
403   {
404     HitTestAlgorithm::Results results;
405     HitTest(stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction);
406     DALI_TEST_CHECK( results.actor == layerHitActor );
407     tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
408   }
409
410   // Hit within actor but outside of stencil, should hit the root-layer
411   {
412     HitTestAlgorithm::Results results;
413     HitTest(stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction);
414     DALI_TEST_CHECK( results.actor == rootLayer );
415     tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
416   }
417   END_TEST;
418 }