[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-physics2d / utc-Dali-PhysicsAdaptor.cpp
1 /*
2  * Copyright (c) 2023 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 #include <stdlib.h>
18 #include <iostream>
19 #include <typeinfo>
20
21 // Need to override adaptor classes for toolkit test harness, so include
22 // test harness headers before dali headers.
23 #include <dali-physics/dali-physics.h>
24 #include <dali-toolkit-test-suite-utils.h>
25 #include <toolkit-event-thread-callback.h>
26
27 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
28 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
29 #include <dali/devel-api/adaptor-framework/window-devel.h>
30 #include <dali/devel-api/events/hit-test-algorithm.h>
31
32 #include <chipmunk/chipmunk.h>
33
34 using namespace Dali;
35 using namespace Dali::Toolkit::Physics;
36
37 void utc_dali_physics2d_startup(void)
38 {
39   test_return_value = TET_UNDEF;
40 }
41
42 void utc_dali_physics2d_cleanup(void)
43 {
44   test_return_value = TET_PASS;
45 }
46
47 cpBody* CreateBody(cpSpace* space)
48 {
49   const float BALL_MASS       = 10.0f;
50   const float BALL_RADIUS     = 26.0f;
51   const float BALL_ELASTICITY = 0.5f;
52   const float BALL_FRICTION   = 0.5f;
53
54   cpBody* body = cpSpaceAddBody(space, cpBodyNew(BALL_MASS, cpMomentForCircle(BALL_MASS, 0.0f, BALL_RADIUS, cpvzero)));
55
56   cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, BALL_RADIUS, cpvzero));
57   cpShapeSetElasticity(shape, BALL_ELASTICITY);
58   cpShapeSetFriction(shape, BALL_FRICTION);
59
60   return body;
61 }
62
63 // Defines a PolyShape
64 cpBody* CreateHexBody(cpSpace* space)
65 {
66   const float MASS       = 10.0f;
67   const float RADIUS     = 26.0f;
68   const float ELASTICITY = 0.5f;
69   const float FRICTION   = 0.5f;
70
71   cpVect hexagon[6];
72   for(int i = 0; i < 6; i++)
73   {
74     cpFloat angle = -CP_PI * 2.0f * i / 6.0f;
75     hexagon[i]    = cpvmult(cpv(cos(angle), sin(angle)), RADIUS - 1.0f);
76   }
77
78   cpBody*  body  = cpSpaceAddBody(space, cpBodyNew(MASS, cpMomentForPoly(MASS, 6, hexagon, cpvzero, 0.0f)));
79   cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 6, hexagon, cpTransformIdentity, 1.0f));
80
81   cpShapeSetElasticity(shape, ELASTICITY);
82   cpShapeSetFriction(shape, FRICTION);
83
84   return body;
85 }
86
87 // Defines a SegmentShape
88 cpBody* CreateSegBody(cpSpace* space)
89 {
90   const float MASS       = 10.0f;
91   const float RADIUS     = 26.0f;
92   const float ELASTICITY = 0.5f;
93   const float FRICTION   = 0.5f;
94
95   cpVect   a     = cpv(0, 100);
96   cpVect   b     = cpv(100, 0);
97   cpBody*  body  = cpSpaceAddBody(space, cpBodyNew(MASS, cpMomentForSegment(MASS, a, b, 0.0f)));
98   cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, RADIUS));
99
100   cpShapeSetElasticity(shape, ELASTICITY);
101   cpShapeSetFriction(shape, FRICTION);
102
103   return body;
104 }
105
106 int UtcDaliPhysics2DCreateAdaptorP1(void)
107 {
108   ToolkitTestApplication application;
109
110   Matrix     transform(true);
111   Uint16Pair size(640, 480);
112
113   PhysicsAdaptor handle = PhysicsAdaptor::New(transform, size);
114   DALI_TEST_CHECK(handle);
115
116   END_TEST;
117 }
118
119 int UtcDaliPhysics2DCreateAdaptorN1(void)
120 {
121   ToolkitTestApplication application;
122
123   PhysicsAdaptor handle;
124   DALI_TEST_CHECK(!handle);
125
126   END_TEST;
127 }
128
129 int UtcDaliPhysics2DDowncastP1(void)
130 {
131   ToolkitTestApplication application;
132
133   Matrix     transform(true);
134   Uint16Pair size(640, 480);
135
136   BaseHandle handle = PhysicsAdaptor::New(transform, size);
137
138   auto adaptor = PhysicsAdaptor::DownCast(handle);
139   DALI_TEST_CHECK(adaptor);
140   //Following only works if type is registered
141   //DALI_TEST_EQUALS("PhysicsAdaptor", adaptor.GetTypeName(), TEST_LOCATION);
142   END_TEST;
143 }
144
145 int UtcDaliPhysics2DDowncastN1(void)
146 {
147   BaseHandle handle;
148   auto       adaptor = PhysicsAdaptor::DownCast(handle);
149   DALI_TEST_CHECK(!adaptor);
150
151   DALI_TEST_CHECK(typeid(PhysicsAdaptor) == typeid(decltype(adaptor)));
152   END_TEST;
153 }
154
155 int UtcDaliPhysics2DAdaptorMoveConstructor(void)
156 {
157   ToolkitTestApplication application;
158   tet_infoline("Testing the move constructor");
159
160   Matrix         transform(true);
161   Uint16Pair     size(640, 480);
162   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
163   DALI_TEST_CHECK(adaptor);
164
165   PhysicsAdaptor moved = std::move(adaptor);
166   DALI_TEST_CHECK(moved);
167   DALI_TEST_CHECK(!adaptor);
168   DALI_TEST_CHECK(moved != adaptor);
169
170   END_TEST;
171 }
172
173 int UtcDaliPhysics2DAdaptorCopyConstructor(void)
174 {
175   ToolkitTestApplication application;
176   tet_infoline("Testing the move constructor");
177
178   Matrix         transform(true);
179   Uint16Pair     size(640, 480);
180   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
181
182   DALI_TEST_CHECK(adaptor);
183
184   PhysicsAdaptor altAdaptor = adaptor;
185   DALI_TEST_CHECK(altAdaptor);
186   DALI_TEST_CHECK(adaptor);
187   DALI_TEST_CHECK(altAdaptor == adaptor); // should point at same object
188
189   END_TEST;
190 }
191
192 int UtcDaliPhysics2DAdaptorCopyAssign(void)
193 {
194   ToolkitTestApplication application;
195   tet_infoline("Testing the copy assign");
196
197   Matrix         transform(true);
198   Uint16Pair     size(640, 480);
199   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
200   DALI_TEST_CHECK(adaptor);
201
202   PhysicsAdaptor altAdaptor = adaptor;
203   DALI_TEST_CHECK(altAdaptor);
204   DALI_TEST_CHECK(adaptor);
205   DALI_TEST_CHECK(altAdaptor == adaptor); // should point at same object
206
207   END_TEST;
208 }
209
210 int UtcDaliPhysics2DAdaptorMoveAssignment(void)
211 {
212   ToolkitTestApplication application;
213   tet_infoline("Testing the move constructor");
214
215   Matrix         transform(true);
216   Uint16Pair     size(640, 480);
217   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
218   DALI_TEST_CHECK(adaptor);
219
220   PhysicsAdaptor moved;
221   moved = std::move(adaptor);
222   DALI_TEST_CHECK(moved);
223   DALI_TEST_CHECK(!adaptor);
224
225   END_TEST;
226 }
227
228 int UtcDaliPhysics2DSetTimestep(void)
229 {
230   ToolkitTestApplication application;
231
232   Matrix     transform(true);
233   Uint16Pair size(640, 480);
234
235   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
236   adaptor.SetTimestep(1.0f / 60.0f);
237
238   DALI_TEST_EQUALS(adaptor.GetTimestep(), 1.0f / 60.0f, 0.0001f, TEST_LOCATION);
239
240   END_TEST;
241 }
242
243 int UtcDaliPhysics2DGetTimestep(void)
244 {
245   ToolkitTestApplication application;
246
247   Matrix     transform(true);
248   Uint16Pair size(640, 480);
249
250   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
251   adaptor.SetTimestep(1.0f / 60.0f);
252   float timestep = adaptor.GetTimestep();
253   float expected = 1.0f / 60.0f;
254   DALI_TEST_EQUALS(timestep, expected, 0.0001f, TEST_LOCATION);
255
256   adaptor.SetTimestep(1.0f / 120.0f);
257   timestep = adaptor.GetTimestep();
258   expected = 1.0f / 120.0f;
259   DALI_TEST_EQUALS(timestep, expected, 0.0001f, TEST_LOCATION);
260
261   END_TEST;
262 }
263
264 int UtcDaliPhysics2DGetPhysicsAccessorP1(void)
265 {
266   ToolkitTestApplication application;
267
268   Matrix     transform(true);
269   Uint16Pair size(640, 480);
270
271   PhysicsAdaptor                           adaptor  = PhysicsAdaptor::New(transform, size);
272   PhysicsAdaptor::ScopedPhysicsAccessorPtr accessor = adaptor.GetPhysicsAccessor();
273   DALI_TEST_CHECK(accessor.get() != nullptr);
274
275   Dali::Any world = accessor->GetNative();
276   DALI_TEST_CHECK(!world.Empty());
277
278   END_TEST;
279 }
280
281 int UtcDaliPhysics2DGetPhysicsAccessorN1(void)
282 {
283   ToolkitTestApplication application;
284
285   PhysicsAdaptor handle;
286   DALI_TEST_CHECK(!handle);
287
288   try
289   {
290     auto ptr = handle.GetPhysicsAccessor();
291     DALI_TEST_CHECK(ptr == nullptr);
292
293     tet_result(TET_FAIL);
294   }
295   catch(DaliException& e)
296   {
297     DALI_TEST_ASSERT(e, "Physics adaptor handle is empty", TEST_LOCATION);
298   }
299
300   END_TEST;
301 }
302
303 int UtcDaliPhysics2DAdaptorGetRootActor(void)
304 {
305   tet_infoline("Test that the root actor can be retrieved");
306
307   ToolkitTestApplication application;
308   Matrix                 transform(false);
309   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
310   Uint16Pair     size(640, 480);
311   auto           scene     = application.GetScene();
312   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
313   Actor          rootActor = adaptor.GetRootActor();
314   scene.Add(rootActor);
315
316   DALI_TEST_CHECK(rootActor);
317   DALI_TEST_EQUALS(rootActor.GetProperty<Vector2>(Actor::Property::SIZE), Vector2(640.0f, 480.0f), 0.001f, TEST_LOCATION);
318
319   END_TEST;
320 }
321
322 int UtcDaliPhysics2DAdaptorCreateDebugLayer(void)
323 {
324   ToolkitTestApplication application;
325   Matrix                 transform(true);
326   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
327   Uint16Pair size(640, 480);
328   auto       scene = application.GetScene();
329
330   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
331   Actor          rootActor = adaptor.GetRootActor();
332   scene.Add(rootActor);
333   Window window = DevelWindow::Get(rootActor);
334
335   Layer layer = adaptor.CreateDebugLayer(window);
336   DALI_TEST_CHECK(layer);
337
338   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
339
340   cpBody* body{nullptr};
341   cpBody* body2{nullptr};
342   cpBody* body3{nullptr};
343   {
344     auto accessor = adaptor.GetPhysicsAccessor();
345     auto space    = accessor->GetNative().Get<cpSpace*>();
346
347     body                     = CreateBody(space);
348     Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
349     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
350     cpBodySetPosition(body, cpv(0, 0));
351
352     // Constraint should create a dot in debug
353     cpBody* staticBody = cpSpaceGetStaticBody(space);
354     cpSpaceAddConstraint(space, cpPivotJointNew(staticBody, body, cpv(10, 10)));
355
356     body2                     = CreateHexBody(space);
357     Dali::Actor ballActor2    = Toolkit::ImageView::New("gallery-small-1.jpg");
358     auto        physicsActor2 = adaptor.AddActorBody(ballActor2, body2);
359     cpBodySleep(body2);
360
361     body3                     = CreateSegBody(space);
362     Dali::Actor ballActor3    = Toolkit::ImageView::New("gallery-small-1.jpg");
363     auto        physicsActor3 = adaptor.AddActorBody(ballActor3, body3);
364   }
365   Test::WaitForEventThreadTrigger(1);
366
367   // Render - if it doesn't crash, great!
368   application.SendNotification();
369   application.Render();
370
371   Uint16Pair size2(480, 640);
372   adaptor.SetTransformAndSize(transform, size2);
373
374   application.SendNotification();
375   application.Render();
376
377   END_TEST;
378 }
379
380 int UtcDaliPhysics2DAdaptorTranslateToPhysicsSpace1(void)
381 {
382   ToolkitTestApplication application;
383   Matrix                 transform(false);
384   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
385   Uint16Pair     size(640, 480);
386   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
387
388   Vector3 a(30, 20, 10);
389   Vector3 expected(60, 40, 10);
390   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expected, 0.0001f, TEST_LOCATION);
391
392   END_TEST;
393 }
394
395 int UtcDaliPhysics2DAdaptorTranslateToPhysicsSpace2(void)
396 {
397   ToolkitTestApplication application;
398   Matrix                 transform(false);
399   tet_infoline("Test that using an alternative scale doesn't change rotation");
400   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
401   Uint16Pair     size(640, 480);
402   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
403
404   // Rotation shouldn't change under this scale
405   Quaternion q(Degree(30.0f), Vector3::XAXIS);
406   Quaternion expected(Degree(30.0f), Vector3::XAXIS);
407   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), expected, 0.0001f, TEST_LOCATION);
408
409   END_TEST;
410 }
411
412 int UtcDaliPhysics2DAdaptorTranslateToPhysicsSpace3(void)
413 {
414   ToolkitTestApplication application;
415   Matrix                 transform(false);
416   tet_infoline("Test that using an inverted Y scale inverts rotation");
417
418   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
419   Uint16Pair     size(640, 480);
420   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
421
422   Quaternion q(Degree(30.0f), Vector3::ZAXIS);
423   Quaternion expected(Degree(-30.0f), Vector3::ZAXIS);
424
425   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(q), expected, 0.0001f, TEST_LOCATION);
426
427   END_TEST;
428 }
429
430 int UtcDaliPhysics2DAdaptorTranslateFromPhysicsSpace1(void)
431 {
432   ToolkitTestApplication application;
433   Matrix                 transform(false);
434   tet_infoline("Test that using a double scale halves position");
435
436   transform.SetIdentityAndScale(Vector3(2.0f, -2.0f, 1.0f));
437   Uint16Pair     size(640, 480);
438   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
439
440   Vector3 position(20.0f, 20.0f, 0.0f);
441   Vector3 expected(10.0f, -10.0f, 0.0f);
442
443   DALI_TEST_EQUALS(adaptor.TranslateFromPhysicsSpace(position), expected, 0.0001f, TEST_LOCATION);
444
445   END_TEST;
446 }
447
448 int UtcDaliPhysics2DAdaptorConvertVectorToPhysicsSpace01(void)
449 {
450   ToolkitTestApplication application;
451   Matrix                 transform(false);
452   tet_infoline("Test that using a translation does not translate vector");
453
454   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
455   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
456   Uint16Pair     size(640, 480);
457   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
458   Vector3        vector(20.0f, 20.0f, 0.0f);
459   DALI_TEST_EQUALS(adaptor.ConvertVectorToPhysicsSpace(vector), vector, 0.0001f, TEST_LOCATION);
460
461   END_TEST;
462 }
463
464 int UtcDaliPhysics2DAdaptorConvertVectorToPhysicsSpace02(void)
465 {
466   ToolkitTestApplication application;
467   Matrix                 transform(false);
468   tet_infoline("Test that using a translation with inverse Y does not translate vector");
469
470   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
471   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
472   Uint16Pair     size(640, 480);
473   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
474   Vector3        vector(20.0f, 20.0f, 0.0f);
475   Vector3        expected(20.0f, -20.0f, 0.0f);
476   DALI_TEST_EQUALS(adaptor.ConvertVectorToPhysicsSpace(vector), expected, 0.0001f, TEST_LOCATION);
477
478   END_TEST;
479 }
480
481 int UtcDaliPhysics2DAdaptorConvertVectorFromPhysicsSpace01(void)
482 {
483   ToolkitTestApplication application;
484   Matrix                 transform(false);
485   tet_infoline("Test that using a translation does not translate vector");
486
487   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
488   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
489   Uint16Pair     size(640, 480);
490   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
491   Vector3        vector(20.0f, 20.0f, 0.0f);
492   DALI_TEST_EQUALS(adaptor.ConvertVectorFromPhysicsSpace(vector), vector, 0.0001f, TEST_LOCATION);
493
494   END_TEST;
495 }
496
497 int UtcDaliPhysics2DAdaptorConvertVectorFromPhysicsSpace02(void)
498 {
499   ToolkitTestApplication application;
500   Matrix                 transform(false);
501   tet_infoline("Test that using a translation with inverse Y does not translate vector");
502
503   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
504   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
505   Uint16Pair     size(640, 480);
506   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
507   Vector3        vector(20.0f, 20.0f, 0.0f);
508   Vector3        expected(20.0f, -20.0f, 0.0f);
509   DALI_TEST_EQUALS(adaptor.ConvertVectorFromPhysicsSpace(vector), expected, 0.0001f, TEST_LOCATION);
510
511   END_TEST;
512 }
513
514 int UtcDaliPhysics2DAdaptorSetTransformAndSize(void)
515 {
516   ToolkitTestApplication application;
517   Matrix                 transform(false);
518   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
519   Uint16Pair     size(640, 480);
520   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
521
522   Vector3 a(30, 20, 10);
523   Vector3 expected(60, 40, 10);
524   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expected, 0.0001f, TEST_LOCATION);
525
526   transform.SetIdentityAndScale(Vector3(1.0f, -1.0f, 1.0f));
527   transform.SetTranslation(Vector3(0.0f, 100.0f, 0.0f));
528   adaptor.SetTransformAndSize(transform, size);
529
530   Vector3 expect2(30, 80, 10);
531   DALI_TEST_EQUALS(adaptor.TranslateToPhysicsSpace(a), expect2, 0.0001f, TEST_LOCATION);
532
533   END_TEST;
534 }
535
536 int UtcDaliPhysics2DAdaptorSetIntegrationState(void)
537 {
538   tet_infoline("Test that changing the integration state is reflected");
539
540   ToolkitTestApplication application;
541   Matrix                 transform(false);
542   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
543   Uint16Pair     size(640, 480);
544   auto           scene     = application.GetScene();
545   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
546   Actor          rootActor = adaptor.GetRootActor();
547   scene.Add(rootActor);
548
549   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::ON);
550
551   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::OFF);
552   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::OFF);
553
554   END_TEST;
555 }
556
557 int UtcDaliPhysics2DAdaptorGetIntegrationState(void)
558 {
559   tet_infoline("Test that changing the integration state is reflected");
560
561   ToolkitTestApplication application;
562   Matrix                 transform(false);
563   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
564   Uint16Pair     size(640, 480);
565   auto           scene     = application.GetScene();
566   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
567   Actor          rootActor = adaptor.GetRootActor();
568   scene.Add(rootActor);
569
570   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::OFF);
571   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::OFF);
572
573   adaptor.SetIntegrationState(PhysicsAdaptor::IntegrationState::ON);
574   DALI_TEST_CHECK(adaptor.GetIntegrationState() == PhysicsAdaptor::IntegrationState::ON);
575
576   // Can't test actual integration step runs without adding actors - see utc-Dali-PhysicsActor.cpp.
577   END_TEST;
578 }
579
580 int UtcDaliPhysics2DAdaptorSetDebugState(void)
581 {
582   tet_infoline("Test that changing the debug state is reflected");
583
584   ToolkitTestApplication application;
585   Matrix                 transform(false);
586   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
587   Uint16Pair     size(640, 480);
588   auto           scene     = application.GetScene();
589   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
590   Actor          rootActor = adaptor.GetRootActor();
591   scene.Add(rootActor);
592
593   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
594
595   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
596   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::ON);
597
598   adaptor.SetDebugState(PhysicsAdaptor::DebugState::OFF);
599   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
600
601   END_TEST;
602 }
603
604 int UtcDaliPhysics2DAdaptorGetDebugState(void)
605 {
606   tet_infoline("Test that changing the debug state is reflected");
607
608   ToolkitTestApplication application;
609   Matrix                 transform(false);
610   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
611   Uint16Pair     size(640, 480);
612   auto           scene     = application.GetScene();
613   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
614   Actor          rootActor = adaptor.GetRootActor();
615   scene.Add(rootActor);
616
617   adaptor.SetDebugState(PhysicsAdaptor::DebugState::OFF);
618   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::OFF);
619
620   adaptor.SetDebugState(PhysicsAdaptor::DebugState::ON);
621   DALI_TEST_CHECK(adaptor.GetDebugState() == PhysicsAdaptor::DebugState::ON);
622
623   // Can't test actual debug step runs without adding actors - see utc-Dali-PhysicsActor.cpp.
624   END_TEST;
625 }
626
627 int UtcDaliPhysics2DAdaptorAddActorBody(void)
628 {
629   tet_infoline("Test that an actor/body pair can be added");
630
631   ToolkitTestApplication application;
632   Matrix                 transform(false);
633   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
634   Uint16Pair     size(640, 480);
635   auto           scene     = application.GetScene();
636   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
637   Actor          rootActor = adaptor.GetRootActor();
638   scene.Add(rootActor);
639
640   auto accessor = adaptor.GetPhysicsAccessor();
641   auto space    = accessor->GetNative().Get<cpSpace*>();
642
643   cpBody*     body         = CreateBody(space);
644   Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
645   auto        physicsActor = adaptor.AddActorBody(ballActor, body);
646
647   DALI_TEST_CHECK(physicsActor);
648   int id = ballActor[Actor::Property::ID];
649
650   DALI_TEST_EQUALS(physicsActor.GetId(), id, TEST_LOCATION);
651   DALI_TEST_EQUALS(physicsActor.GetBody().Get<cpBody*>(), body, TEST_LOCATION);
652
653   END_TEST;
654 }
655
656 void removeShape(cpBody* body, cpShape* shape, void* data)
657 {
658   cpSpace* space = static_cast<cpSpace*>(data);
659   cpSpaceRemoveShape(space, shape);
660   cpShapeSetBody(shape, nullptr);
661   cpShapeFree(shape);
662 }
663
664 int UtcDaliPhysics2DAdaptorRemoveActorBodyP01(void)
665 {
666   tet_infoline("Test that an actor/body pair can be removed");
667
668   ToolkitTestApplication application;
669   Matrix                 transform(false);
670   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
671   Uint16Pair     size(640, 480);
672   auto           scene     = application.GetScene();
673   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
674   Actor          rootActor = adaptor.GetRootActor();
675   scene.Add(rootActor);
676
677   cpBody* body;
678   {
679     auto accessor = adaptor.GetPhysicsAccessor();
680     auto space    = accessor->GetNative().Get<cpSpace*>();
681
682     body = CreateBody(space);
683   }
684   Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
685   auto        physicsActor = adaptor.AddActorBody(ballActor, body);
686
687   application.SendNotification();
688   application.Render();
689   application.SendNotification();
690   application.Render();
691
692   adaptor.RemoveActorBody(physicsActor);
693   DALI_TEST_CHECK(!ballActor.GetParent());
694
695   {
696     auto accessor = adaptor.GetPhysicsAccessor();
697     auto space    = accessor->GetNative().Get<cpSpace*>();
698
699     try
700     {
701       cpBodyEachShape(body, removeShape, space);
702       cpSpaceRemoveBody(space, body);
703       tet_result(TET_PASS);
704     }
705     catch(std::exception& e)
706     {
707       tet_result(TET_FAIL);
708     }
709   }
710
711   END_TEST;
712 }
713
714 int UtcDaliPhysics2DAdaptorRemoveActorBodyN01(void)
715 {
716   ToolkitTestApplication application;
717   Matrix                 transform(false);
718   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
719   Uint16Pair     size(640, 480);
720   auto           scene     = application.GetScene();
721   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
722   Actor          rootActor = adaptor.GetRootActor();
723   scene.Add(rootActor);
724
725   tet_infoline("Test that removing a physics actor that hasn't been created with AddActorBody does nothing");
726   Dali::Actor  actor        = Dali::Actor::New();
727   cpBody*      body         = cpBodyNew(1.0f, 1.0f);
728   PhysicsActor physicsActor = PhysicsActor::New(actor, body, adaptor);
729   ;
730   try
731   {
732     adaptor.RemoveActorBody(physicsActor);
733     tet_result(TET_PASS);
734   }
735   catch(std::exception& e)
736   {
737     // Should fail silently, without exception!
738     tet_result(TET_FAIL);
739   }
740
741   END_TEST;
742 }
743
744 int UtcDaliPhysics2DAdaptorRemoveActorBodyN02(void)
745 {
746   tet_infoline("Test that an empty actor/body pair doesn't break adaptor");
747
748   ToolkitTestApplication application;
749   Matrix                 transform(false);
750   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
751   Uint16Pair     size(640, 480);
752   auto           scene     = application.GetScene();
753   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
754   Actor          rootActor = adaptor.GetRootActor();
755   scene.Add(rootActor);
756
757   PhysicsActor physicsActor;
758   try
759   {
760     adaptor.RemoveActorBody(physicsActor);
761     tet_result(TET_FAIL);
762   }
763   catch(DaliException& e)
764   {
765     DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
766   }
767
768   END_TEST;
769 }
770
771 int UtcDaliPhysics2DAdaptorGetPhysicsActor(void)
772 {
773   tet_infoline("Test that an actor/body pair can be retrieved");
774
775   ToolkitTestApplication application;
776   Matrix                 transform(false);
777   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
778   Uint16Pair     size(640, 480);
779   auto           scene     = application.GetScene();
780   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
781   Actor          rootActor = adaptor.GetRootActor();
782   scene.Add(rootActor);
783
784   auto accessor = adaptor.GetPhysicsAccessor();
785   auto space    = accessor->GetNative().Get<cpSpace*>();
786
787   cpBody*     body         = CreateBody(space);
788   Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
789   auto        physicsActor = adaptor.AddActorBody(ballActor, body);
790
791   DALI_TEST_CHECK(physicsActor);
792
793   PhysicsActor testActor = adaptor.GetPhysicsActor(body);
794   DALI_TEST_CHECK(testActor);
795   DALI_TEST_CHECK(physicsActor == testActor);
796
797   END_TEST;
798 }
799
800 int UtcDaliPhysics2DAdaptorBuildPickingRay(void)
801 {
802   tet_infoline("Test that picking ray converts screen coords");
803
804   ToolkitTestApplication application;
805   Matrix                 transform(false);
806   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
807   Uint16Pair     size(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT);
808   const Vector2  center(TestApplication::DEFAULT_SURFACE_WIDTH * 0.5f, TestApplication::DEFAULT_SURFACE_HEIGHT * 0.5f);
809   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
810   Actor          rootActor = adaptor.GetRootActor();
811   auto           scene     = application.GetScene();
812   scene.Add(rootActor);
813
814   Vector3 from, to;
815   adaptor.BuildPickingRay(Vector3(center), Vector3(center), from, to); // Hit test centre of screen
816   Vector3 physCenter = adaptor.TranslateToPhysicsSpace(Vector3(center));
817   DALI_TEST_EQUALS(from, physCenter, 0.001f, TEST_LOCATION);
818
819   END_TEST;
820 }
821
822 int UtcDaliPhysics2DAdaptorProjectPoint(void)
823 {
824   tet_infoline("Test that a point is projected into physics space");
825
826   ToolkitTestApplication application;
827   Matrix                 transform(false);
828   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
829   Uint16Pair     size(640, 480);
830   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
831
832   Vector3 projectedPoint = adaptor.ProjectPoint(Vector3(), -Vector3::ZAXIS, 200);
833
834   DALI_TEST_EQUALS(projectedPoint, Vector3(0.0f, 0.0f, 0.0f), 0.001f, TEST_LOCATION);
835
836   END_TEST;
837 }
838
839 int UtcDaliPhysics2DAdaptorQueue(void)
840 {
841   tet_infoline("Test that Queue and CreateSyncPoint both work");
842
843   ToolkitTestApplication application;
844   Matrix                 transform(false);
845   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
846   Uint16Pair     size(640, 480);
847   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
848   Actor          rootActor = adaptor.GetRootActor();
849   auto           scene     = application.GetScene();
850   scene.Add(rootActor);
851
852   cpBody* body{nullptr};
853   {
854     auto accessor            = adaptor.GetPhysicsAccessor();
855     auto space               = accessor->GetNative().Get<cpSpace*>();
856     body                     = CreateBody(space);
857     Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
858     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
859   }
860
861   tet_infoline("Test that Queue works without accessor");
862   adaptor.Queue([body]() {
863     cpBodySetPosition(body, cpv(100.0f, 20.0f));
864   });
865   adaptor.CreateSyncPoint();
866
867   application.SendNotification();
868   application.Render();
869   // Should trigger an Update
870
871   {
872     auto   accessor = adaptor.GetPhysicsAccessor();
873     cpVect origin   = cpBodyGetPosition(body);
874
875     DALI_TEST_EQUALS(origin.x, cpFloat(100.0f), 0.001f, TEST_LOCATION);
876     DALI_TEST_EQUALS(origin.y, cpFloat(20.0f), 0.001f, TEST_LOCATION);
877   }
878
879   END_TEST;
880 }
881
882 int UtcDaliPhysics2DAdaptorCreateSyncPoint(void)
883 {
884   tet_infoline("Test that a delayed CreateSyncPoint delays update");
885
886   ToolkitTestApplication application;
887   Matrix                 transform(false);
888   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
889   Uint16Pair     size(640, 480);
890   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
891   Actor          rootActor = adaptor.GetRootActor();
892   auto           scene     = application.GetScene();
893   scene.Add(rootActor);
894
895   cpBody* body{nullptr};
896   {
897     auto accessor            = adaptor.GetPhysicsAccessor();
898     auto space               = accessor->GetNative().Get<cpSpace*>();
899     body                     = CreateBody(space);
900     Dali::Actor ballActor    = Toolkit::ImageView::New("gallery-small-1.jpg");
901     auto        physicsActor = adaptor.AddActorBody(ballActor, body);
902
903     tet_infoline("Test that Queue works with accessor");
904     adaptor.Queue([body]() {
905       cpBodySetPosition(body, cpv(100.0f, 20.0f));
906     });
907   }
908
909   // Should trigger an Update without processing queue
910   application.SendNotification();
911   application.Render();
912
913   {
914     auto accessor = adaptor.GetPhysicsAccessor();
915
916     cpVect origin = cpBodyGetPosition(body);
917     DALI_TEST_EQUALS(origin.x, cpFloat(0.0f), 0.01f, TEST_LOCATION);
918     DALI_TEST_EQUALS(origin.y, cpFloat(0.0f), 0.01f, TEST_LOCATION);
919   }
920
921   // Should now execute queue
922   adaptor.CreateSyncPoint();
923   application.SendNotification();
924   application.Render();
925
926   {
927     auto accessor = adaptor.GetPhysicsAccessor();
928
929     cpVect origin = cpBodyGetPosition(body);
930     DALI_TEST_EQUALS(origin.x, cpFloat(100.0f), 0.01f, TEST_LOCATION);
931     DALI_TEST_EQUALS(origin.y, cpFloat(20.0f), 0.01f, TEST_LOCATION);
932   }
933
934   END_TEST;
935 }
936
937 int UtcDaliPhysics2DAdaptorHitTestP(void)
938 {
939   tet_infoline("Test that hit testing finds a body");
940
941   ToolkitTestApplication application;
942   Matrix                 transform(false);
943   transform.SetIdentityAndScale(Vector3(1.0f, 1.0f, 1.0f));
944   Uint16Pair     size(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT);
945   const Vector2  center(TestApplication::DEFAULT_SURFACE_WIDTH * 0.5f, TestApplication::DEFAULT_SURFACE_HEIGHT * 0.5f);
946   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
947   Actor          rootActor = adaptor.GetRootActor();
948   auto           scene     = application.GetScene();
949   scene.Add(rootActor);
950
951   {
952     auto        accessor  = adaptor.GetPhysicsAccessor(); // Prevent integration
953     auto        space     = accessor->GetNative().Get<cpSpace*>();
954     Dali::Actor ballActor = Toolkit::ImageView::New(TEST_RESOURCE_DIR "/gallery-small-1.jpg");
955     cpBody*     body      = CreateBody(space);
956     cpBodySetPosition(body, cpv(center.x, center.y));
957
958     ballActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
959     ballActor[Actor::Property::ANCHOR_POINT]  = AnchorPoint::CENTER;
960
961     auto physicsActor = adaptor.AddActorBody(ballActor, body);
962   }
963   Test::WaitForEventThreadTrigger(1);
964
965   // Should trigger an Update without processing queue
966   application.SendNotification();
967   application.Render();
968
969   Vector3 from, to;
970   adaptor.BuildPickingRay(Vector3(center), Vector3(center), from, to); // Hit test centre of screen
971
972   {
973     auto    accessor = adaptor.GetPhysicsAccessor();
974     Vector3 localPivot;
975     float   distanceFromCamera;
976
977     cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, 1u << 31, 1u << 31};
978     Dali::Any     nativeFilter{GRAB_FILTER};
979
980     auto body = accessor->HitTest(from, from, nativeFilter, localPivot, distanceFromCamera);
981
982     DALI_TEST_CHECK(!body.Empty());
983   }
984
985   END_TEST;
986 }