Merge "Updated FrameCallback to return value to specify whether we should keep render...
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-FrameCallbackInterface.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
18 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/actors/actor-devel.h>
20 #include <dali/devel-api/common/map-wrapper.h>
21 #include <dali/devel-api/common/stage-devel.h>
22 #include <dali/devel-api/update/frame-callback-interface.h>
23 #include <dali/devel-api/update/update-proxy.h>
24 #include <dali/public-api/dali-core.h>
25 #include <stdlib.h>
26
27 #include <iostream>
28
29 using namespace Dali;
30
31 void utc_dali_frame_callback_interface_startup(void)
32 {
33   test_return_value = TET_UNDEF;
34 }
35
36 void utc_dali_frame_callback_interface_cleanup(void)
37 {
38   test_return_value = TET_PASS;
39 }
40
41 ///////////////////////////////////////////////////////////////////////////////
42 namespace
43 {
44 class FrameCallbackBasic : public FrameCallbackInterface
45 {
46 public:
47   FrameCallbackBasic() = default;
48
49   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds)
50   {
51     mCalled = true;
52     return false;
53   }
54
55   virtual void Reset()
56   {
57     mCalled = false;
58   }
59
60   bool mCalled{false};
61 };
62
63 class FrameCallbackOneActor : public FrameCallbackBasic
64 {
65 public:
66   FrameCallbackOneActor(unsigned int actorId)
67   : mActorId(actorId)
68   {
69   }
70
71   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
72   {
73     FrameCallbackBasic::Update(updateProxy, elapsedSeconds);
74     updateProxy.GetPosition(mActorId, mPositionGetPositionCall);
75     updateProxy.GetPositionAndSize(mActorId, mPositionGetPositionAndSizeCall, mSizeGetPositionAndSizeCall);
76     updateProxy.GetSize(mActorId, mSizeGetSizeCall);
77     updateProxy.GetOrientation(mActorId, mOrientation);
78     updateProxy.GetColor(mActorId, mColor);
79     updateProxy.GetScale(mActorId, mScale);
80
81     updateProxy.GetWorldPositionScaleAndSize(mActorId, mWorldPosition, mWorldScale, mSizeGetWorldPositionAndSizeCall);
82     updateProxy.GetWorldTransformAndSize(mActorId, mWorldTransformPosition, mWorldTransformScale, mWorldTransformOrientation, mSizeGetWorldTransform);
83
84     return false;
85   }
86
87   const unsigned int mActorId;
88
89   Vector3    mPositionGetPositionCall;
90   Vector3    mPositionGetPositionAndSizeCall;
91   Vector3    mSizeGetSizeCall;
92   Vector3    mSizeGetPositionAndSizeCall;
93   Vector4    mColor;
94   Vector3    mScale;
95   Quaternion mOrientation;
96
97   Vector3 mWorldPosition;
98   Vector3 mWorldScale;
99   Vector3 mSizeGetWorldPositionAndSizeCall;
100
101   Vector3    mWorldTransformPosition;
102   Vector3    mWorldTransformScale;
103   Quaternion mWorldTransformOrientation;
104   Vector3    mSizeGetWorldTransform;
105 };
106
107 class FrameCallbackSetter : public FrameCallbackBasic
108 {
109 public:
110   FrameCallbackSetter(
111     unsigned int      actorId,
112     const Vector3&    sizeToSet,
113     const Vector3&    positionToSet,
114     const Vector4&    colorToSet,
115     const Vector3&    scaleToSet,
116     const Quaternion& orientationToSet)
117   : mActorId(actorId),
118     mSizeToSet(sizeToSet),
119     mPositionToSet(positionToSet),
120     mColorToSet(colorToSet),
121     mScaleToSet(scaleToSet),
122     mOrientationToSet(orientationToSet)
123   {
124   }
125
126   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
127   {
128     Vector3 size;
129     FrameCallbackBasic::Update(updateProxy, elapsedSeconds);
130     updateProxy.SetSize(mActorId, mSizeToSet);
131     updateProxy.SetPosition(mActorId, mPositionToSet);
132     updateProxy.SetOrientation(mActorId, mOrientationToSet);
133     updateProxy.SetColor(mActorId, mColorToSet);
134     updateProxy.SetScale(mActorId, mScaleToSet);
135     updateProxy.GetSize(mActorId, mSizeAfterSetting);
136     updateProxy.GetPosition(mActorId, mPositionAfterSetting);
137     updateProxy.GetColor(mActorId, mColorAfterSetting);
138     updateProxy.GetScale(mActorId, mScaleAfterSetting);
139     updateProxy.GetOrientation(mActorId, mOrientationAfterSetting);
140
141     return false;
142   }
143
144   const unsigned int mActorId;
145   const Vector3&     mSizeToSet;
146   const Vector3&     mPositionToSet;
147   const Vector4&     mColorToSet;
148   const Vector3&     mScaleToSet;
149   const Quaternion&  mOrientationToSet;
150
151   Vector3    mSizeAfterSetting;
152   Vector3    mPositionAfterSetting;
153   Vector4    mColorAfterSetting;
154   Vector3    mScaleAfterSetting;
155   Quaternion mOrientationAfterSetting;
156 };
157
158 class FrameCallbackBaker : public FrameCallbackBasic
159 {
160 public:
161   FrameCallbackBaker(
162     unsigned int      actorId,
163     const Vector3&    sizeToSet,
164     const Vector3&    positionToSet,
165     const Vector4&    colorToSet,
166     const Vector3&    scaleToSet,
167     const Quaternion& orientationToSet)
168   : mActorId(actorId),
169     mSizeToSet(sizeToSet),
170     mPositionToSet(positionToSet),
171     mColorToSet(colorToSet),
172     mScaleToSet(scaleToSet),
173     mOrientationToSet(orientationToSet)
174   {
175   }
176
177   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
178   {
179     Vector3 size;
180     FrameCallbackBasic::Update(updateProxy, elapsedSeconds);
181     updateProxy.BakeSize(mActorId, mSizeToSet);
182     updateProxy.BakePosition(mActorId, mPositionToSet);
183     updateProxy.BakeColor(mActorId, mColorToSet);
184     updateProxy.BakeScale(mActorId, mScaleToSet);
185     updateProxy.BakeOrientation(mActorId, mOrientationToSet);
186     updateProxy.GetSize(mActorId, mSizeAfterSetting);
187     updateProxy.GetPosition(mActorId, mPositionAfterSetting);
188     updateProxy.GetColor(mActorId, mColorAfterSetting);
189     updateProxy.GetScale(mActorId, mScaleAfterSetting);
190     updateProxy.GetOrientation(mActorId, mOrientationAfterSetting);
191
192     return false;
193   }
194
195   const unsigned int mActorId;
196   const Vector3&     mSizeToSet;
197   const Vector3&     mPositionToSet;
198   const Vector4&     mColorToSet;
199   const Vector3&     mScaleToSet;
200   const Quaternion&  mOrientationToSet;
201
202   Vector3    mSizeAfterSetting;
203   Vector3    mPositionAfterSetting;
204   Vector4    mColorAfterSetting;
205   Vector3    mScaleAfterSetting;
206   Quaternion mOrientationAfterSetting;
207 };
208
209 class FrameCallbackMultipleActors : public FrameCallbackBasic
210 {
211 public:
212   FrameCallbackMultipleActors()
213   {
214   }
215
216   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
217   {
218     FrameCallbackBasic::Update(updateProxy, elapsedSeconds);
219     for(auto&& i : mActorIds)
220     {
221       Vector3 position;
222       Vector3 size;
223       updateProxy.GetPositionAndSize(i, position, size);
224       mPositions[i] = position;
225       mSizes[i]     = size;
226     }
227
228     return false;
229   }
230
231   Vector<unsigned int> mActorIds;
232
233   std::map<unsigned int, Vector3> mPositions;
234   std::map<unsigned int, Vector3> mSizes;
235 };
236
237 class FrameCallbackActorIdCheck : public FrameCallbackBasic
238 {
239 public:
240   FrameCallbackActorIdCheck(unsigned int actorId)
241   : mActorId(actorId)
242   {
243   }
244
245   virtual bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
246   {
247     FrameCallbackBasic::Update(updateProxy, elapsedSeconds);
248     Vector3    vec3;
249     Vector4    vec4;
250     Quaternion quat;
251
252     mGetSizeCallSuccess                      = updateProxy.GetSize(mActorId, vec3);
253     mGetPositionCallSuccess                  = updateProxy.GetPosition(mActorId, vec3);
254     mGetColorCallSuccess                     = updateProxy.GetColor(mActorId, vec4);
255     mGetScaleCallSuccess                     = updateProxy.GetScale(mActorId, vec3);
256     mGetPositionAndSizeCallSuccess           = updateProxy.GetPositionAndSize(mActorId, vec3, vec3);
257     mGetWorldPositionScaleAndSizeCallSuccess = updateProxy.GetWorldPositionScaleAndSize(mActorId, vec3, vec3, vec3);
258     mSetSizeCallSuccess                      = updateProxy.SetSize(mActorId, vec3);
259     mSetPositionCallSuccess                  = updateProxy.SetPosition(mActorId, vec3);
260     mSetColorCallSuccess                     = updateProxy.SetColor(mActorId, vec4);
261     mSetScaleCallSuccess                     = updateProxy.SetScale(mActorId, vec3);
262     mBakeSizeCallSuccess                     = updateProxy.BakeSize(mActorId, vec3);
263     mBakePositionCallSuccess                 = updateProxy.BakePosition(mActorId, vec3);
264     mBakeColorCallSuccess                    = updateProxy.BakeColor(mActorId, vec4);
265     mBakeScaleCallSuccess                    = updateProxy.BakeScale(mActorId, vec3);
266
267     mGetOrientationCallSuccess    = updateProxy.GetOrientation(mActorId, quat);
268     mSetOrientationCallSuccess    = updateProxy.SetOrientation(mActorId, quat);
269     mBakeOrientationCallSuccess   = updateProxy.BakeOrientation(mActorId, quat);
270     mGetWorldTransformCallSuccess = updateProxy.GetWorldTransformAndSize(mActorId, vec3, vec3, quat, vec3);
271
272     return false;
273   }
274
275   virtual void Reset() override
276   {
277     // Up-call
278     FrameCallbackBasic::Reset();
279
280     mGetSizeCallSuccess                      = false;
281     mGetPositionCallSuccess                  = false;
282     mGetColorCallSuccess                     = false;
283     mGetScaleCallSuccess                     = false;
284     mGetPositionAndSizeCallSuccess           = false;
285     mGetWorldPositionScaleAndSizeCallSuccess = false;
286     mSetSizeCallSuccess                      = false;
287     mSetPositionCallSuccess                  = false;
288     mSetColorCallSuccess                     = false;
289     mSetScaleCallSuccess                     = false;
290     mBakeSizeCallSuccess                     = false;
291     mBakePositionCallSuccess                 = false;
292     mBakeColorCallSuccess                    = false;
293     mBakeScaleCallSuccess                    = false;
294
295     mSetOrientationCallSuccess  = false;
296     mGetOrientationCallSuccess  = false;
297     mBakeOrientationCallSuccess = false;
298
299     mGetWorldTransformCallSuccess = false;
300   }
301
302   const uint32_t mActorId;
303
304   bool mGetSizeCallSuccess{false};
305   bool mGetPositionCallSuccess{false};
306   bool mGetOrientationCallSuccess{false};
307   bool mGetColorCallSuccess{false};
308   bool mGetScaleCallSuccess{false};
309   bool mGetPositionAndSizeCallSuccess{false};
310   bool mGetWorldPositionScaleAndSizeCallSuccess{false};
311   bool mSetSizeCallSuccess{false};
312   bool mSetPositionCallSuccess{false};
313   bool mSetColorCallSuccess{false};
314   bool mSetScaleCallSuccess{false};
315   bool mSetOrientationCallSuccess{false};
316   bool mBakeSizeCallSuccess{false};
317   bool mBakePositionCallSuccess{false};
318   bool mBakeColorCallSuccess{false};
319   bool mBakeScaleCallSuccess{false};
320   bool mBakeOrientationCallSuccess{false};
321   bool mGetWorldTransformCallSuccess{false};
322 };
323
324 } // namespace
325
326 ///////////////////////////////////////////////////////////////////////////////
327
328 int UtcDaliFrameCallbackCheckInstallationAndRemoval(void)
329 {
330   // Basic test to check that the frame-callback can be installed and removed correctly
331
332   TestApplication application;
333
334   FrameCallbackBasic frameCallback;
335
336   Stage stage = Stage::GetCurrent();
337   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
338
339   application.SendNotification();
340   application.Render();
341
342   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
343
344   frameCallback.mCalled = false;
345
346   DevelStage::RemoveFrameCallback(stage, frameCallback);
347
348   application.SendNotification();
349   application.Render();
350
351   DALI_TEST_EQUALS(frameCallback.mCalled, false, TEST_LOCATION);
352
353   END_TEST;
354 }
355
356 int UtcDaliFrameCallbackGetters(void)
357 {
358   // Test to see that the Getters all return the expected values
359
360   TestApplication application;
361
362   Vector2    actorSize(200, 300);
363   Vector4    color(0.5f, 0.6f, 0.7f, 0.8f);
364   Vector3    position(10.0f, 20.0f, 30.0f);
365   Vector3    scale(2.0f, 4.0f, 6.0f);
366   Quaternion orientation; //(Radian(Math::PI_2), Vector3::ZAXIS);
367   Actor      actor = Actor::New();
368   actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
369   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
370   actor.SetProperty(Actor::Property::SIZE, actorSize);
371   actor.SetProperty(Actor::Property::COLOR, color);
372   actor.SetProperty(Actor::Property::POSITION, position);
373   actor.SetProperty(Actor::Property::SCALE, scale);
374   actor.SetProperty(Actor::Property::ORIENTATION, orientation);
375
376   Stage stage = Stage::GetCurrent();
377   stage.Add(actor);
378
379   FrameCallbackOneActor frameCallback(actor.GetProperty<int>(Actor::Property::ID));
380   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
381
382   application.SendNotification();
383   application.Render();
384
385   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
386   DALI_TEST_EQUALS(frameCallback.mSizeGetSizeCall, Vector3(actorSize.width, actorSize.height, 0.0f), TEST_LOCATION);
387   DALI_TEST_EQUALS(frameCallback.mPositionGetPositionCall, position, TEST_LOCATION);
388   DALI_TEST_EQUALS(frameCallback.mPositionGetPositionAndSizeCall, position, TEST_LOCATION);
389   DALI_TEST_EQUALS(frameCallback.mSizeGetPositionAndSizeCall, Vector3(actorSize.width, actorSize.height, 0.0f), TEST_LOCATION);
390
391   DALI_TEST_EQUALS(frameCallback.mColor, color, TEST_LOCATION);
392   DALI_TEST_EQUALS(frameCallback.mScale, scale, TEST_LOCATION);
393   DALI_TEST_EQUALS(frameCallback.mOrientation, orientation, TEST_LOCATION);
394
395   frameCallback.Reset();
396
397   application.SendNotification();
398   application.Render();
399
400   Vector3    worldPosition, worldScale;
401   Quaternion worldRotation;
402   Matrix     worldTransform = DevelActor::GetWorldTransform(actor);
403   worldTransform.GetTransformComponents(worldPosition, worldRotation, worldScale);
404
405   // World position and scale values are updated after FrameCallbackInterface::Update()
406   // So test them after the second rendering
407   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
408
409   DALI_TEST_EQUALS(frameCallback.mSizeGetWorldTransform, Vector3(actorSize.width, actorSize.height, 0.0f), TEST_LOCATION);
410   DALI_TEST_EQUALS(frameCallback.mWorldPosition, worldPosition, TEST_LOCATION);
411   DALI_TEST_EQUALS(frameCallback.mWorldScale, worldScale, TEST_LOCATION);
412   DALI_TEST_EQUALS(frameCallback.mSizeGetWorldPositionAndSizeCall, Vector3(actorSize), TEST_LOCATION);
413   DALI_TEST_EQUALS(frameCallback.mWorldTransformPosition, worldPosition, TEST_LOCATION);
414   DALI_TEST_EQUALS(frameCallback.mWorldTransformScale, worldScale, TEST_LOCATION);
415   DALI_TEST_EQUALS(frameCallback.mWorldTransformOrientation, worldRotation, TEST_LOCATION);
416
417   END_TEST;
418 }
419
420 int UtcDaliFrameCallbackSetters(void)
421 {
422   // Test to see that the setters set the values appropriately
423
424   TestApplication application;
425   Vector2         actorSize(200, 300);
426
427   Actor actor = Actor::New();
428   actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
429   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
430   actor.SetProperty(Actor::Property::SIZE, actorSize);
431
432   Stage stage = Stage::GetCurrent();
433   stage.Add(actor);
434
435   Vector3    sizeToSet(1.0f, 2.0f, 3.0f);
436   Vector3    positionToSet(10.0f, 20.0f, 30.0f);
437   Vector4    colorToSet(Color::MAGENTA);
438   Vector3    scaleToSet(1.0f, 3.0f, 5.0f);
439   Quaternion orientationToSet(Radian(Math::PI_2), Vector3::ZAXIS);
440
441   FrameCallbackSetter frameCallback(actor.GetProperty<int>(Actor::Property::ID), sizeToSet, positionToSet, colorToSet, scaleToSet, orientationToSet);
442   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
443
444   application.SendNotification();
445   application.Render();
446
447   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
448   DALI_TEST_EQUALS(frameCallback.mSizeAfterSetting, sizeToSet, TEST_LOCATION);
449   DALI_TEST_EQUALS(frameCallback.mPositionAfterSetting, positionToSet, TEST_LOCATION);
450   DALI_TEST_EQUALS(frameCallback.mColorAfterSetting, colorToSet, TEST_LOCATION);
451   DALI_TEST_EQUALS(frameCallback.mScaleAfterSetting, scaleToSet, TEST_LOCATION);
452   DALI_TEST_EQUALS(frameCallback.mOrientationAfterSetting, orientationToSet, TEST_LOCATION);
453
454   // Ensure the actual actor values haven't changed as we didn't bake the values after removing the callback
455   DevelStage::RemoveFrameCallback(stage, frameCallback);
456
457   application.SendNotification();
458   application.Render();
459
460   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), Vector3::ZERO, TEST_LOCATION);
461   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SIZE).Get<Vector3>(), Vector3(actorSize), TEST_LOCATION);
462   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::COLOR).Get<Vector4>(), Color::WHITE, TEST_LOCATION);
463   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3::ONE, TEST_LOCATION);
464   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::ORIENTATION).Get<Quaternion>(), Quaternion(Radian(0.0f), Vector3::ZAXIS), TEST_LOCATION);
465
466   // Render for a couple more frames to ensure the values are reset properly (some values are double-buffered)
467
468   application.SendNotification();
469   application.Render();
470
471   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), Vector3::ZERO, TEST_LOCATION);
472   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SIZE).Get<Vector3>(), Vector3(actorSize), TEST_LOCATION);
473   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::COLOR).Get<Vector4>(), Color::WHITE, TEST_LOCATION);
474   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3::ONE, TEST_LOCATION);
475   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::ORIENTATION).Get<Quaternion>(), Quaternion(Radian(0.0f), Vector3::ZAXIS), TEST_LOCATION);
476
477   application.SendNotification();
478   application.Render();
479
480   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), Vector3::ZERO, TEST_LOCATION);
481   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SIZE).Get<Vector3>(), Vector3(actorSize), TEST_LOCATION);
482   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::COLOR).Get<Vector4>(), Color::WHITE, TEST_LOCATION);
483   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3::ONE, TEST_LOCATION);
484   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::ORIENTATION).Get<Quaternion>(), Quaternion(Radian(0.0f), Vector3::ZAXIS), TEST_LOCATION);
485
486   END_TEST;
487 }
488
489 int UtcDaliFrameCallbackBake(void)
490 {
491   // Test to see that the bake methods bake the values
492
493   TestApplication application;
494   Vector2         actorSize(200, 300);
495
496   Actor actor = Actor::New();
497   actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
498   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
499   actor.SetProperty(Actor::Property::SIZE, actorSize);
500
501   Stage stage = Stage::GetCurrent();
502   stage.Add(actor);
503
504   Vector3    sizeToSet(1.0f, 2.0f, 3.0f);
505   Vector3    positionToSet(10.0f, 20.0f, 30.0f);
506   Vector4    colorToSet(Color::MAGENTA);
507   Vector3    scaleToSet(1.0f, 3.0f, 5.0f);
508   Quaternion orientationToSet(Radian(Math::PI * 0.3), Vector3::YAXIS);
509
510   FrameCallbackBaker frameCallback(actor.GetProperty<int>(Actor::Property::ID), sizeToSet, positionToSet, colorToSet, scaleToSet, orientationToSet);
511   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
512
513   application.SendNotification();
514   application.Render();
515
516   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
517   DALI_TEST_EQUALS(frameCallback.mSizeAfterSetting, sizeToSet, TEST_LOCATION);
518   DALI_TEST_EQUALS(frameCallback.mPositionAfterSetting, positionToSet, TEST_LOCATION);
519   DALI_TEST_EQUALS(frameCallback.mColorAfterSetting, colorToSet, TEST_LOCATION);
520   DALI_TEST_EQUALS(frameCallback.mScaleAfterSetting, scaleToSet, TEST_LOCATION);
521   DALI_TEST_EQUALS(frameCallback.mOrientationAfterSetting, orientationToSet, TEST_LOCATION);
522
523   // Ensure the new values are saved after removing the callback
524   DevelStage::RemoveFrameCallback(stage, frameCallback);
525
526   application.SendNotification();
527   application.Render();
528
529   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), positionToSet, TEST_LOCATION);
530   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SIZE).Get<Vector3>(), sizeToSet, TEST_LOCATION);
531   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::COLOR).Get<Vector4>(), colorToSet, TEST_LOCATION);
532   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::SCALE).Get<Vector3>(), scaleToSet, TEST_LOCATION);
533   DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::ORIENTATION).Get<Quaternion>(), orientationToSet, TEST_LOCATION);
534
535   END_TEST;
536 }
537
538 int UtcDaliFrameCallbackMultipleActors(void)
539 {
540   /**
541    * Test to check that the frame callback behaves appropriately with multiple actors
542    *
543    * Tree:
544    *              root-layer
545    *              /        \
546    *             /          \
547    *            /            \
548    *           /              \
549    *        actorA           actorE
550    *         / \              / \
551    *        /   \            /   \
552    *    actorB  actorD   actorF actorG
553    *      /                        \
554    *   actorC                     actorH
555    *
556    *  Screen positions (with minor alterations due to local position):
557    *  -----------------------
558    *  |actorA|actorD        |
559    *  |      actorB         |
560    *  |      actorC         |
561    *  |                     |
562    *  |                     |
563    *  |                     |
564    *  |                     |
565    *  |                     |
566    *  |actorF       actorH  |
567    *  |actorE|actorG        |
568    *  -----------------------
569    */
570
571   TestApplication application;
572   Stage           stage = Stage::GetCurrent();
573
574   std::map<char, Vector3> sizes;
575   sizes['A'] = Vector3(50.0f, 50.0f, 0.0f);
576   sizes['B'] = Vector3(100.0f, 100.0f, 0.0f);
577   sizes['C'] = Vector3(150.0f, 150.0f, 0.0f);
578   sizes['D'] = Vector3(200.0f, 200.0f, 0.0f);
579   sizes['E'] = Vector3(250.0f, 250.0f, 0.0f);
580   sizes['F'] = Vector3(300.0f, 300.0f, 0.0f);
581   sizes['G'] = Vector3(350.0f, 350.0f, 0.0f);
582   sizes['H'] = Vector3(400.0f, 350.0f, 0.0f);
583
584   std::map<char, Vector3> positions;
585   positions['A'] = Vector3(0.0f, 1.0f, 2.0f);
586   positions['B'] = Vector3(2.0f, 3.0f, 4.0f);
587   positions['C'] = Vector3(5.0f, 6.0f, 7.0f);
588   positions['D'] = Vector3(8.0f, 9.0f, 10.0f);
589   positions['E'] = Vector3(11.0f, 12.0f, 13.0f);
590   positions['F'] = Vector3(14.0f, 15.0f, 16.0f);
591   positions['G'] = Vector3(17.0f, 18.0f, 19.0f);
592   positions['H'] = Vector3(20.0f, 21.0f, 22.0f);
593
594   Actor actorA = Actor::New();
595   actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
596   actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
597   actorA.SetProperty(Actor::Property::SIZE, sizes['A']);
598   actorA.SetProperty(Actor::Property::POSITION, positions['A']);
599   stage.Add(actorA);
600
601   Actor actorB = Actor::New();
602   actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_RIGHT);
603   actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
604   actorB.SetProperty(Actor::Property::SIZE, sizes['B']);
605   actorB.SetProperty(Actor::Property::POSITION, positions['B']);
606   actorA.Add(actorB);
607
608   Actor actorC = Actor::New();
609   actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
610   actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
611   actorC.SetProperty(Actor::Property::SIZE, sizes['C']);
612   actorC.SetProperty(Actor::Property::POSITION, positions['C']);
613   actorB.Add(actorC);
614
615   Actor actorD = Actor::New();
616   actorD.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_RIGHT);
617   actorD.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
618   actorD.SetProperty(Actor::Property::SIZE, sizes['D']);
619   actorD.SetProperty(Actor::Property::POSITION, positions['D']);
620   actorA.Add(actorD);
621
622   Actor actorE = Actor::New();
623   actorE.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
624   actorE.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT);
625   actorE.SetProperty(Actor::Property::SIZE, sizes['E']);
626   actorE.SetProperty(Actor::Property::POSITION, positions['E']);
627   stage.Add(actorE);
628
629   Actor actorF = Actor::New();
630   actorF.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
631   actorF.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
632   actorF.SetProperty(Actor::Property::SIZE, sizes['F']);
633   actorF.SetProperty(Actor::Property::POSITION, positions['F']);
634   actorE.Add(actorF);
635
636   Actor actorG = Actor::New();
637   actorG.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_RIGHT);
638   actorG.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
639   actorG.SetProperty(Actor::Property::SIZE, sizes['G']);
640   actorG.SetProperty(Actor::Property::POSITION, positions['G']);
641   actorE.Add(actorG);
642
643   Actor actorH = Actor::New();
644   actorH.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT);
645   actorH.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT);
646   actorH.SetProperty(Actor::Property::SIZE, sizes['H']);
647   actorH.SetProperty(Actor::Property::POSITION, positions['H']);
648   actorG.Add(actorH);
649
650   std::map<char, unsigned int> actorIds;
651   actorIds['A'] = actorA.GetProperty<int>(Actor::Property::ID);
652   actorIds['B'] = actorB.GetProperty<int>(Actor::Property::ID);
653   actorIds['C'] = actorC.GetProperty<int>(Actor::Property::ID);
654   actorIds['D'] = actorD.GetProperty<int>(Actor::Property::ID);
655   actorIds['E'] = actorE.GetProperty<int>(Actor::Property::ID);
656   actorIds['F'] = actorF.GetProperty<int>(Actor::Property::ID);
657   actorIds['G'] = actorG.GetProperty<int>(Actor::Property::ID);
658   actorIds['H'] = actorH.GetProperty<int>(Actor::Property::ID);
659
660   FrameCallbackMultipleActors frameCallback;
661   for(auto&& i : actorIds)
662   {
663     frameCallback.mActorIds.PushBack(i.second);
664   }
665
666   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
667
668   application.SendNotification();
669   application.Render();
670
671   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
672
673   for(char i = 'A'; i <= 'H'; ++i)
674   {
675     DALI_TEST_EQUALS(frameCallback.mPositions[actorIds[i]], positions[i], TEST_LOCATION);
676     DALI_TEST_EQUALS(frameCallback.mSizes[actorIds[i]], sizes[i], TEST_LOCATION);
677   }
678
679   // Render again to make sure it still gets called and gives the correct values (in case any optimisations break this)
680   frameCallback.mCalled = false;
681
682   application.SendNotification();
683   application.Render();
684
685   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
686
687   for(char i = 'A'; i <= 'H'; ++i)
688   {
689     DALI_TEST_EQUALS(frameCallback.mPositions[actorIds[i]], positions[i], TEST_LOCATION);
690     DALI_TEST_EQUALS(frameCallback.mSizes[actorIds[i]], sizes[i], TEST_LOCATION);
691   }
692
693   END_TEST;
694 }
695
696 int UtcDaliFrameCallbackCheckActorNotAdded(void)
697 {
698   TestApplication application;
699
700   Actor actor = Actor::New();
701   actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
702   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
703   actor.SetProperty(Actor::Property::SIZE, Vector2(200, 300));
704
705   Stage                 stage = Stage::GetCurrent();
706   FrameCallbackOneActor frameCallback(actor.GetProperty<int>(Actor::Property::ID));
707   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
708
709   application.SendNotification();
710   application.Render();
711
712   // All should be default constructed objects
713   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
714   DALI_TEST_EQUALS(frameCallback.mPositionGetPositionCall, Vector3::ZERO, TEST_LOCATION);
715   DALI_TEST_EQUALS(frameCallback.mWorldPosition, Vector3::ZERO, TEST_LOCATION);
716   DALI_TEST_EQUALS(frameCallback.mSizeGetSizeCall, Vector3::ZERO, TEST_LOCATION);
717   DALI_TEST_EQUALS(frameCallback.mColor, Vector4::ZERO, TEST_LOCATION);
718   DALI_TEST_EQUALS(frameCallback.mScale, Vector3::ZERO, TEST_LOCATION);
719   DALI_TEST_EQUALS(frameCallback.mWorldScale, Vector3::ZERO, TEST_LOCATION);
720   DALI_TEST_EQUALS(frameCallback.mOrientation, Quaternion::IDENTITY, TEST_LOCATION);
721
722   END_TEST;
723 }
724
725 int UtcDaliFrameCallbackInvalidActorId(void)
726 {
727   // Test to ensure that there are no issues when trying to use the update-proxy methods with an invalid actor ID.
728
729   TestApplication application;
730   Stage           stage = Stage::GetCurrent();
731
732   FrameCallbackActorIdCheck frameCallback(10000);
733   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
734
735   application.SendNotification();
736   application.Render();
737
738   // Invalid Actor ID so all the methods should not return successfully.
739
740   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
741   DALI_TEST_EQUALS(frameCallback.mGetSizeCallSuccess, false, TEST_LOCATION);
742   DALI_TEST_EQUALS(frameCallback.mGetPositionCallSuccess, false, TEST_LOCATION);
743   DALI_TEST_EQUALS(frameCallback.mGetColorCallSuccess, false, TEST_LOCATION);
744   DALI_TEST_EQUALS(frameCallback.mGetScaleCallSuccess, false, TEST_LOCATION);
745   DALI_TEST_EQUALS(frameCallback.mGetPositionAndSizeCallSuccess, false, TEST_LOCATION);
746   DALI_TEST_EQUALS(frameCallback.mGetWorldPositionScaleAndSizeCallSuccess, false, TEST_LOCATION);
747   DALI_TEST_EQUALS(frameCallback.mSetSizeCallSuccess, false, TEST_LOCATION);
748   DALI_TEST_EQUALS(frameCallback.mSetPositionCallSuccess, false, TEST_LOCATION);
749   DALI_TEST_EQUALS(frameCallback.mSetColorCallSuccess, false, TEST_LOCATION);
750   DALI_TEST_EQUALS(frameCallback.mSetScaleCallSuccess, false, TEST_LOCATION);
751   DALI_TEST_EQUALS(frameCallback.mBakeSizeCallSuccess, false, TEST_LOCATION);
752   DALI_TEST_EQUALS(frameCallback.mBakePositionCallSuccess, false, TEST_LOCATION);
753   DALI_TEST_EQUALS(frameCallback.mBakeColorCallSuccess, false, TEST_LOCATION);
754   DALI_TEST_EQUALS(frameCallback.mBakeScaleCallSuccess, false, TEST_LOCATION);
755
756   DALI_TEST_EQUALS(frameCallback.mGetOrientationCallSuccess, false, TEST_LOCATION);
757   DALI_TEST_EQUALS(frameCallback.mSetOrientationCallSuccess, false, TEST_LOCATION);
758   DALI_TEST_EQUALS(frameCallback.mBakeOrientationCallSuccess, false, TEST_LOCATION);
759
760   DALI_TEST_EQUALS(frameCallback.mGetWorldTransformCallSuccess, false, TEST_LOCATION);
761
762   END_TEST;
763 }
764
765 int UtcDaliFrameCallbackActorRemovedAndAdded(void)
766 {
767   // Test to ensure that we do not call methods on actors that have been removed on the stage
768   // and then re-start calling the required methods if that actor is re-added back to the stage
769
770   TestApplication application;
771   Stage           stage = Stage::GetCurrent();
772
773   Actor actor = Actor::New();
774   stage.Add(actor);
775
776   FrameCallbackActorIdCheck frameCallback(actor.GetProperty<int>(Actor::Property::ID));
777   DevelStage::AddFrameCallback(stage, frameCallback, stage.GetRootLayer());
778
779   application.SendNotification();
780   application.Render();
781
782   // All methods should return successfully.
783
784   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
785   DALI_TEST_EQUALS(frameCallback.mGetSizeCallSuccess, true, TEST_LOCATION);
786   DALI_TEST_EQUALS(frameCallback.mGetPositionCallSuccess, true, TEST_LOCATION);
787   DALI_TEST_EQUALS(frameCallback.mGetColorCallSuccess, true, TEST_LOCATION);
788   DALI_TEST_EQUALS(frameCallback.mGetScaleCallSuccess, true, TEST_LOCATION);
789   DALI_TEST_EQUALS(frameCallback.mGetPositionAndSizeCallSuccess, true, TEST_LOCATION);
790   DALI_TEST_EQUALS(frameCallback.mGetWorldPositionScaleAndSizeCallSuccess, true, TEST_LOCATION);
791   DALI_TEST_EQUALS(frameCallback.mSetSizeCallSuccess, true, TEST_LOCATION);
792   DALI_TEST_EQUALS(frameCallback.mSetPositionCallSuccess, true, TEST_LOCATION);
793   DALI_TEST_EQUALS(frameCallback.mSetColorCallSuccess, true, TEST_LOCATION);
794   DALI_TEST_EQUALS(frameCallback.mSetScaleCallSuccess, true, TEST_LOCATION);
795   DALI_TEST_EQUALS(frameCallback.mBakeSizeCallSuccess, true, TEST_LOCATION);
796   DALI_TEST_EQUALS(frameCallback.mBakePositionCallSuccess, true, TEST_LOCATION);
797   DALI_TEST_EQUALS(frameCallback.mBakeColorCallSuccess, true, TEST_LOCATION);
798   DALI_TEST_EQUALS(frameCallback.mBakeScaleCallSuccess, true, TEST_LOCATION);
799   DALI_TEST_EQUALS(frameCallback.mGetOrientationCallSuccess, true, TEST_LOCATION);
800   DALI_TEST_EQUALS(frameCallback.mSetOrientationCallSuccess, true, TEST_LOCATION);
801   DALI_TEST_EQUALS(frameCallback.mBakeOrientationCallSuccess, true, TEST_LOCATION);
802   DALI_TEST_EQUALS(frameCallback.mGetWorldTransformCallSuccess, true, TEST_LOCATION);
803
804   frameCallback.Reset();
805
806   // Remove the actor from stage, the methods should not return successfully.
807
808   stage.Remove(actor);
809
810   application.SendNotification();
811   application.Render();
812
813   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
814   DALI_TEST_EQUALS(frameCallback.mGetSizeCallSuccess, false, TEST_LOCATION);
815   DALI_TEST_EQUALS(frameCallback.mGetPositionCallSuccess, false, TEST_LOCATION);
816   DALI_TEST_EQUALS(frameCallback.mGetColorCallSuccess, false, TEST_LOCATION);
817   DALI_TEST_EQUALS(frameCallback.mGetScaleCallSuccess, false, TEST_LOCATION);
818   DALI_TEST_EQUALS(frameCallback.mGetPositionAndSizeCallSuccess, false, TEST_LOCATION);
819   DALI_TEST_EQUALS(frameCallback.mGetWorldPositionScaleAndSizeCallSuccess, false, TEST_LOCATION);
820   DALI_TEST_EQUALS(frameCallback.mSetSizeCallSuccess, false, TEST_LOCATION);
821   DALI_TEST_EQUALS(frameCallback.mSetPositionCallSuccess, false, TEST_LOCATION);
822   DALI_TEST_EQUALS(frameCallback.mSetColorCallSuccess, false, TEST_LOCATION);
823   DALI_TEST_EQUALS(frameCallback.mSetScaleCallSuccess, false, TEST_LOCATION);
824   DALI_TEST_EQUALS(frameCallback.mBakeSizeCallSuccess, false, TEST_LOCATION);
825   DALI_TEST_EQUALS(frameCallback.mBakePositionCallSuccess, false, TEST_LOCATION);
826   DALI_TEST_EQUALS(frameCallback.mBakeColorCallSuccess, false, TEST_LOCATION);
827   DALI_TEST_EQUALS(frameCallback.mBakeScaleCallSuccess, false, TEST_LOCATION);
828   DALI_TEST_EQUALS(frameCallback.mGetOrientationCallSuccess, false, TEST_LOCATION);
829   DALI_TEST_EQUALS(frameCallback.mSetOrientationCallSuccess, false, TEST_LOCATION);
830   DALI_TEST_EQUALS(frameCallback.mBakeOrientationCallSuccess, false, TEST_LOCATION);
831   DALI_TEST_EQUALS(frameCallback.mGetWorldTransformCallSuccess, false, TEST_LOCATION);
832
833   frameCallback.Reset();
834
835   // Re-add the actor back to the stage, all the methods should once again, return successfully.
836
837   stage.Add(actor);
838
839   application.SendNotification();
840   application.Render();
841
842   DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
843   DALI_TEST_EQUALS(frameCallback.mGetSizeCallSuccess, true, TEST_LOCATION);
844   DALI_TEST_EQUALS(frameCallback.mGetPositionCallSuccess, true, TEST_LOCATION);
845   DALI_TEST_EQUALS(frameCallback.mGetColorCallSuccess, true, TEST_LOCATION);
846   DALI_TEST_EQUALS(frameCallback.mGetScaleCallSuccess, true, TEST_LOCATION);
847   DALI_TEST_EQUALS(frameCallback.mGetPositionAndSizeCallSuccess, true, TEST_LOCATION);
848   DALI_TEST_EQUALS(frameCallback.mGetWorldPositionScaleAndSizeCallSuccess, true, TEST_LOCATION);
849   DALI_TEST_EQUALS(frameCallback.mSetSizeCallSuccess, true, TEST_LOCATION);
850   DALI_TEST_EQUALS(frameCallback.mSetPositionCallSuccess, true, TEST_LOCATION);
851   DALI_TEST_EQUALS(frameCallback.mSetColorCallSuccess, true, TEST_LOCATION);
852   DALI_TEST_EQUALS(frameCallback.mSetScaleCallSuccess, true, TEST_LOCATION);
853   DALI_TEST_EQUALS(frameCallback.mBakeSizeCallSuccess, true, TEST_LOCATION);
854   DALI_TEST_EQUALS(frameCallback.mBakePositionCallSuccess, true, TEST_LOCATION);
855   DALI_TEST_EQUALS(frameCallback.mBakeColorCallSuccess, true, TEST_LOCATION);
856   DALI_TEST_EQUALS(frameCallback.mBakeScaleCallSuccess, true, TEST_LOCATION);
857   DALI_TEST_EQUALS(frameCallback.mGetOrientationCallSuccess, true, TEST_LOCATION);
858   DALI_TEST_EQUALS(frameCallback.mSetOrientationCallSuccess, true, TEST_LOCATION);
859   DALI_TEST_EQUALS(frameCallback.mBakeOrientationCallSuccess, true, TEST_LOCATION);
860   DALI_TEST_EQUALS(frameCallback.mGetWorldTransformCallSuccess, true, TEST_LOCATION);
861
862   END_TEST;
863 }
864
865 int UtcDaliFrameCallbackMultipleCallbacks(void)
866 {
867   // Test to ensure multiple frame-callbacks work as expected
868
869   TestApplication application;
870   Stage           stage = Stage::GetCurrent();
871
872   Actor actor = Actor::New();
873   stage.Add(actor);
874
875   FrameCallbackBasic frameCallback1;
876   FrameCallbackBasic frameCallback2;
877   DevelStage::AddFrameCallback(stage, frameCallback1, stage.GetRootLayer());
878   DevelStage::AddFrameCallback(stage, frameCallback2, stage.GetRootLayer());
879
880   application.SendNotification();
881   application.Render();
882
883   DALI_TEST_EQUALS(frameCallback1.mCalled, true, TEST_LOCATION);
884   DALI_TEST_EQUALS(frameCallback2.mCalled, true, TEST_LOCATION);
885   frameCallback1.Reset();
886   frameCallback2.Reset();
887
888   // Remove the second frame-callback, only the first should be called
889
890   DevelStage::RemoveFrameCallback(stage, frameCallback2);
891
892   application.SendNotification();
893   application.Render();
894
895   DALI_TEST_EQUALS(frameCallback1.mCalled, true, TEST_LOCATION);
896   DALI_TEST_EQUALS(frameCallback2.mCalled, false, TEST_LOCATION);
897   frameCallback1.Reset();
898   frameCallback2.Reset();
899
900   // Re-add the second frame-callback and remove the first, only the second should be called
901
902   DevelStage::AddFrameCallback(stage, frameCallback2, stage.GetRootLayer());
903   DevelStage::RemoveFrameCallback(stage, frameCallback1);
904
905   application.SendNotification();
906   application.Render();
907
908   DALI_TEST_EQUALS(frameCallback1.mCalled, false, TEST_LOCATION);
909   DALI_TEST_EQUALS(frameCallback2.mCalled, true, TEST_LOCATION);
910   frameCallback1.Reset();
911   frameCallback2.Reset();
912
913   // Attempt removal of the first frame-callback again, should be a no-op and yield the exact same results as the last run
914   DevelStage::RemoveFrameCallback(stage, frameCallback1);
915
916   application.SendNotification();
917   application.Render();
918
919   DALI_TEST_EQUALS(frameCallback1.mCalled, false, TEST_LOCATION);
920   DALI_TEST_EQUALS(frameCallback2.mCalled, true, TEST_LOCATION);
921   frameCallback1.Reset();
922   frameCallback2.Reset();
923
924   // Remove the second frame-callback as well, neither should be called
925   DevelStage::RemoveFrameCallback(stage, frameCallback2);
926
927   application.SendNotification();
928   application.Render();
929
930   DALI_TEST_EQUALS(frameCallback1.mCalled, false, TEST_LOCATION);
931   DALI_TEST_EQUALS(frameCallback2.mCalled, false, TEST_LOCATION);
932
933   END_TEST;
934 }
935
936 int UtcDaliFrameCallbackActorDestroyed(void)
937 {
938   // Test to ensure that the frame-callback behaves gracefully if the connected root-actor is destroyed
939
940   TestApplication application;
941   Stage           stage = Stage::GetCurrent();
942
943   Actor actor = Actor::New();
944   stage.Add(actor);
945
946   FrameCallbackBasic frameCallback1;
947   FrameCallbackBasic frameCallback2;
948   DevelStage::AddFrameCallback(stage, frameCallback1, actor);
949   DevelStage::AddFrameCallback(stage, frameCallback2, actor);
950
951   application.SendNotification();
952   application.Render();
953
954   DALI_TEST_EQUALS(frameCallback1.mCalled, true, TEST_LOCATION);
955   DALI_TEST_EQUALS(frameCallback2.mCalled, true, TEST_LOCATION);
956   frameCallback1.Reset();
957   frameCallback2.Reset();
958
959   // Remove the second frame-callback, only the first should be called
960
961   DevelStage::RemoveFrameCallback(stage, frameCallback2);
962
963   application.SendNotification();
964   application.Render();
965
966   DALI_TEST_EQUALS(frameCallback1.mCalled, true, TEST_LOCATION);
967   DALI_TEST_EQUALS(frameCallback2.mCalled, false, TEST_LOCATION);
968   frameCallback1.Reset();
969   frameCallback2.Reset();
970
971   // Remove and destroy the actor, the first one should not be called either
972   stage.Remove(actor);
973   actor.Reset();
974
975   application.SendNotification();
976   application.Render();
977
978   DALI_TEST_EQUALS(frameCallback1.mCalled, false, TEST_LOCATION);
979   DALI_TEST_EQUALS(frameCallback2.mCalled, false, TEST_LOCATION);
980
981   END_TEST;
982 }
983
984 int UtcDaliFrameCallbackDestroyedBeforeRemoving(void)
985 {
986   // Ensure there's no segmentation fault if the callback is deleted without being removed
987
988   TestApplication application;
989   Stage           stage = Stage::GetCurrent();
990
991   Actor actor = Actor::New();
992   stage.Add(actor);
993
994   {
995     FrameCallbackBasic frameCallback;
996     DevelStage::AddFrameCallback(stage, frameCallback, actor);
997
998     application.SendNotification();
999     application.Render();
1000
1001     DALI_TEST_EQUALS(frameCallback.mCalled, true, TEST_LOCATION);
1002     frameCallback.Reset();
1003   }
1004
1005   // frameCallback has now been destroyed but not removed
1006
1007   application.SendNotification();
1008   application.Render();
1009   DALI_TEST_CHECK(true); // If it runs to here then there's no segmentation fault
1010
1011   END_TEST;
1012 }
1013
1014 int UtcDaliFrameCallbackDoubleAddition(void)
1015 {
1016   // Ensure we don't connect the same frame-callback twice
1017
1018   TestApplication application;
1019   Stage           stage     = Stage::GetCurrent();
1020   Actor           rootActor = stage.GetRootLayer();
1021
1022   FrameCallbackBasic frameCallback;
1023   DevelStage::AddFrameCallback(stage, frameCallback, rootActor);
1024
1025   try
1026   {
1027     DevelStage::AddFrameCallback(stage, frameCallback, rootActor);
1028   }
1029   catch(...)
1030   {
1031     DALI_TEST_CHECK(true);
1032   }
1033
1034   END_TEST;
1035 }
1036
1037 int UtcDaliFrameCallbackGetExtension(void)
1038 {
1039   FrameCallbackBasic frameCallback;
1040   DALI_TEST_CHECK(frameCallback.GetExtension() == nullptr);
1041
1042   END_TEST;
1043 }