2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <chipmunk/chipmunk.h>
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>
26 #include <dali-physics/dali-physics.h>
27 #include <dali-toolkit/dali-toolkit.h>
28 #include <dali-toolkit/devel-api/controls/alignment/alignment.h>
31 using namespace Dali::Toolkit::Physics;
33 extern cpBody* CreateBody(cpSpace* space);
35 const char* BALL_IMAGE = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
37 int UtcDaliPhysics2DActorNew(void)
39 ToolkitTestApplication application;
41 cpBody* body{nullptr};
43 Matrix transform(true);
44 Uint16Pair size(640, 480);
45 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
52 PhysicsActor physicsActor = PhysicsActor::New(ballActor, body, adaptor);
54 DALI_TEST_CHECK(physicsActor);
58 int UtcDaliPhysics2DActorDownCastP(void)
60 ToolkitTestApplication application;
62 Matrix transform(true);
63 Uint16Pair size(640, 480);
64 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
74 PhysicsActor actor2 = PhysicsActor::DownCast(handle);
75 DALI_TEST_CHECK(actor2);
76 DALI_TEST_EQUALS(physicsActor.GetId(), actor2.GetId(), TEST_LOCATION);
81 int UtcDaliPhysics2DActorDownCastN(void)
83 BaseHandle uninitializedHandle;
84 PhysicsActor actor = PhysicsActor::DownCast(uninitializedHandle);
85 DALI_TEST_CHECK(!actor);
89 int UtcDaliPhysics2DActorMoveConstructor(void)
91 ToolkitTestApplication application;
92 tet_infoline("Testing the move constructor");
94 Matrix transform(true);
95 Uint16Pair size(640, 480);
96 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
105 DALI_TEST_CHECK(physicsActor);
106 uint32_t id = physicsActor.GetId();
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);
117 int UtcDaliPhysics2DActorCopyConstructor(void)
119 ToolkitTestApplication application;
120 tet_infoline("Testing the move constructor");
122 Matrix transform(true);
123 Uint16Pair size(640, 480);
124 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
133 DALI_TEST_CHECK(physicsActor);
134 uint32_t id = physicsActor.GetId();
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);
145 int UtcDaliPhysics2DActorCopyAssign(void)
147 ToolkitTestApplication application;
148 tet_infoline("Testing the copy assign");
150 Matrix transform(true);
151 Uint16Pair size(640, 480);
152 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
161 DALI_TEST_CHECK(physicsActor);
162 uint32_t id = physicsActor.GetId();
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);
173 int UtcDaliPhysics2DActorMoveAssignment(void)
175 ToolkitTestApplication application;
176 tet_infoline("Testing the move constructor");
178 Matrix transform(true);
179 Uint16Pair size(640, 480);
180 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
189 DALI_TEST_CHECK(physicsActor);
190 uint32_t id = physicsActor.GetId();
193 moved = std::move(physicsActor);
194 DALI_TEST_CHECK(moved);
195 DALI_TEST_CHECK(!physicsActor);
196 DALI_TEST_EQUALS(moved.GetId(), id, TEST_LOCATION);
201 int UtcDaliPhysics2DActorGetIdP(void)
203 ToolkitTestApplication application;
204 tet_infoline("Testing the ID Getter");
206 Matrix transform(true);
207 Uint16Pair size(640, 480);
208 PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
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);
223 int UtcDaliPhysics2DActorGetIdN(void)
225 ToolkitTestApplication application;
226 tet_infoline("Testing the ID Getter");
228 PhysicsActor physicsActor;
231 uint32_t id __attribute__((unused)) = physicsActor.GetId();
232 tet_result(TET_FAIL);
234 catch(DaliException e)
236 DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
242 int UtcDaliPhysics2DActorGetBodyP(void)
244 ToolkitTestApplication application;
245 tet_infoline("Testing the body Getter");
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);
254 PhysicsActor physicsActor;
255 cpBody* body{nullptr};
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);
262 physicsActor = adaptor.AddActorBody(ballActor, body);
265 application.Render();
266 Test::WaitForEventThreadTrigger(1);
268 Dali::Any any = physicsActor.GetBody();
269 DALI_TEST_EQUALS(any.Get<cpBody*>(), body, TEST_LOCATION);
274 int UtcDaliPhysics2DActorGetBodyN(void)
276 ToolkitTestApplication application;
277 tet_infoline("Testing the ID Getter");
279 PhysicsActor physicsActor;
282 Dali::Any any __attribute__((unused)) = physicsActor.GetBody();
283 tet_result(TET_FAIL);
285 catch(DaliException e)
287 DALI_TEST_ASSERT(e, "Physics actor handle is empty", TEST_LOCATION);
292 int UtcDaliPhysics2DActorSetPosition(void)
294 tet_infoline("Test the AsyncSetPhysicsPosition() function");
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);
305 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
307 cpBody* body{nullptr};
308 PhysicsActor physicsActor;
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));
317 Test::WaitForEventThreadTrigger(1);
318 adaptor.CreateSyncPoint();
319 application.SendNotification();
320 application.Render();
322 // Run 2 frames to ensure both buffers are set.
323 application.SendNotification();
324 application.Render();
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);
336 int UtcDaliPhysics2DActorSetRotation1(void)
338 tet_infoline("Test the AsyncSetPhysicsRotation() function");
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);
349 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
351 cpBody* body{nullptr};
352 PhysicsActor physicsActor;
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));
361 Test::WaitForEventThreadTrigger(1);
362 adaptor.CreateSyncPoint();
363 application.SendNotification();
364 application.Render();
366 // Run 2 frames to ensure both buffers are set.
367 application.SendNotification();
368 application.Render();
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);
382 int UtcDaliPhysics2DActorSetRotation2(void)
384 tet_infoline("Test the AsyncSetPhysicsRotation() function");
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);
395 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
397 cpBody* body{nullptr};
398 PhysicsActor physicsActor;
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));
407 Test::WaitForEventThreadTrigger(1);
408 adaptor.CreateSyncPoint();
409 application.SendNotification();
410 application.Render();
412 // Run 2 frames to ensure both buffers are set.
413 application.SendNotification();
414 application.Render();
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);
428 int UtcDaliPhysics2DActorGetActorPosition(void)
430 tet_infoline("Test the GetActorPosition() function");
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);
441 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
443 cpBody* body{nullptr};
444 PhysicsActor physicsActor;
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));
454 Test::WaitForEventThreadTrigger(1);
455 adaptor.CreateSyncPoint();
456 application.SendNotification();
457 application.Render();
459 // Run 2 frames to ensure both buffers are set.
460 application.SendNotification();
461 application.Render();
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);
471 int UtcDaliPhysics2DActorGetActorRotation(void)
473 tet_infoline("Test the GetActorRotation() function");
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);
484 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
486 cpBody* body{nullptr};
487 PhysicsActor physicsActor;
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));
496 Test::WaitForEventThreadTrigger(1);
497 adaptor.CreateSyncPoint();
498 application.SendNotification();
499 application.Render();
501 // Run 2 frames to ensure both buffers are set.
502 application.SendNotification();
503 application.Render();
505 auto accessor = adaptor.GetPhysicsAccessor();
506 DALI_TEST_EQUALS(physicsActor.GetActorRotation(), Quaternion(Degree(30), Vector3::ZAXIS), 0.0001f, TEST_LOCATION);
512 int UtcDaliPhysics2DActorGetPhysicsPosition(void)
514 tet_infoline("Test the GetPhysicsPosition() function");
516 ToolkitTestApplication application;
517 Matrix transform(false);
518 transform.SetIdentityAndScale(Vector3(2.0f, 2.0f, 2.0f));
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);
526 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
528 cpBody* body{nullptr};
529 PhysicsActor physicsActor;
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));
538 Test::WaitForEventThreadTrigger(1);
539 adaptor.CreateSyncPoint();
540 application.SendNotification();
541 application.Render();
543 // Run 2 frames to ensure both buffers are set.
544 application.SendNotification();
545 application.Render();
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);
555 int UtcDaliPhysics2DActorGetPhysicsRotation(void)
557 tet_infoline("Test the GetPhysicsRotation() function");
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);
568 Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
570 cpBody* body{nullptr};
571 PhysicsActor physicsActor;
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));
580 Test::WaitForEventThreadTrigger(1);
581 adaptor.CreateSyncPoint();
582 application.SendNotification();
583 application.Render();
585 // Run 2 frames to ensure both buffers are set.
586 application.SendNotification();
587 application.Render();
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);