[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-physics2d / utc-Dali-PhysicsActor.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 <chipmunk/chipmunk.h>
18 #include <stdlib.h>
19 #include <iostream>
20
21 // Need to override adaptor classes for toolkit test harness, so include
22 // test harness headers before dali headers.
23 #include <dali-toolkit-test-suite-utils.h>
24 #include <toolkit-event-thread-callback.h>
25
26 #include <dali-physics/dali-physics.h>
27 #include <dali-toolkit/dali-toolkit.h>
28 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
29
30 using namespace Dali;
31 using namespace Dali::Toolkit::Physics;
32
33 extern cpBody* CreateBody(cpSpace* space);
34
35 const char* BALL_IMAGE = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
36
37 int UtcDaliPhysics2DActorNew(void)
38 {
39   ToolkitTestApplication application;
40
41   cpBody* body{nullptr};
42
43   Matrix         transform(true);
44   Uint16Pair     size(640, 480);
45   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
46
47   auto accessor         = adaptor.GetPhysicsAccessor();
48   auto space            = accessor->GetNative().Get<cpSpace*>();
49   body                  = CreateBody(space);
50   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
51
52   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
53
54   DALI_TEST_CHECK(physicsActor);
55   END_TEST;
56 }
57
58 int UtcDaliPhysics2DActorDownCastP(void)
59 {
60   ToolkitTestApplication application;
61
62   Matrix         transform(true);
63   Uint16Pair     size(640, 480);
64   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
65
66   cpBody* body{nullptr};
67   auto    accessor          = adaptor.GetPhysicsAccessor();
68   auto    space             = accessor->GetNative().Get<cpSpace*>();
69   body                      = CreateBody(space);
70   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
71   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
72   BaseHandle   handle(physicsActor);
73
74   PhysicsActor actor2 = PhysicsActor::DownCast(handle);
75   DALI_TEST_CHECK(actor2);
76   DALI_TEST_EQUALS(physicsActor.GetId(), actor2.GetId(), TEST_LOCATION);
77
78   END_TEST;
79 }
80
81 int UtcDaliPhysics2DActorDownCastN(void)
82 {
83   BaseHandle   uninitializedHandle;
84   PhysicsActor actor = PhysicsActor::DownCast(uninitializedHandle);
85   DALI_TEST_CHECK(!actor);
86   END_TEST;
87 }
88
89 int UtcDaliPhysics2DActorMoveConstructor(void)
90 {
91   ToolkitTestApplication application;
92   tet_infoline("Testing the move constructor");
93
94   Matrix         transform(true);
95   Uint16Pair     size(640, 480);
96   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
97
98   cpBody* body{nullptr};
99   auto    accessor          = adaptor.GetPhysicsAccessor();
100   auto    space             = accessor->GetNative().Get<cpSpace*>();
101   body                      = CreateBody(space);
102   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
103   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
104
105   DALI_TEST_CHECK(physicsActor);
106   uint32_t id = physicsActor.GetId();
107
108   PhysicsActor moved = std::move(physicsActor);
109   DALI_TEST_CHECK(moved);
110   DALI_TEST_CHECK(!physicsActor);
111   DALI_TEST_CHECK(moved != physicsActor);
112   DALI_TEST_EQUALS(moved.GetId(), id, TEST_LOCATION);
113
114   END_TEST;
115 }
116
117 int UtcDaliPhysics2DActorCopyConstructor(void)
118 {
119   ToolkitTestApplication application;
120   tet_infoline("Testing the move constructor");
121
122   Matrix         transform(true);
123   Uint16Pair     size(640, 480);
124   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
125
126   cpBody* body{nullptr};
127   auto    accessor          = adaptor.GetPhysicsAccessor();
128   auto    space             = accessor->GetNative().Get<cpSpace*>();
129   body                      = CreateBody(space);
130   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
131   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
132
133   DALI_TEST_CHECK(physicsActor);
134   uint32_t id = physicsActor.GetId();
135
136   PhysicsActor selectedActor(physicsActor);
137   DALI_TEST_CHECK(selectedActor);
138   DALI_TEST_CHECK(physicsActor);
139   DALI_TEST_CHECK(selectedActor == physicsActor); // should point at same object
140   DALI_TEST_EQUALS(selectedActor.GetId(), id, TEST_LOCATION);
141
142   END_TEST;
143 }
144
145 int UtcDaliPhysics2DActorCopyAssign(void)
146 {
147   ToolkitTestApplication application;
148   tet_infoline("Testing the copy assign");
149
150   Matrix         transform(true);
151   Uint16Pair     size(640, 480);
152   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
153
154   cpBody* body{nullptr};
155   auto    accessor          = adaptor.GetPhysicsAccessor();
156   auto    space             = accessor->GetNative().Get<cpSpace*>();
157   body                      = CreateBody(space);
158   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
159   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
160
161   DALI_TEST_CHECK(physicsActor);
162   uint32_t id = physicsActor.GetId();
163
164   PhysicsActor selectedActor = physicsActor;
165   DALI_TEST_CHECK(selectedActor);
166   DALI_TEST_CHECK(physicsActor);
167   DALI_TEST_CHECK(selectedActor == physicsActor); // should point at same object
168   DALI_TEST_EQUALS(selectedActor.GetId(), id, TEST_LOCATION);
169
170   END_TEST;
171 }
172
173 int UtcDaliPhysics2DActorMoveAssignment(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   cpBody* body{nullptr};
183   auto    accessor          = adaptor.GetPhysicsAccessor();
184   auto    space             = accessor->GetNative().Get<cpSpace*>();
185   body                      = CreateBody(space);
186   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
187   PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
188
189   DALI_TEST_CHECK(physicsActor);
190   uint32_t id = physicsActor.GetId();
191
192   PhysicsActor moved;
193   moved = std::move(physicsActor);
194   DALI_TEST_CHECK(moved);
195   DALI_TEST_CHECK(!physicsActor);
196   DALI_TEST_EQUALS(moved.GetId(), id, TEST_LOCATION);
197
198   END_TEST;
199 }
200
201 int UtcDaliPhysics2DActorGetIdP(void)
202 {
203   ToolkitTestApplication application;
204   tet_infoline("Testing the ID Getter");
205
206   Matrix         transform(true);
207   Uint16Pair     size(640, 480);
208   PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
209
210   cpBody* body{nullptr};
211   auto    accessor          = adaptor.GetPhysicsAccessor();
212   auto    space             = accessor->GetNative().Get<cpSpace*>();
213   body                      = CreateBody(space);
214   Dali::Actor  ballActor    = Toolkit::ImageView::New(BALL_IMAGE);
215   PhysicsActor physicsActor = adaptor.AddActorBody(ballActor, body);
216   int          id           = physicsActor.GetId();
217   int          actorId      = ballActor[Actor::Property::ID];
218   DALI_TEST_EQUALS(id, actorId, TEST_LOCATION);
219
220   END_TEST;
221 }
222
223 int UtcDaliPhysics2DActorGetIdN(void)
224 {
225   ToolkitTestApplication application;
226   tet_infoline("Testing the ID Getter");
227
228   PhysicsActor physicsActor;
229   try
230   {
231     uint32_t id __attribute__((unused)) = physicsActor.GetId();
232     tet_result(TET_FAIL);
233   }
234   catch(DaliException e)
235   {
236     DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
237   }
238
239   END_TEST;
240 }
241
242 int UtcDaliPhysics2DActorGetBodyP(void)
243 {
244   ToolkitTestApplication application;
245   tet_infoline("Testing the body Getter");
246
247   Matrix         transform(true);
248   Uint16Pair     size(640, 480);
249   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
250   Actor          rootActor = adaptor.GetRootActor();
251   auto           scene     = application.GetScene();
252   scene.Add(rootActor);
253
254   PhysicsActor physicsActor;
255   cpBody*      body{nullptr};
256   {
257     auto accessor         = adaptor.GetPhysicsAccessor();
258     auto space            = accessor->GetNative().Get<cpSpace*>();
259     body                  = CreateBody(space);
260     Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
261
262     physicsActor = adaptor.AddActorBody(ballActor, body);
263   }
264
265   application.Render();
266   Test::WaitForEventThreadTrigger(1);
267
268   Dali::Any any = physicsActor.GetBody();
269   DALI_TEST_EQUALS(any.Get<cpBody*>(), body, TEST_LOCATION);
270
271   END_TEST;
272 }
273
274 int UtcDaliPhysics2DActorGetBodyN(void)
275 {
276   ToolkitTestApplication application;
277   tet_infoline("Testing the ID Getter");
278
279   PhysicsActor physicsActor;
280   try
281   {
282     Dali::Any any __attribute__((unused)) = physicsActor.GetBody();
283     tet_result(TET_FAIL);
284   }
285   catch(DaliException e)
286   {
287     DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
288   }
289   END_TEST;
290 }
291
292 int UtcDaliPhysics2DActorSetPosition(void)
293 {
294   tet_infoline("Test the AsyncSetPhysicsPosition() function");
295
296   ToolkitTestApplication application;
297   Matrix                 transform(false);
298   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
299   Uint16Pair     size(640, 480);
300   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
301   Actor          rootActor = adaptor.GetRootActor();
302   auto           scene     = application.GetScene();
303   scene.Add(rootActor);
304
305   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
306
307   cpBody*      body{nullptr};
308   PhysicsActor physicsActor;
309   {
310     auto accessor = adaptor.GetPhysicsAccessor();
311     auto space    = accessor->GetNative().Get<cpSpace*>();
312     body          = CreateBody(space);
313     physicsActor  = adaptor.AddActorBody(ballActor, body);
314     physicsActor.AsyncSetPhysicsPosition(Vector3(10, 20, -30));
315   }
316
317   Test::WaitForEventThreadTrigger(1);
318   adaptor.CreateSyncPoint();
319   application.SendNotification();
320   application.Render();
321
322   // Run 2 frames to ensure both buffers are set.
323   application.SendNotification();
324   application.Render();
325   {
326     auto accessor = adaptor.GetPhysicsAccessor();
327     auto actor    = rootActor.FindChildById(physicsActor.GetId());
328     // Warning - physics properties are never reflected in the event size cache.
329     // Have to use GetCurrentProperty to see the updated values.
330     DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(10, 20, 0), 0.01f, TEST_LOCATION);
331   }
332
333   END_TEST;
334 }
335
336 int UtcDaliPhysics2DActorSetRotation1(void)
337 {
338   tet_infoline("Test the AsyncSetPhysicsRotation() function");
339
340   ToolkitTestApplication application;
341   Matrix                 transform(false);
342   transform.SetIdentityAndScale(Vector3(2.0f, -2.0f, 1.0f));
343   Uint16Pair     size(640, 480);
344   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
345   Actor          rootActor = adaptor.GetRootActor();
346   auto           scene     = application.GetScene();
347   scene.Add(rootActor);
348
349   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
350
351   cpBody*      body{nullptr};
352   PhysicsActor physicsActor;
353   {
354     auto accessor = adaptor.GetPhysicsAccessor();
355     auto space    = accessor->GetNative().Get<cpSpace*>();
356     body          = CreateBody(space);
357     physicsActor  = adaptor.AddActorBody(ballActor, body);
358     physicsActor.AsyncSetPhysicsRotation(Quaternion(Degree(30), Vector3::ZAXIS));
359   }
360
361   Test::WaitForEventThreadTrigger(1);
362   adaptor.CreateSyncPoint();
363   application.SendNotification();
364   application.Render();
365
366   // Run 2 frames to ensure both buffers are set.
367   application.SendNotification();
368   application.Render();
369   {
370     auto accessor = adaptor.GetPhysicsAccessor();
371     auto actor    = rootActor.FindChildById(physicsActor.GetId());
372     // Warning - physics properties are never reflected in the event size cache.
373     // Have to use GetCurrentProperty to see the updated values.
374     Quaternion q = actor.GetCurrentProperty<Quaternion>(Actor::Property::ORIENTATION);
375     Quaternion expected(Degree(-30), Vector3::ZAXIS);
376     DALI_TEST_EQUALS(q, expected, 0.0001f, TEST_LOCATION);
377   }
378
379   END_TEST;
380 }
381
382 int UtcDaliPhysics2DActorSetRotation2(void)
383 {
384   tet_infoline("Test the AsyncSetPhysicsRotation() function");
385
386   ToolkitTestApplication application;
387   Matrix                 transform(false);
388   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 1.0f));
389   Uint16Pair     size(640, 480);
390   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
391   Actor          rootActor = adaptor.GetRootActor();
392   auto           scene     = application.GetScene();
393   scene.Add(rootActor);
394
395   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
396
397   cpBody*      body{nullptr};
398   PhysicsActor physicsActor;
399   {
400     auto accessor = adaptor.GetPhysicsAccessor();
401     auto space    = accessor->GetNative().Get<cpSpace*>();
402     body          = CreateBody(space);
403     physicsActor  = adaptor.AddActorBody(ballActor, body);
404     physicsActor.AsyncSetPhysicsRotation(Quaternion(Degree(30), Vector3::ZAXIS));
405   }
406
407   Test::WaitForEventThreadTrigger(1);
408   adaptor.CreateSyncPoint();
409   application.SendNotification();
410   application.Render();
411
412   // Run 2 frames to ensure both buffers are set.
413   application.SendNotification();
414   application.Render();
415   {
416     auto accessor = adaptor.GetPhysicsAccessor();
417     auto actor    = rootActor.FindChildById(physicsActor.GetId());
418     // Warning - physics properties are never reflected in the event size cache.
419     // Have to use GetCurrentProperty to see the updated values.
420     Quaternion q = actor.GetCurrentProperty<Quaternion>(Actor::Property::ORIENTATION);
421     Quaternion expected(Degree(30), Vector3::ZAXIS);
422     DALI_TEST_EQUALS(q, expected, 0.001f, TEST_LOCATION);
423   }
424
425   END_TEST;
426 }
427
428 int UtcDaliPhysics2DActorGetActorPosition(void)
429 {
430   tet_infoline("Test the GetActorPosition() function");
431
432   ToolkitTestApplication application;
433   Matrix                 transform(false);
434   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
435   Uint16Pair     size(640, 480);
436   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
437   Actor          rootActor = adaptor.GetRootActor();
438   auto           scene     = application.GetScene();
439   scene.Add(rootActor);
440
441   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
442
443   cpBody*      body{nullptr};
444   PhysicsActor physicsActor;
445   {
446     auto accessor = adaptor.GetPhysicsAccessor();
447     auto space    = accessor->GetNative().Get<cpSpace*>();
448     body          = CreateBody(space);
449     physicsActor  = adaptor.AddActorBody(ballActor, body);
450     tet_infoline("Test that Z is ignored");
451     physicsActor.AsyncSetPhysicsPosition(Vector3(10, 20, -30));
452   }
453
454   Test::WaitForEventThreadTrigger(1);
455   adaptor.CreateSyncPoint();
456   application.SendNotification();
457   application.Render();
458
459   // Run 2 frames to ensure both buffers are set.
460   application.SendNotification();
461   application.Render();
462   {
463     auto accessor = adaptor.GetPhysicsAccessor();
464     tet_infoline("Test that Z is ignored. Note, error is quite high, so make epsilon low");
465     DALI_TEST_EQUALS(physicsActor.GetActorPosition(), Vector3(10, 20, 0), 0.01f, TEST_LOCATION);
466   }
467
468   END_TEST;
469 }
470
471 int UtcDaliPhysics2DActorGetActorRotation(void)
472 {
473   tet_infoline("Test the GetActorRotation() function");
474
475   ToolkitTestApplication application;
476   Matrix                 transform(false);
477   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
478   Uint16Pair     size(640, 480);
479   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
480   Actor          rootActor = adaptor.GetRootActor();
481   auto           scene     = application.GetScene();
482   scene.Add(rootActor);
483
484   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
485
486   cpBody*      body{nullptr};
487   PhysicsActor physicsActor;
488   {
489     auto accessor = adaptor.GetPhysicsAccessor();
490     auto space    = accessor->GetNative().Get<cpSpace*>();
491     body          = CreateBody(space);
492     physicsActor  = adaptor.AddActorBody(ballActor, body);
493     physicsActor.AsyncSetPhysicsRotation(Quaternion(Degree(30), Vector3::ZAXIS));
494   }
495
496   Test::WaitForEventThreadTrigger(1);
497   adaptor.CreateSyncPoint();
498   application.SendNotification();
499   application.Render();
500
501   // Run 2 frames to ensure both buffers are set.
502   application.SendNotification();
503   application.Render();
504   {
505     auto accessor = adaptor.GetPhysicsAccessor();
506     DALI_TEST_EQUALS(physicsActor.GetActorRotation(), Quaternion(Degree(30), Vector3::ZAXIS), 0.0001f, TEST_LOCATION);
507   }
508
509   END_TEST;
510 }
511
512 int UtcDaliPhysics2DActorGetPhysicsPosition(void)
513 {
514   tet_infoline("Test the GetPhysicsPosition() function");
515
516   ToolkitTestApplication application;
517   Matrix                 transform(false);
518   transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
519
520   Uint16Pair     size(640, 480);
521   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
522   Actor          rootActor = adaptor.GetRootActor();
523   auto           scene     = application.GetScene();
524   scene.Add(rootActor);
525
526   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
527
528   cpBody*      body{nullptr};
529   PhysicsActor physicsActor;
530   {
531     auto accessor = adaptor.GetPhysicsAccessor();
532     auto space    = accessor->GetNative().Get<cpSpace*>();
533     body          = CreateBody(space);
534     physicsActor  = adaptor.AddActorBody(ballActor, body);
535     physicsActor.AsyncSetPhysicsPosition(Vector3(10, 20, -30));
536   }
537
538   Test::WaitForEventThreadTrigger(1);
539   adaptor.CreateSyncPoint();
540   application.SendNotification();
541   application.Render();
542
543   // Run 2 frames to ensure both buffers are set.
544   application.SendNotification();
545   application.Render();
546   {
547     auto    accessor = adaptor.GetPhysicsAccessor();
548     Vector4 pos      = transform * Vector4(10, 20, 0, 1);
549     DALI_TEST_EQUALS(physicsActor.GetPhysicsPosition(), Vector3(pos), 0.01f, TEST_LOCATION);
550   }
551
552   END_TEST;
553 }
554
555 int UtcDaliPhysics2DActorGetPhysicsRotation(void)
556 {
557   tet_infoline("Test the GetPhysicsRotation() function");
558
559   ToolkitTestApplication application;
560   Matrix                 transform(false);
561   transform.SetIdentityAndScale(Vector3(2.0f, -2.0f, 1.0f));
562   Uint16Pair     size(640, 480);
563   PhysicsAdaptor adaptor   = PhysicsAdaptor::New(transform, size);
564   Actor          rootActor = adaptor.GetRootActor();
565   auto           scene     = application.GetScene();
566   scene.Add(rootActor);
567
568   Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
569
570   cpBody*      body{nullptr};
571   PhysicsActor physicsActor;
572   {
573     auto accessor = adaptor.GetPhysicsAccessor();
574     auto space    = accessor->GetNative().Get<cpSpace*>();
575     body          = CreateBody(space);
576     physicsActor  = adaptor.AddActorBody(ballActor, body);
577     physicsActor.AsyncSetPhysicsRotation(Quaternion(Degree(30), Vector3::ZAXIS));
578   }
579
580   Test::WaitForEventThreadTrigger(1);
581   adaptor.CreateSyncPoint();
582   application.SendNotification();
583   application.Render();
584
585   // Run 2 frames to ensure both buffers are set.
586   application.SendNotification();
587   application.Render();
588   {
589     tet_infoline("Check that actor and physics rotations are identical");
590     auto accessor = adaptor.GetPhysicsAccessor();
591     DALI_TEST_EQUALS(physicsActor.GetPhysicsRotation(), Quaternion(Degree(30), Vector3::ZAXIS), 0.0001f, TEST_LOCATION);
592   }
593
594   END_TEST;
595 }