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