Dali 3D User Interface Engine
utc-Dali-HitTestAlgorithm.cpp
Go to the documentation of this file.
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>
24 #include <dali-test-suite-utils.h>
25 
26 using namespace Dali;
27 
28 namespace
29 {
30 
35 {
36  bool hittable = false;
37 
38  switch (type)
39  {
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  }
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 
73 {
74  bool hittable = false;
75 
76  switch (type)
77  {
79  {
80  if( actor.IsVisible() &&
81  actor.IsSensitive() &&
82  actor.GetCurrentWorldColor().a > 0.01f)
83  {
84  hittable = true;
85  }
86  break;
87  }
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
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);
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
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();
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 
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);
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 );
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 
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();
201  Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
202  DALI_TEST_CHECK( !results.actor );
204 
205  screenCoordinates.x = 80.f;
206  screenCoordinates.y = 70.f;
207 
208  results.actor = Actor();
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();
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  screenCoordinates.x = 120.f;
221  screenCoordinates.y = 130.f;
222 
223  results.actor = Actor();
225  Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
226  DALI_TEST_CHECK( !results.actor );
228 
229  results.actor = Actor();
231  Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
232  DALI_TEST_CHECK( results.actor == actor[1]);
233  DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
234  END_TEST;
235 }
236 
237 
239 {
240  TestApplication application;
241  tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()");
242 
243  Stage stage = Stage::GetCurrent();
244  RenderTaskList renderTaskList = stage.GetRenderTaskList();
245  RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
246  Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
247 
248  Vector2 stageSize ( stage.GetSize() );
249  cameraActor.SetOrthographicProjection( stageSize );
250  cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
251 
252  Vector2 actorSize( stageSize * 0.5f );
253  // Create two actors with half the size of the stage and set them to be partially overlapping
254  Actor blue = Actor::New();
255  blue.SetName( "Blue" );
257  blue.SetParentOrigin( Vector3(1.0f/3.0f, 1.0f/3.0f, 0.5f) );
258  blue.SetSize( actorSize );
259  blue.SetZ(30.0f);
260 
261  Actor green = Actor::New( );
262  green.SetName( "Green" );
264  green.SetParentOrigin( Vector3(2.0f/3.0f, 2.0f/3.0f, 0.5f) );
265  green.SetSize( actorSize );
266 
267  // Add the actors to the view
268  stage.Add( blue );
269  stage.Add( green );
270 
271  // Render and notify
272  application.SendNotification();
273  application.Render(0);
274  application.Render(10);
275 
277  HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
278  DALI_TEST_CHECK( results.actor == green );
279  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 1.0f/6.0f, TEST_LOCATION );
280 
281  HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
282  DALI_TEST_CHECK( results.actor == blue );
283  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
284 
285  HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
286  DALI_TEST_CHECK( results.actor == green );
287  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
288  END_TEST;
289 }
290 
291 
293 {
294  TestApplication application;
295  tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()");
296 
297  Stage stage = Stage::GetCurrent();
298  RenderTaskList renderTaskList = stage.GetRenderTaskList();
299  RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
300  Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
301 
302  Vector2 stageSize ( stage.GetSize() );
303  cameraActor.SetOrthographicProjection(-stageSize.x * 0.3f, stageSize.x * 0.7f,
304  stageSize.y * 0.3f, -stageSize.y * 0.7f,
305  800.0f, 4895.0f);
306  cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
307 
308  Vector2 actorSize( stageSize * 0.5f );
309  // Create two actors with half the size of the stage and set them to be partially overlapping
310  Actor blue = Actor::New();
311  blue.SetName( "Blue" );
313  blue.SetParentOrigin( Vector3(0.2f, 0.2f, 0.5f) );
314  blue.SetSize( actorSize );
315  blue.SetZ(30.0f);
316 
317  Actor green = Actor::New( );
318  green.SetName( "Green" );
320  green.SetParentOrigin( Vector3(0.4f, 0.4f, 0.5f) );
321  green.SetSize( actorSize );
322 
323  // Add the actors to the view
324  stage.Add( blue );
325  stage.Add( green );
326 
327  // Render and notify
328  application.SendNotification();
329  application.Render(0);
330  application.Render(10);
331 
332  {
334  HitTest(stage, Vector2( 240.0f, 400.0f ), results, &DefaultIsActorTouchableFunction);
335  DALI_TEST_CHECK( results.actor == green );
336  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION );
337  }
338 
339  {
341  HitTest(stage, Vector2( 0.001f, 0.001f ), results, &DefaultIsActorTouchableFunction);
342  DALI_TEST_CHECK( results.actor == blue );
343  DALI_TEST_EQUALS( results.actorCoordinates, Vector2( 0.001f, 0.001f ), 0.001f, TEST_LOCATION );
344  }
345 
346  {
348  HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction);
349  DALI_TEST_CHECK( ! results.actor );
351  }
352 
353  // Just inside green
354  {
356  HitTest(stage, stageSize*0.69f, results, &DefaultIsActorTouchableFunction);
357  DALI_TEST_CHECK( results.actor == green );
358  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION );
359  }
360 
361  END_TEST;
362 }
363 
365 {
366  TestApplication application;
367  tet_infoline("Testing Dali::HitTestAlgorithm with a stencil");
368 
369  Stage stage = Stage::GetCurrent();
370  Actor rootLayer = stage.GetRootLayer();
371  rootLayer.SetName( "RootLayer" );
372 
373  // Create a layer
374  Layer layer = Layer::New();
377  layer.SetName( "layer" );
378  stage.Add( layer );
379 
380  // Create a stencil and add that to the layer
384  stencil.SetSize( 50.0f, 50.0f );
385  stencil.SetDrawMode( DrawMode::STENCIL );
386  stencil.SetName( "stencil" );
387  layer.Add( stencil );
388 
389  // Create a renderable actor and add that to the layer
390  Actor layerHitActor = ImageActor::New( Dali::BufferImage::WHITE() );
391  layerHitActor.SetSize( 100.0f, 100.0f );
392  layerHitActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
393  layerHitActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
394  layerHitActor.SetName( "layerHitActor" );
395  layer.Add( layerHitActor );
396 
397  // Render and notify
398  application.SendNotification();
399  application.Render();
400 
401  // Hit within stencil and actor
402  {
404  HitTest(stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction);
405  DALI_TEST_CHECK( results.actor == layerHitActor );
406  tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
407  }
408 
409  // Hit within actor but outside of stencil, should hit the root-layer
410  {
412  HitTest(stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction);
413  DALI_TEST_CHECK( results.actor == rootLayer );
414  tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
415  }
416  END_TEST;
417 }
418 
420 {
421  TestApplication application;
422  tet_infoline("Testing Dali::HitTestAlgorithm with overlay actors");
423 
424  Stage stage = Stage::GetCurrent();
425  RenderTaskList renderTaskList = stage.GetRenderTaskList();
426  RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
427  Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
428 
429  Vector2 stageSize ( stage.GetSize() );
430  cameraActor.SetOrthographicProjection( stageSize );
431  cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
432 
433  Vector2 actorSize( stageSize * 0.5f );
434  // Create two actors with half the size of the stage and set them to be partially overlapping
435  Actor blue = Actor::New();
437  blue.SetName( "Blue" );
439  blue.SetParentOrigin( Vector3(1.0f/3.0f, 1.0f/3.0f, 0.5f) );
440  blue.SetSize( actorSize );
441  blue.SetZ(30.0f);
442 
443  Actor green = Actor::New( );
444  green.SetName( "Green" );
446  green.SetParentOrigin( Vector3(2.0f/3.0f, 2.0f/3.0f, 0.5f) );
447  green.SetSize( actorSize );
448 
449  // Add the actors to the view
450  stage.Add( blue );
451  stage.Add( green );
452 
453  // Render and notify
454  application.SendNotification();
455  application.Render(0);
456  application.Render(10);
457 
459 
460  //Hit in the intersection. Should pick the blue actor since it is an overlay.
461  HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
462  DALI_TEST_CHECK( results.actor == blue );
463  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 5.0f/6.0f, TEST_LOCATION );
464 
465  //Hit in the blue actor
466  HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
467  DALI_TEST_CHECK( results.actor == blue );
468  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
469 
470  //Hit in the green actor
471  HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
472  DALI_TEST_CHECK( results.actor == green );
473  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
474  END_TEST;
475 }
Dali Docs Home
Read more about Dali