[Tizen] Add TOUCH_FOCUSABLE property
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2021 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 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <cfloat>
24 #include <cmath>
25
26 // INTERNAL INCLUDES
27 #include <dali/devel-api/actors/actor-devel.h>
28 #include <dali/devel-api/actors/layer-devel.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/internal/event/actors/actor-property-handler.h>
31 #include <dali/internal/event/actors/actor-relayouter.h>
32 #include <dali/internal/event/actors/camera-actor-impl.h>
33 #include <dali/internal/event/common/event-thread-services.h>
34 #include <dali/internal/event/common/projection.h>
35 #include <dali/internal/event/common/property-helper.h>
36 #include <dali/internal/event/common/scene-impl.h>
37 #include <dali/internal/event/common/stage-impl.h>
38 #include <dali/internal/event/common/thread-local-storage.h>
39 #include <dali/internal/event/common/type-info-impl.h>
40 #include <dali/internal/event/events/actor-gesture-data.h>
41 #include <dali/internal/event/render-tasks/render-task-impl.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
44 #include <dali/internal/update/nodes/node-messages.h>
45 #include <dali/public-api/common/constants.h>
46 #include <dali/public-api/common/dali-common.h>
47 #include <dali/public-api/math/radian.h>
48 #include <dali/public-api/math/vector2.h>
49 #include <dali/public-api/math/vector3.h>
50 #include <dali/public-api/object/type-registry.h>
51
52 using Dali::Internal::SceneGraph::AnimatableProperty;
53 using Dali::Internal::SceneGraph::Node;
54 using Dali::Internal::SceneGraph::PropertyBase;
55
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter         = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER");
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER");
59 #endif
60
61 namespace Dali
62 {
63 namespace Internal
64 {
65 namespace // unnamed namespace
66 {
67 // Properties
68
69 /**
70  * We want to discourage the use of property strings (minimize string comparisons),
71  * particularly for the default properties.
72  *              Name                  Type   writable animatable constraint-input  enum for index-checking
73  */
74 DALI_PROPERTY_TABLE_BEGIN
75 DALI_PROPERTY("parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN)
76 DALI_PROPERTY("parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X)
77 DALI_PROPERTY("parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y)
78 DALI_PROPERTY("parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z)
79 DALI_PROPERTY("anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT)
80 DALI_PROPERTY("anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X)
81 DALI_PROPERTY("anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y)
82 DALI_PROPERTY("anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z)
83 DALI_PROPERTY("size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE)
84 DALI_PROPERTY("sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH)
85 DALI_PROPERTY("sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT)
86 DALI_PROPERTY("sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH)
87 DALI_PROPERTY("position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION)
88 DALI_PROPERTY("positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X)
89 DALI_PROPERTY("positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y)
90 DALI_PROPERTY("positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z)
91 DALI_PROPERTY("worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION)
92 DALI_PROPERTY("worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X)
93 DALI_PROPERTY("worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y)
94 DALI_PROPERTY("worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z)
95 DALI_PROPERTY("orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION)
96 DALI_PROPERTY("worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION)
97 DALI_PROPERTY("scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE)
98 DALI_PROPERTY("scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X)
99 DALI_PROPERTY("scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y)
100 DALI_PROPERTY("scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z)
101 DALI_PROPERTY("worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE)
102 DALI_PROPERTY("visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE)
103 DALI_PROPERTY("color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR)
104 DALI_PROPERTY("colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED)
105 DALI_PROPERTY("colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN)
106 DALI_PROPERTY("colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE)
107 DALI_PROPERTY("colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA)
108 DALI_PROPERTY("worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR)
109 DALI_PROPERTY("worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX)
110 DALI_PROPERTY("name", STRING, true, false, false, Dali::Actor::Property::NAME)
111 DALI_PROPERTY("sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE)
112 DALI_PROPERTY("leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED)
113 DALI_PROPERTY("inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION)
114 DALI_PROPERTY("inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE)
115 DALI_PROPERTY("colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE)
116 DALI_PROPERTY("drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE)
117 DALI_PROPERTY("sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR)
118 DALI_PROPERTY("widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY)
119 DALI_PROPERTY("heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY)
120 DALI_PROPERTY("sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY)
121 DALI_PROPERTY("widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT)
122 DALI_PROPERTY("heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH)
123 DALI_PROPERTY("padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING)
124 DALI_PROPERTY("minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE)
125 DALI_PROPERTY("maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE)
126 DALI_PROPERTY("inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION)
127 DALI_PROPERTY("clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE)
128 DALI_PROPERTY("layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION)
129 DALI_PROPERTY("inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION)
130 DALI_PROPERTY("opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY)
131 DALI_PROPERTY("screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION)
132 DALI_PROPERTY("positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT)
133 DALI_PROPERTY("culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED)
134 DALI_PROPERTY("id", INTEGER, false, false, false, Dali::Actor::Property::ID)
135 DALI_PROPERTY("hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH)
136 DALI_PROPERTY("isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT)
137 DALI_PROPERTY("isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER)
138 DALI_PROPERTY("connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE)
139 DALI_PROPERTY("keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE)
140 DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER)
141 DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT)
142 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
143 DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
144 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
145 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
146
147 // Signals
148
149 const char* const SIGNAL_HOVERED                  = "hovered";
150 const char* const SIGNAL_WHEEL_EVENT              = "wheelEvent";
151 const char* const SIGNAL_ON_SCENE                 = "onScene";
152 const char* const SIGNAL_OFF_SCENE                = "offScene";
153 const char* const SIGNAL_ON_RELAYOUT              = "onRelayout";
154 const char* const SIGNAL_TOUCHED                  = "touched";
155 const char* const SIGNAL_VISIBILITY_CHANGED       = "visibilityChanged";
156 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
157 const char* const SIGNAL_CHILD_ADDED              = "childAdded";
158 const char* const SIGNAL_CHILD_REMOVED            = "childRemoved";
159
160 // Actions
161
162 const char* const ACTION_SHOW = "show";
163 const char* const ACTION_HIDE = "hide";
164
165 BaseHandle CreateActor()
166 {
167   return Dali::Actor::New();
168 }
169
170 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
171
172 SignalConnectorType signalConnector2(mType, SIGNAL_HOVERED, &Actor::DoConnectSignal);
173 SignalConnectorType signalConnector3(mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal);
174 SignalConnectorType signalConnector4(mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal);
175 SignalConnectorType signalConnector5(mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal);
176 SignalConnectorType signalConnector6(mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal);
177 SignalConnectorType signalConnector7(mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal);
178 SignalConnectorType signalConnector8(mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector9(mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector10(mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector11(mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal);
182
183 TypeAction a1(mType, ACTION_SHOW, &Actor::DoAction);
184 TypeAction a2(mType, ACTION_HIDE, &Actor::DoAction);
185
186 /**
187  * @brief Extract a given dimension from a Vector2
188  *
189  * @param[in] values The values to extract from
190  * @param[in] dimension The dimension to extract
191  * @return Return the value for the dimension
192  */
193 constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension)
194 {
195   switch(dimension)
196   {
197     case Dimension::WIDTH:
198     {
199       return values.width;
200     }
201     case Dimension::HEIGHT:
202     {
203       return values.height;
204     }
205     default:
206     {
207       break;
208     }
209   }
210   return 0.0f;
211 }
212
213 /**
214  * @brief Extract a given dimension from a Vector3
215  *
216  * @param[in] values The values to extract from
217  * @param[in] dimension The dimension to extract
218  * @return Return the value for the dimension
219  */
220 float GetDimensionValue(const Vector3& values, Dimension::Type dimension)
221 {
222   return GetDimensionValue(values.GetVectorXY(), dimension);
223 }
224
225 /**
226  * @brief Recursively emits the visibility-changed-signal on the actor tree.
227  * @param[in] actor The actor to emit the signal on
228  * @param[in] visible The new visibility of the actor
229  * @param[in] type Whether the actor's visible property has changed or a parent's
230  */
231 void EmitVisibilityChangedSignalRecursively(ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type)
232 {
233   if(actor)
234   {
235     actor->EmitVisibilityChangedSignal(visible, type);
236
237     if(actor->GetChildCount() > 0)
238     {
239       for(auto& child : actor->GetChildrenInternal())
240       {
241         EmitVisibilityChangedSignalRecursively(child, visible, DevelActor::VisibilityChange::PARENT);
242       }
243     }
244   }
245 }
246
247 /// Helper for emitting a signal
248 template<typename Signal, typename Event>
249 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
250 {
251   bool consumed = false;
252
253   if(!signal.Empty())
254   {
255     Dali::Actor handle(&actor);
256     consumed = signal.Emit(handle, event);
257   }
258
259   return consumed;
260 }
261
262 /// Helper for emitting signals with multiple parameters
263 template<typename Signal, typename... Param>
264 void EmitSignal(Actor& actor, Signal& signal, Param... params)
265 {
266   if(!signal.Empty())
267   {
268     Dali::Actor handle(&actor);
269     signal.Emit(handle, params...);
270   }
271 }
272
273 bool ScreenToLocalInternal(
274   const Matrix&   viewMatrix,
275   const Matrix&   projectionMatrix,
276   const Matrix&   worldMatrix,
277   const Viewport& viewport,
278   const Vector3&  currentSize,
279   float&          localX,
280   float&          localY,
281   float           screenX,
282   float           screenY)
283 {
284   // Get the ModelView matrix
285   Matrix modelView;
286   Matrix::Multiply(modelView, worldMatrix, viewMatrix);
287
288   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
289   Matrix invertedMvp(false /*don't init*/);
290   Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
291   bool success = invertedMvp.Invert();
292
293   // Convert to GL coordinates
294   Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
295
296   Vector4 nearPos;
297   if(success)
298   {
299     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
300   }
301
302   Vector4 farPos;
303   if(success)
304   {
305     screenPos.z = 1.0f;
306     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
307   }
308
309   if(success)
310   {
311     Vector4 local;
312     if(XyPlaneIntersect(nearPos, farPos, local))
313     {
314       Vector3 size = currentSize;
315       localX       = local.x + size.x * 0.5f;
316       localY       = local.y + size.y * 0.5f;
317     }
318     else
319     {
320       success = false;
321     }
322   }
323
324   return success;
325 }
326
327 } // unnamed namespace
328
329 ActorPtr Actor::New()
330 {
331   // pass a reference to actor, actor does not own its node
332   ActorPtr actor(new Actor(BASIC, *CreateNode()));
333
334   // Second-phase construction
335   actor->Initialize();
336
337   return actor;
338 }
339
340 const SceneGraph::Node* Actor::CreateNode()
341 {
342   // create node. Nodes are owned by the update manager
343   SceneGraph::Node*              node = SceneGraph::Node::New();
344   OwnerPointer<SceneGraph::Node> transferOwnership(node);
345   Internal::ThreadLocalStorage*  tls = Internal::ThreadLocalStorage::GetInternal();
346
347   DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
348
349   AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
350
351   return node;
352 }
353
354 void Actor::SetName(const std::string& name)
355 {
356   mName = name;
357
358   // ATTENTION: string for debug purposes is not thread safe.
359   DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), name);
360 }
361
362 uint32_t Actor::GetId() const
363 {
364   return GetNode().GetId();
365 }
366
367 Dali::Layer Actor::GetLayer()
368 {
369   Dali::Layer layer;
370
371   // Short-circuit for Layer derived actors
372   if(mIsLayer)
373   {
374     layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(this)); // static cast as we trust the flag
375   }
376
377   // Find the immediate Layer parent
378   for(Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent())
379   {
380     if(parent->IsLayer())
381     {
382       layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(parent)); // static cast as we trust the flag
383     }
384   }
385
386   return layer;
387 }
388
389 void Actor::Add(Actor& child)
390 {
391   DALI_ASSERT_ALWAYS(this != &child && "Cannot add actor to itself");
392   DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
393
394   if(!mChildren)
395   {
396     mChildren = new ActorContainer;
397   }
398
399   Actor* const oldParent(child.mParent);
400
401   // child might already be ours
402   if(this != oldParent)
403   {
404     // if we already have parent, unparent us first
405     if(oldParent)
406     {
407       oldParent->Remove(child); // This causes OnChildRemove callback & ChildRemoved signal
408
409       // Old parent may need to readjust to missing child
410       if(oldParent->RelayoutDependentOnChildren())
411       {
412         oldParent->RelayoutRequest();
413       }
414     }
415
416     // Guard against Add() during previous OnChildRemove callback
417     if(!child.mParent)
418     {
419       // Do this first, since user callbacks from within SetParent() may need to remove child
420       mChildren->push_back(ActorPtr(&child));
421
422       // SetParent asserts that child can be added
423       child.SetParent(this);
424
425       // Notification for derived classes
426       OnChildAdd(child);
427       EmitChildAddedSignal(child);
428
429       InheritLayoutDirectionRecursively(ActorPtr(&child), mLayoutDirection);
430
431       // Only put in a relayout request if there is a suitable dependency
432       if(RelayoutDependentOnChildren())
433       {
434         RelayoutRequest();
435       }
436     }
437   }
438 }
439
440 void Actor::Remove(Actor& child)
441 {
442   if((this == &child) || (!mChildren))
443   {
444     // no children or removing itself
445     return;
446   }
447
448   ActorPtr removed;
449
450   // Find the child in mChildren, and unparent it
451   ActorIter end = mChildren->end();
452   for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
453   {
454     ActorPtr actor = (*iter);
455
456     if(actor.Get() == &child)
457     {
458       // Keep handle for OnChildRemove notification
459       removed = actor;
460
461       // Do this first, since user callbacks from within SetParent() may need to add the child
462       mChildren->erase(iter);
463
464       DALI_ASSERT_DEBUG(actor->GetParent() == this);
465       actor->SetParent(nullptr);
466
467       break;
468     }
469   }
470
471   if(removed)
472   {
473     // Only put in a relayout request if there is a suitable dependency
474     if(RelayoutDependentOnChildren())
475     {
476       RelayoutRequest();
477     }
478   }
479
480   // Notification for derived classes
481   OnChildRemove(child);
482   EmitChildRemovedSignal(child);
483 }
484
485 void Actor::Unparent()
486 {
487   if(mParent)
488   {
489     // Remove this actor from the parent. The remove will put a relayout request in for
490     // the parent if required
491     mParent->Remove(*this);
492     // mParent is now NULL!
493   }
494 }
495
496 uint32_t Actor::GetChildCount() const
497 {
498   return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
499 }
500
501 ActorPtr Actor::GetChildAt(uint32_t index) const
502 {
503   DALI_ASSERT_ALWAYS(index < GetChildCount());
504
505   return ((mChildren) ? (*mChildren)[index] : ActorPtr());
506 }
507
508 ActorPtr Actor::FindChildByName(const std::string& actorName)
509 {
510   ActorPtr child = nullptr;
511   if(actorName == mName)
512   {
513     child = this;
514   }
515   else if(mChildren)
516   {
517     for(const auto& actor : *mChildren)
518     {
519       child = actor->FindChildByName(actorName);
520
521       if(child)
522       {
523         break;
524       }
525     }
526   }
527   return child;
528 }
529
530 ActorPtr Actor::FindChildById(const uint32_t id)
531 {
532   ActorPtr child = nullptr;
533   if(id == GetId())
534   {
535     child = this;
536   }
537   else if(mChildren)
538   {
539     for(const auto& actor : *mChildren)
540     {
541       child = actor->FindChildById(id);
542
543       if(child)
544       {
545         break;
546       }
547     }
548   }
549   return child;
550 }
551
552 void Actor::SetParentOrigin(const Vector3& origin)
553 {
554   // node is being used in a separate thread; queue a message to set the value & base value
555   SetParentOriginMessage(GetEventThreadServices(), GetNode(), origin);
556
557   // Cache for event-thread access
558   if(!mParentOrigin)
559   {
560     // not allocated, check if different from default
561     if(ParentOrigin::DEFAULT != origin)
562     {
563       mParentOrigin = new Vector3(origin);
564     }
565   }
566   else
567   {
568     // check if different from current costs more than just set
569     *mParentOrigin = origin;
570   }
571 }
572
573 const Vector3& Actor::GetCurrentParentOrigin() const
574 {
575   // Cached for event-thread access
576   return (mParentOrigin) ? *mParentOrigin : ParentOrigin::DEFAULT;
577 }
578
579 void Actor::SetAnchorPoint(const Vector3& anchor)
580 {
581   // node is being used in a separate thread; queue a message to set the value & base value
582   SetAnchorPointMessage(GetEventThreadServices(), GetNode(), anchor);
583
584   // Cache for event-thread access
585   if(!mAnchorPoint)
586   {
587     // not allocated, check if different from default
588     if(AnchorPoint::DEFAULT != anchor)
589     {
590       mAnchorPoint = new Vector3(anchor);
591     }
592   }
593   else
594   {
595     // check if different from current costs more than just set
596     *mAnchorPoint = anchor;
597   }
598 }
599
600 const Vector3& Actor::GetCurrentAnchorPoint() const
601 {
602   // Cached for event-thread access
603   return (mAnchorPoint) ? *mAnchorPoint : AnchorPoint::DEFAULT;
604 }
605
606 void Actor::SetPosition(float x, float y)
607 {
608   SetPosition(Vector3(x, y, 0.0f));
609 }
610
611 void Actor::SetPosition(float x, float y, float z)
612 {
613   SetPosition(Vector3(x, y, z));
614 }
615
616 void Actor::SetPosition(const Vector3& position)
617 {
618   mTargetPosition = position;
619
620   // node is being used in a separate thread; queue a message to set the value & base value
621   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position);
622 }
623
624 void Actor::SetX(float x)
625 {
626   mTargetPosition.x = x;
627
628   // node is being used in a separate thread; queue a message to set the value & base value
629   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
630 }
631
632 void Actor::SetY(float y)
633 {
634   mTargetPosition.y = y;
635
636   // node is being used in a separate thread; queue a message to set the value & base value
637   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
638 }
639
640 void Actor::SetZ(float z)
641 {
642   mTargetPosition.z = z;
643
644   // node is being used in a separate thread; queue a message to set the value & base value
645   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
646 }
647
648 void Actor::TranslateBy(const Vector3& distance)
649 {
650   mTargetPosition += distance;
651
652   // node is being used in a separate thread; queue a message to set the value & base value
653   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance);
654 }
655
656 const Vector3& Actor::GetCurrentPosition() const
657 {
658   // node is being used in a separate thread; copy the value from the previous update
659   return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
660 }
661
662 const Vector3& Actor::GetCurrentWorldPosition() const
663 {
664   // node is being used in a separate thread; copy the value from the previous update
665   return GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
666 }
667
668 const Vector2 Actor::GetCurrentScreenPosition() const
669 {
670   if(mScene && OnScene())
671   {
672     Vector3 worldPosition  = GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
673     Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
674     worldPosition -= cameraPosition;
675
676     Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
677     Vector2 halfSceneSize(mScene->GetSize() * 0.5f); // World position origin is center of scene
678     Vector3 halfActorSize(actorSize * 0.5f);
679     Vector3 anchorPointOffSet = halfActorSize - actorSize * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
680
681     return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
682                    halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
683   }
684
685   return Vector2::ZERO;
686 }
687
688 void Actor::SetInheritPosition(bool inherit)
689 {
690   if(mInheritPosition != inherit)
691   {
692     // non animatable so keep local copy
693     mInheritPosition = inherit;
694     SetInheritPositionMessage(GetEventThreadServices(), GetNode(), inherit);
695   }
696 }
697
698 void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
699 {
700   Vector3 normalizedAxis(axis.x, axis.y, axis.z);
701   normalizedAxis.Normalize();
702
703   Quaternion orientation(angle, normalizedAxis);
704
705   SetOrientation(orientation);
706 }
707
708 void Actor::SetOrientation(const Quaternion& orientation)
709 {
710   mTargetOrientation = orientation;
711
712   // node is being used in a separate thread; queue a message to set the value & base value
713   SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation);
714 }
715
716 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
717 {
718   RotateBy(Quaternion(angle, axis));
719 }
720
721 void Actor::RotateBy(const Quaternion& relativeRotation)
722 {
723   mTargetOrientation *= Quaternion(relativeRotation);
724
725   // node is being used in a separate thread; queue a message to set the value & base value
726   SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation);
727 }
728
729 const Quaternion& Actor::GetCurrentOrientation() const
730 {
731   // node is being used in a separate thread; copy the value from the previous update
732   return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
733 }
734
735 const Quaternion& Actor::GetCurrentWorldOrientation() const
736 {
737   // node is being used in a separate thread; copy the value from the previous update
738   return GetNode().GetWorldOrientation(GetEventThreadServices().GetEventBufferIndex());
739 }
740
741 void Actor::SetScale(float scale)
742 {
743   SetScale(Vector3(scale, scale, scale));
744 }
745
746 void Actor::SetScale(float x, float y, float z)
747 {
748   SetScale(Vector3(x, y, z));
749 }
750
751 void Actor::SetScale(const Vector3& scale)
752 {
753   mTargetScale = scale;
754
755   // node is being used in a separate thread; queue a message to set the value & base value
756   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale);
757 }
758
759 void Actor::SetScaleX(float x)
760 {
761   mTargetScale.x = x;
762
763   // node is being used in a separate thread; queue a message to set the value & base value
764   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
765 }
766
767 void Actor::SetScaleY(float y)
768 {
769   mTargetScale.y = y;
770
771   // node is being used in a separate thread; queue a message to set the value & base value
772   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
773 }
774
775 void Actor::SetScaleZ(float z)
776 {
777   mTargetScale.z = z;
778
779   // node is being used in a separate thread; queue a message to set the value & base value
780   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
781 }
782
783 void Actor::ScaleBy(const Vector3& relativeScale)
784 {
785   mTargetScale *= relativeScale;
786
787   // node is being used in a separate thread; queue a message to set the value & base value
788   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale);
789 }
790
791 const Vector3& Actor::GetCurrentScale() const
792 {
793   // node is being used in a separate thread; copy the value from the previous update
794   return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
795 }
796
797 const Vector3& Actor::GetCurrentWorldScale() const
798 {
799   // node is being used in a separate thread; copy the value from the previous update
800   return GetNode().GetWorldScale(GetEventThreadServices().GetEventBufferIndex());
801 }
802
803 void Actor::SetInheritScale(bool inherit)
804 {
805   if(mInheritScale != inherit)
806   {
807     // non animatable so keep local copy
808     mInheritScale = inherit;
809     // node is being used in a separate thread; queue a message to set the value
810     SetInheritScaleMessage(GetEventThreadServices(), GetNode(), inherit);
811   }
812 }
813
814 Matrix Actor::GetCurrentWorldMatrix() const
815 {
816   return GetNode().GetWorldMatrix(0);
817 }
818
819 void Actor::SetVisible(bool visible)
820 {
821   SetVisibleInternal(visible, SendMessage::TRUE);
822 }
823
824 bool Actor::IsVisible() const
825 {
826   // node is being used in a separate thread; copy the value from the previous update
827   return GetNode().IsVisible(GetEventThreadServices().GetEventBufferIndex());
828 }
829
830 void Actor::SetOpacity(float opacity)
831 {
832   mTargetColor.a = opacity;
833
834   // node is being used in a separate thread; queue a message to set the value & base value
835   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity);
836 }
837
838 float Actor::GetCurrentOpacity() const
839 {
840   // node is being used in a separate thread; copy the value from the previous update
841   return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
842 }
843
844 const Vector4& Actor::GetCurrentWorldColor() const
845 {
846   return GetNode().GetWorldColor(GetEventThreadServices().GetEventBufferIndex());
847 }
848
849 void Actor::SetColor(const Vector4& color)
850 {
851   mTargetColor = color;
852
853   // node is being used in a separate thread; queue a message to set the value & base value
854   SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color);
855 }
856
857 void Actor::SetColorRed(float red)
858 {
859   mTargetColor.r = red;
860
861   // node is being used in a separate thread; queue a message to set the value & base value
862   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red);
863 }
864
865 void Actor::SetColorGreen(float green)
866 {
867   mTargetColor.g = green;
868
869   // node is being used in a separate thread; queue a message to set the value & base value
870   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green);
871 }
872
873 void Actor::SetColorBlue(float blue)
874 {
875   mTargetColor.b = blue;
876
877   // node is being used in a separate thread; queue a message to set the value & base value
878   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue);
879 }
880
881 const Vector4& Actor::GetCurrentColor() const
882 {
883   // node is being used in a separate thread; copy the value from the previous update
884   return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
885 }
886
887 void Actor::SetInheritOrientation(bool inherit)
888 {
889   if(mInheritOrientation != inherit)
890   {
891     // non animatable so keep local copy
892     mInheritOrientation = inherit;
893     // node is being used in a separate thread; queue a message to set the value
894     SetInheritOrientationMessage(GetEventThreadServices(), GetNode(), inherit);
895   }
896 }
897
898 void Actor::SetSizeModeFactor(const Vector3& factor)
899 {
900   EnsureRelayouter();
901
902   mRelayoutData->sizeModeFactor = factor;
903 }
904
905 const Vector3& Actor::GetSizeModeFactor() const
906 {
907   if(mRelayoutData)
908   {
909     return mRelayoutData->sizeModeFactor;
910   }
911
912   return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
913 }
914
915 void Actor::SetColorMode(ColorMode colorMode)
916 {
917   // non animatable so keep local copy
918   mColorMode = colorMode;
919   // node is being used in a separate thread; queue a message to set the value
920   SetColorModeMessage(GetEventThreadServices(), GetNode(), colorMode);
921 }
922
923 void Actor::SetSize(float width, float height)
924 {
925   SetSize(Vector2(width, height));
926 }
927
928 void Actor::SetSize(float width, float height, float depth)
929 {
930   SetSize(Vector3(width, height, depth));
931 }
932
933 void Actor::SetSize(const Vector2& size)
934 {
935   SetSize(Vector3(size.width, size.height, 0.f));
936 }
937
938 void Actor::SetSizeInternal(const Vector2& size)
939 {
940   SetSizeInternal(Vector3(size.width, size.height, 0.f));
941 }
942
943 void Actor::SetSize(const Vector3& size)
944 {
945   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
946   {
947     // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
948     SetPreferredSize(size.GetVectorXY());
949   }
950   else
951   {
952     SetSizeInternal(size);
953   }
954 }
955
956 void Actor::SetSizeInternal(const Vector3& size)
957 {
958   // dont allow recursive loop
959   DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
960   // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
961   if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
962      (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
963      (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1))
964   {
965     mTargetSize = size;
966
967     // node is being used in a separate thread; queue a message to set the value & base value
968     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
969
970     // Notification for derived classes
971     mInsideOnSizeSet = true;
972     OnSizeSet(mTargetSize);
973     mInsideOnSizeSet = false;
974
975     // Raise a relayout request if the flag is not locked
976     if(mRelayoutData && !mRelayoutData->insideRelayout)
977     {
978       RelayoutRequest();
979     }
980   }
981 }
982
983 void Actor::SetWidth(float width)
984 {
985   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
986   {
987     SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
988     mRelayoutData->preferredSize.width = width;
989   }
990   else
991   {
992     mTargetSize.width = width;
993
994     // node is being used in a separate thread; queue a message to set the value & base value
995     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
996   }
997
998   mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
999
1000   RelayoutRequest();
1001 }
1002
1003 void Actor::SetHeight(float height)
1004 {
1005   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
1006   {
1007     SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
1008     mRelayoutData->preferredSize.height = height;
1009   }
1010   else
1011   {
1012     mTargetSize.height = height;
1013
1014     // node is being used in a separate thread; queue a message to set the value & base value
1015     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
1016   }
1017
1018   mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1019
1020   RelayoutRequest();
1021 }
1022
1023 void Actor::SetDepth(float depth)
1024 {
1025   mTargetSize.depth = depth;
1026
1027   mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1028
1029   // node is being used in a separate thread; queue a message to set the value & base value
1030   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
1031 }
1032
1033 Vector3 Actor::GetTargetSize() const
1034 {
1035   Vector3 size = mTargetSize;
1036
1037   if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
1038   {
1039     // Should return animated size if size is animated
1040     size.width = mAnimatedSize.width;
1041   }
1042   else
1043   {
1044     // Should return preferred size if size is fixed as set by SetSize
1045     if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
1046     {
1047       size.width = GetPreferredSize().width;
1048     }
1049   }
1050
1051   if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
1052   {
1053     size.height = mAnimatedSize.height;
1054   }
1055   else
1056   {
1057     if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
1058     {
1059       size.height = GetPreferredSize().height;
1060     }
1061   }
1062
1063   if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
1064   {
1065     size.depth = mAnimatedSize.depth;
1066   }
1067
1068   return size;
1069 }
1070
1071 const Vector3& Actor::GetCurrentSize() const
1072 {
1073   // node is being used in a separate thread; copy the value from the previous update
1074   return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
1075 }
1076
1077 Vector3 Actor::GetNaturalSize() const
1078 {
1079   // It is up to deriving classes to return the appropriate natural size
1080   return Vector3(0.0f, 0.0f, 0.0f);
1081 }
1082
1083 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
1084 {
1085   EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1086
1087   OnSetResizePolicy(policy, dimension);
1088
1089   // Trigger relayout on this control
1090   RelayoutRequest();
1091 }
1092
1093 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
1094 {
1095   if(mRelayoutData)
1096   {
1097     return mRelayoutData->GetResizePolicy(dimension);
1098   }
1099
1100   return ResizePolicy::DEFAULT;
1101 }
1102
1103 void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
1104 {
1105   EnsureRelayouter();
1106
1107   mRelayoutData->sizeSetPolicy = policy;
1108
1109   // Trigger relayout on this control
1110   RelayoutRequest();
1111 }
1112
1113 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1114 {
1115   if(mRelayoutData)
1116   {
1117     return mRelayoutData->sizeSetPolicy;
1118   }
1119
1120   return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1121 }
1122
1123 void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
1124 {
1125   EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1126 }
1127
1128 Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
1129 {
1130   if(mRelayoutData)
1131   {
1132     return mRelayoutData->GetDimensionDependency(dimension);
1133   }
1134
1135   return Dimension::ALL_DIMENSIONS; // Default
1136 }
1137
1138 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
1139 {
1140   // If relayout data has not been allocated yet and the client is requesting
1141   // to disable it, do nothing
1142   if(mRelayoutData || relayoutEnabled)
1143   {
1144     EnsureRelayouter();
1145
1146     DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
1147
1148     mRelayoutData->relayoutEnabled = relayoutEnabled;
1149   }
1150 }
1151
1152 bool Actor::IsRelayoutEnabled() const
1153 {
1154   // Assume that if relayout data has not been allocated yet then
1155   // relayout is disabled
1156   return mRelayoutData && mRelayoutData->relayoutEnabled;
1157 }
1158
1159 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
1160 {
1161   EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1162 }
1163
1164 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
1165 {
1166   return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1167 }
1168
1169 bool Actor::RelayoutPossible(Dimension::Type dimension) const
1170 {
1171   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
1172 }
1173
1174 bool Actor::RelayoutRequired(Dimension::Type dimension) const
1175 {
1176   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
1177 }
1178
1179 uint32_t Actor::AddRenderer(Renderer& renderer)
1180 {
1181   if(!mRenderers)
1182   {
1183     mRenderers = new RendererContainer;
1184   }
1185
1186   uint32_t    index       = static_cast<uint32_t>(mRenderers->size()); //  4,294,967,295 renderers per actor
1187   RendererPtr rendererPtr = RendererPtr(&renderer);
1188   mRenderers->push_back(rendererPtr);
1189   AttachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject());
1190   return index;
1191 }
1192
1193 uint32_t Actor::GetRendererCount() const
1194 {
1195   uint32_t rendererCount(0);
1196   if(mRenderers)
1197   {
1198     rendererCount = static_cast<uint32_t>(mRenderers->size()); //  4,294,967,295 renderers per actor
1199   }
1200
1201   return rendererCount;
1202 }
1203
1204 RendererPtr Actor::GetRendererAt(uint32_t index)
1205 {
1206   RendererPtr renderer;
1207   if(index < GetRendererCount())
1208   {
1209     renderer = (*mRenderers)[index];
1210   }
1211
1212   return renderer;
1213 }
1214
1215 void Actor::RemoveRenderer(Renderer& renderer)
1216 {
1217   if(mRenderers)
1218   {
1219     RendererIter end = mRenderers->end();
1220     for(RendererIter iter = mRenderers->begin(); iter != end; ++iter)
1221     {
1222       if((*iter).Get() == &renderer)
1223       {
1224         mRenderers->erase(iter);
1225         DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject());
1226         break;
1227       }
1228     }
1229   }
1230 }
1231
1232 void Actor::RemoveRenderer(uint32_t index)
1233 {
1234   if(index < GetRendererCount())
1235   {
1236     RendererPtr renderer = (*mRenderers)[index];
1237     DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject());
1238     mRenderers->erase(mRenderers->begin() + index);
1239   }
1240 }
1241
1242 void Actor::SetDrawMode(DrawMode::Type drawMode)
1243 {
1244   // this flag is not animatable so keep the value
1245   mDrawMode = drawMode;
1246
1247   // node is being used in a separate thread; queue a message to set the value
1248   SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1249 }
1250
1251 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1252 {
1253   // only valid when on-stage
1254   if(mScene && OnScene())
1255   {
1256     const RenderTaskList& taskList = mScene->GetRenderTaskList();
1257
1258     Vector2 converted(screenX, screenY);
1259
1260     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1261     uint32_t taskCount = taskList.GetTaskCount();
1262     for(uint32_t i = taskCount; i > 0; --i)
1263     {
1264       RenderTaskPtr task = taskList.GetTask(i - 1);
1265       if(ScreenToLocal(*task, localX, localY, screenX, screenY))
1266       {
1267         // found a task where this conversion was ok so return
1268         return true;
1269       }
1270     }
1271   }
1272   return false;
1273 }
1274
1275 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1276 {
1277   bool retval = false;
1278   // only valid when on-stage
1279   if(OnScene())
1280   {
1281     CameraActor* camera = renderTask.GetCameraActor();
1282     if(camera)
1283     {
1284       Viewport viewport;
1285       renderTask.GetViewport(viewport);
1286
1287       // need to translate coordinates to render tasks coordinate space
1288       Vector2 converted(screenX, screenY);
1289       if(renderTask.TranslateCoordinates(converted))
1290       {
1291         retval = ScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y);
1292       }
1293     }
1294   }
1295   return retval;
1296 }
1297
1298 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1299 {
1300   return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1301 }
1302
1303 ActorGestureData& Actor::GetGestureData()
1304 {
1305   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1306   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1307   if(nullptr == mGestureData)
1308   {
1309     mGestureData = new ActorGestureData;
1310   }
1311   return *mGestureData;
1312 }
1313
1314 bool Actor::IsGestureRequired(GestureType::Value type) const
1315 {
1316   return mGestureData && mGestureData->IsGestureRequired(type);
1317 }
1318
1319 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1320 {
1321   return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1322 }
1323
1324 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1325 {
1326   return EmitConsumingSignal(*this, mTouchedSignal, touch);
1327 }
1328
1329 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1330 {
1331   return EmitConsumingSignal(*this, mHoveredSignal, event);
1332 }
1333
1334 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1335 {
1336   return EmitConsumingSignal(*this, mWheelEventSignal, event);
1337 }
1338
1339 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1340 {
1341   EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1342 }
1343
1344 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1345 {
1346   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1347 }
1348
1349 void Actor::EmitChildAddedSignal(Actor& child)
1350 {
1351   EmitSignal(child, mChildAddedSignal);
1352 }
1353
1354 void Actor::EmitChildRemovedSignal(Actor& child)
1355 {
1356   EmitSignal(child, mChildRemovedSignal);
1357 }
1358
1359 bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1360 {
1361   bool   connected(true);
1362   Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
1363
1364   if(0 == signalName.compare(SIGNAL_HOVERED))
1365   {
1366     actor->HoveredSignal().Connect(tracker, functor);
1367   }
1368   else if(0 == signalName.compare(SIGNAL_WHEEL_EVENT))
1369   {
1370     actor->WheelEventSignal().Connect(tracker, functor);
1371   }
1372   else if(0 == signalName.compare(SIGNAL_ON_SCENE))
1373   {
1374     actor->OnSceneSignal().Connect(tracker, functor);
1375   }
1376   else if(0 == signalName.compare(SIGNAL_OFF_SCENE))
1377   {
1378     actor->OffSceneSignal().Connect(tracker, functor);
1379   }
1380   else if(0 == signalName.compare(SIGNAL_ON_RELAYOUT))
1381   {
1382     actor->OnRelayoutSignal().Connect(tracker, functor);
1383   }
1384   else if(0 == signalName.compare(SIGNAL_TOUCHED))
1385   {
1386     actor->TouchedSignal().Connect(tracker, functor);
1387   }
1388   else if(0 == signalName.compare(SIGNAL_VISIBILITY_CHANGED))
1389   {
1390     actor->VisibilityChangedSignal().Connect(tracker, functor);
1391   }
1392   else if(0 == signalName.compare(SIGNAL_LAYOUT_DIRECTION_CHANGED))
1393   {
1394     actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
1395   }
1396   else if(0 == signalName.compare(SIGNAL_CHILD_ADDED))
1397   {
1398     actor->ChildAddedSignal().Connect(tracker, functor);
1399   }
1400   else if(0 == signalName.compare(SIGNAL_CHILD_REMOVED))
1401   {
1402     actor->ChildRemovedSignal().Connect(tracker, functor);
1403   }
1404   else
1405   {
1406     // signalName does not match any signal
1407     connected = false;
1408   }
1409
1410   return connected;
1411 }
1412
1413 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1414 : Object(&node),
1415   mScene(nullptr),
1416   mParent(nullptr),
1417   mChildren(nullptr),
1418   mRenderers(nullptr),
1419   mParentOrigin(nullptr),
1420   mAnchorPoint(nullptr),
1421   mRelayoutData(nullptr),
1422   mGestureData(nullptr),
1423   mInterceptTouchedSignal(),
1424   mTouchedSignal(),
1425   mHoveredSignal(),
1426   mWheelEventSignal(),
1427   mOnSceneSignal(),
1428   mOffSceneSignal(),
1429   mOnRelayoutSignal(),
1430   mVisibilityChangedSignal(),
1431   mLayoutDirectionChangedSignal(),
1432   mChildAddedSignal(),
1433   mChildRemovedSignal(),
1434   mChildOrderChangedSignal(),
1435   mTargetOrientation(Quaternion::IDENTITY),
1436   mTargetColor(Color::WHITE),
1437   mTargetSize(Vector3::ZERO),
1438   mTargetPosition(Vector3::ZERO),
1439   mTargetScale(Vector3::ONE),
1440   mAnimatedSize(Vector3::ZERO),
1441   mTouchAreaOffset(0, 0, 0, 0),
1442   mName(),
1443   mSortedDepth(0u),
1444   mDepth(0u),
1445   mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1446   mIsRoot(ROOT_LAYER == derivedType),
1447   mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1448   mIsOnScene(false),
1449   mSensitive(true),
1450   mLeaveRequired(false),
1451   mKeyboardFocusable(false),
1452   mTouchFocusable(false),
1453   mOnSceneSignalled(false),
1454   mInsideOnSizeSet(false),
1455   mInheritPosition(true),
1456   mInheritOrientation(true),
1457   mInheritScale(true),
1458   mPositionUsesAnchorPoint(true),
1459   mVisible(true),
1460   mInheritLayoutDirection(true),
1461   mCaptureAllTouchAfterStart(false),
1462   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1463   mDrawMode(DrawMode::NORMAL),
1464   mColorMode(Node::DEFAULT_COLOR_MODE),
1465   mClippingMode(ClippingMode::DISABLED)
1466 {
1467 }
1468
1469 void Actor::Initialize()
1470 {
1471   OnInitialize();
1472
1473   GetEventThreadServices().RegisterObject(this);
1474 }
1475
1476 Actor::~Actor()
1477 {
1478   // Remove mParent pointers from children even if we're destroying core,
1479   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1480   if(mChildren)
1481   {
1482     for(const auto& actor : *mChildren)
1483     {
1484       actor->SetParent(nullptr);
1485     }
1486   }
1487   delete mChildren;
1488   delete mRenderers;
1489
1490   // Guard to allow handle destruction after Core has been destroyed
1491   if(EventThreadServices::IsCoreRunning())
1492   {
1493     // Root layer will destroy its node in its own destructor
1494     if(!mIsRoot)
1495     {
1496       DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1497
1498       GetEventThreadServices().UnregisterObject(this);
1499     }
1500   }
1501
1502   // Cleanup optional gesture data
1503   delete mGestureData;
1504
1505   // Cleanup optional parent origin and anchor
1506   delete mParentOrigin;
1507   delete mAnchorPoint;
1508
1509   // Delete optional relayout data
1510   delete mRelayoutData;
1511 }
1512
1513 void Actor::ConnectToScene(uint32_t parentDepth)
1514 {
1515   // This container is used instead of walking the Actor hierarchy.
1516   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1517   ActorContainer connectionList;
1518
1519   if(mScene)
1520   {
1521     mScene->RequestRebuildDepthTree();
1522   }
1523
1524   // This stage is atomic i.e. not interrupted by user callbacks.
1525   RecursiveConnectToScene(connectionList, parentDepth + 1);
1526
1527   // Notify applications about the newly connected actors.
1528   for(const auto& actor : connectionList)
1529   {
1530     actor->NotifyStageConnection();
1531   }
1532
1533   RelayoutRequest();
1534 }
1535
1536 void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
1537 {
1538   DALI_ASSERT_ALWAYS(!OnScene());
1539
1540   mIsOnScene = true;
1541   mDepth     = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
1542
1543   ConnectToSceneGraph();
1544
1545   // Notification for internal derived classes
1546   OnSceneConnectionInternal();
1547
1548   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1549   connectionList.push_back(ActorPtr(this));
1550
1551   // Recursively connect children
1552   if(mChildren)
1553   {
1554     for(const auto& actor : *mChildren)
1555     {
1556       actor->SetScene(*mScene);
1557       actor->RecursiveConnectToScene(connectionList, depth + 1);
1558     }
1559   }
1560 }
1561
1562 /**
1563  * This method is called when the Actor is connected to the Stage.
1564  * The parent must have added its Node to the scene-graph.
1565  * The child must connect its Node to the parent's Node.
1566  * This is recursive; the child calls ConnectToScene() for its children.
1567  */
1568 void Actor::ConnectToSceneGraph()
1569 {
1570   DALI_ASSERT_DEBUG(mParent != NULL);
1571
1572   // Reparent Node in next Update
1573   ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode());
1574
1575   // Request relayout on all actors that are added to the scenegraph
1576   RelayoutRequest();
1577
1578   // Notification for Object::Observers
1579   OnSceneObjectAdd();
1580 }
1581
1582 void Actor::NotifyStageConnection()
1583 {
1584   // Actors can be removed (in a callback), before the on-stage stage is reported.
1585   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1586   if(OnScene() && !mOnSceneSignalled)
1587   {
1588     // Notification for external (CustomActor) derived classes
1589     OnSceneConnectionExternal(mDepth);
1590
1591     if(!mOnSceneSignal.Empty())
1592     {
1593       Dali::Actor handle(this);
1594       mOnSceneSignal.Emit(handle);
1595     }
1596
1597     // Guard against Remove during callbacks
1598     if(OnScene())
1599     {
1600       mOnSceneSignalled = true; // signal required next time Actor is removed
1601     }
1602   }
1603 }
1604
1605 void Actor::DisconnectFromStage()
1606 {
1607   // This container is used instead of walking the Actor hierachy.
1608   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1609   ActorContainer disconnectionList;
1610
1611   if(mScene)
1612   {
1613     mScene->RequestRebuildDepthTree();
1614   }
1615
1616   // This stage is atomic i.e. not interrupted by user callbacks
1617   RecursiveDisconnectFromStage(disconnectionList);
1618
1619   // Notify applications about the newly disconnected actors.
1620   for(const auto& actor : disconnectionList)
1621   {
1622     actor->NotifyStageDisconnection();
1623   }
1624 }
1625
1626 void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
1627 {
1628   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1629   mIsOnScene = false;
1630
1631   // Recursively disconnect children
1632   if(mChildren)
1633   {
1634     for(const auto& child : *mChildren)
1635     {
1636       child->RecursiveDisconnectFromStage(disconnectionList);
1637     }
1638   }
1639
1640   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1641   disconnectionList.push_back(ActorPtr(this));
1642
1643   // Notification for internal derived classes
1644   OnSceneDisconnectionInternal();
1645
1646   DisconnectFromSceneGraph();
1647 }
1648
1649 /**
1650  * This method is called by an actor or its parent, before a node removal message is sent.
1651  * This is recursive; the child calls DisconnectFromStage() for its children.
1652  */
1653 void Actor::DisconnectFromSceneGraph()
1654 {
1655   // Notification for Object::Observers
1656   OnSceneObjectRemove();
1657 }
1658
1659 void Actor::NotifyStageDisconnection()
1660 {
1661   // Actors can be added (in a callback), before the off-stage state is reported.
1662   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1663   // only do this step if there is a stage, i.e. Core is not being shut down
1664   if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1665   {
1666     // Notification for external (CustomeActor) derived classes
1667     OnSceneDisconnectionExternal();
1668
1669     if(!mOffSceneSignal.Empty())
1670     {
1671       Dali::Actor handle(this);
1672       mOffSceneSignal.Emit(handle);
1673     }
1674
1675     // Guard against Add during callbacks
1676     if(!OnScene())
1677     {
1678       mOnSceneSignalled = false; // signal required next time Actor is added
1679     }
1680   }
1681 }
1682
1683 bool Actor::IsNodeConnected() const
1684 {
1685   bool connected(false);
1686
1687   if(OnScene())
1688   {
1689     if(IsRoot() || GetNode().GetParent())
1690     {
1691       connected = true;
1692     }
1693   }
1694
1695   return connected;
1696 }
1697
1698 // This method initiates traversal of the actor tree using depth-first
1699 // traversal to set a depth index based on traversal order. It sends a
1700 // single message to update manager to update all the actor's nodes in
1701 // this tree with the depth index. The sceneGraphNodeDepths vector's
1702 // elements are ordered by depth, and could be used to reduce sorting
1703 // in the update thread.
1704 void Actor::RebuildDepthTree()
1705 {
1706   DALI_LOG_TIMER_START(depthTimer);
1707
1708   // Vector of scene-graph nodes and their depths to send to UpdateManager
1709   // in a single message
1710   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1711
1712   int32_t depthIndex = 1;
1713   DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1714
1715   SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1716   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1717 }
1718
1719 void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
1720 {
1721   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1722   sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
1723
1724   // Create/add to children of this node
1725   if(mChildren)
1726   {
1727     for(const auto& child : *mChildren)
1728     {
1729       Actor* childActor = child.Get();
1730       ++depthIndex;
1731       childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1732     }
1733   }
1734 }
1735
1736 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1737 {
1738   PropertyHandler::SetDefaultProperty(*this, index, property);
1739 }
1740
1741 // TODO: This method needs to be removed
1742 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1743 {
1744   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1745 }
1746
1747 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1748 {
1749   Property::Value value;
1750
1751   if(!GetCachedPropertyValue(index, value))
1752   {
1753     // If property value is not stored in the event-side, then it must be a scene-graph only property
1754     GetCurrentPropertyValue(index, value);
1755   }
1756
1757   return value;
1758 }
1759
1760 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1761 {
1762   Property::Value value;
1763
1764   if(!GetCurrentPropertyValue(index, value))
1765   {
1766     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1767     GetCachedPropertyValue(index, value);
1768   }
1769
1770   return value;
1771 }
1772
1773 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1774 {
1775   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1776 }
1777
1778 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1779 {
1780   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1781   if(!property)
1782   {
1783     // not our property, ask base
1784     property = Object::GetSceneObjectAnimatableProperty(index);
1785   }
1786
1787   return property;
1788 }
1789
1790 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1791 {
1792   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1793   if(!property)
1794   {
1795     // reuse animatable property getter as animatable properties are inputs as well
1796     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1797     property = GetSceneObjectAnimatableProperty(index);
1798   }
1799
1800   return property;
1801 }
1802
1803 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1804 {
1805   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1806   if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1807   {
1808     // ask base
1809     componentIndex = Object::GetPropertyComponentIndex(index);
1810   }
1811
1812   return componentIndex;
1813 }
1814
1815 void Actor::SetParent(Actor* parent)
1816 {
1817   if(parent)
1818   {
1819     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1820
1821     mParent = parent;
1822
1823     mScene = parent->mScene;
1824
1825     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1826        parent->OnScene())
1827     {
1828       // Instruct each actor to create a corresponding node in the scene graph
1829       ConnectToScene(parent->GetHierarchyDepth());
1830     }
1831
1832     // Resolve the name and index for the child properties if any
1833     ResolveChildProperties();
1834   }
1835   else // parent being set to NULL
1836   {
1837     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1838
1839     mParent = nullptr;
1840
1841     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1842        OnScene())
1843     {
1844       // Disconnect the Node & its children from the scene-graph.
1845       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1846
1847       // Instruct each actor to discard pointers to the scene-graph
1848       DisconnectFromStage();
1849     }
1850
1851     mScene = nullptr;
1852   }
1853 }
1854
1855 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1856 {
1857   bool   done  = false;
1858   Actor* actor = dynamic_cast<Actor*>(object);
1859
1860   if(actor)
1861   {
1862     if(0 == actionName.compare(ACTION_SHOW))
1863     {
1864       actor->SetVisible(true);
1865       done = true;
1866     }
1867     else if(0 == actionName.compare(ACTION_HIDE))
1868     {
1869       actor->SetVisible(false);
1870       done = true;
1871     }
1872   }
1873
1874   return done;
1875 }
1876
1877 Rect<> Actor::CalculateScreenExtents() const
1878 {
1879   auto    screenPosition    = GetCurrentScreenPosition();
1880   Vector3 size              = GetCurrentSize() * GetCurrentWorldScale();
1881   Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1882   Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1883   return {position.x, position.y, size.x, size.y};
1884 }
1885
1886 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1887 {
1888   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1889 }
1890
1891 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1892 {
1893   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1894 }
1895
1896 Actor::Relayouter& Actor::EnsureRelayouter()
1897 {
1898   // Assign relayouter
1899   if(!mRelayoutData)
1900   {
1901     mRelayoutData = new Relayouter();
1902   }
1903
1904   return *mRelayoutData;
1905 }
1906
1907 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1908 {
1909   // Check if actor is dependent on parent
1910   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1911   {
1912     if((dimension & (1 << i)))
1913     {
1914       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1915       if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1916       {
1917         return true;
1918       }
1919     }
1920   }
1921
1922   return false;
1923 }
1924
1925 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1926 {
1927   // Check if actor is dependent on children
1928   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1929   {
1930     if((dimension & (1 << i)))
1931     {
1932       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1933       switch(resizePolicy)
1934       {
1935         case ResizePolicy::FIT_TO_CHILDREN:
1936         case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1937         {
1938           return true;
1939         }
1940
1941         default:
1942         {
1943           break;
1944         }
1945       }
1946     }
1947   }
1948
1949   return false;
1950 }
1951
1952 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1953 {
1954   return Actor::RelayoutDependentOnChildren(dimension);
1955 }
1956
1957 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1958 {
1959   // Check each possible dimension and see if it is dependent on the input one
1960   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1961   {
1962     if(dimension & (1 << i))
1963     {
1964       return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1965     }
1966   }
1967
1968   return false;
1969 }
1970
1971 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1972 {
1973   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1974   {
1975     if(dimension & (1 << i))
1976     {
1977       mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1978     }
1979   }
1980 }
1981
1982 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1983 {
1984   // If more than one dimension is requested, just return the first one found
1985   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1986   {
1987     if((dimension & (1 << i)))
1988     {
1989       return mRelayoutData->negotiatedDimensions[i];
1990     }
1991   }
1992
1993   return 0.0f; // Default
1994 }
1995
1996 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1997 {
1998   EnsureRelayouter().SetPadding(padding, dimension);
1999 }
2000
2001 Vector2 Actor::GetPadding(Dimension::Type dimension) const
2002 {
2003   if(mRelayoutData)
2004   {
2005     // If more than one dimension is requested, just return the first one found
2006     for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2007     {
2008       if((dimension & (1 << i)))
2009       {
2010         return mRelayoutData->dimensionPadding[i];
2011       }
2012     }
2013   }
2014
2015   return Relayouter::DEFAULT_DIMENSION_PADDING;
2016 }
2017
2018 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
2019 {
2020   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2021 }
2022
2023 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
2024 {
2025   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2026 }
2027
2028 float Actor::GetHeightForWidthBase(float width)
2029 {
2030   float height = 0.0f;
2031
2032   const Vector3 naturalSize = GetNaturalSize();
2033   if(naturalSize.width > 0.0f)
2034   {
2035     height = naturalSize.height * width / naturalSize.width;
2036   }
2037   else // we treat 0 as 1:1 aspect ratio
2038   {
2039     height = width;
2040   }
2041
2042   return height;
2043 }
2044
2045 float Actor::GetWidthForHeightBase(float height)
2046 {
2047   float width = 0.0f;
2048
2049   const Vector3 naturalSize = GetNaturalSize();
2050   if(naturalSize.height > 0.0f)
2051   {
2052     width = naturalSize.width * height / naturalSize.height;
2053   }
2054   else // we treat 0 as 1:1 aspect ratio
2055   {
2056     width = height;
2057   }
2058
2059   return width;
2060 }
2061
2062 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
2063 {
2064   // Fill to parent, taking size mode factor into account
2065   switch(child.GetResizePolicy(dimension))
2066   {
2067     case ResizePolicy::FILL_TO_PARENT:
2068     {
2069       return GetLatestSize(dimension);
2070     }
2071
2072     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2073     {
2074       return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2075     }
2076
2077     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2078     {
2079       return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2080     }
2081
2082     default:
2083     {
2084       return GetLatestSize(dimension);
2085     }
2086   }
2087 }
2088
2089 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
2090 {
2091   // Can be overridden in derived class
2092   return CalculateChildSizeBase(child, dimension);
2093 }
2094
2095 float Actor::GetHeightForWidth(float width)
2096 {
2097   // Can be overridden in derived class
2098   return GetHeightForWidthBase(width);
2099 }
2100
2101 float Actor::GetWidthForHeight(float height)
2102 {
2103   // Can be overridden in derived class
2104   return GetWidthForHeightBase(height);
2105 }
2106
2107 float Actor::GetLatestSize(Dimension::Type dimension) const
2108 {
2109   return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
2110 }
2111
2112 float Actor::GetRelayoutSize(Dimension::Type dimension) const
2113 {
2114   Vector2 padding = GetPadding(dimension);
2115
2116   return GetLatestSize(dimension) + padding.x + padding.y;
2117 }
2118
2119 float Actor::NegotiateFromParent(Dimension::Type dimension)
2120 {
2121   Actor* parent = GetParent();
2122   if(parent)
2123   {
2124     Vector2 padding(GetPadding(dimension));
2125     Vector2 parentPadding(parent->GetPadding(dimension));
2126     return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2127   }
2128
2129   return 0.0f;
2130 }
2131
2132 float Actor::NegotiateFromChildren(Dimension::Type dimension)
2133 {
2134   float maxDimensionPoint = 0.0f;
2135
2136   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2137   {
2138     ActorPtr child = GetChildAt(i);
2139
2140     if(!child->RelayoutDependentOnParent(dimension))
2141     {
2142       // Calculate the min and max points that the children range across
2143       float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
2144       float dimensionSize = child->GetRelayoutSize(dimension);
2145       maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
2146     }
2147   }
2148
2149   return maxDimensionPoint;
2150 }
2151
2152 float Actor::GetSize(Dimension::Type dimension) const
2153 {
2154   return GetDimensionValue(mTargetSize, dimension);
2155 }
2156
2157 float Actor::GetNaturalSize(Dimension::Type dimension) const
2158 {
2159   return GetDimensionValue(GetNaturalSize(), dimension);
2160 }
2161
2162 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
2163 {
2164   switch(GetResizePolicy(dimension))
2165   {
2166     case ResizePolicy::USE_NATURAL_SIZE:
2167     {
2168       return GetNaturalSize(dimension);
2169     }
2170
2171     case ResizePolicy::FIXED:
2172     {
2173       return GetDimensionValue(GetPreferredSize(), dimension);
2174     }
2175
2176     case ResizePolicy::USE_ASSIGNED_SIZE:
2177     {
2178       return GetDimensionValue(maximumSize, dimension);
2179     }
2180
2181     case ResizePolicy::FILL_TO_PARENT:
2182     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2183     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2184     {
2185       return NegotiateFromParent(dimension);
2186     }
2187
2188     case ResizePolicy::FIT_TO_CHILDREN:
2189     {
2190       return NegotiateFromChildren(dimension);
2191     }
2192
2193     case ResizePolicy::DIMENSION_DEPENDENCY:
2194     {
2195       const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2196
2197       // Custom rules
2198       if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2199       {
2200         return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2201       }
2202
2203       if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2204       {
2205         return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2206       }
2207
2208       break;
2209     }
2210
2211     default:
2212     {
2213       break;
2214     }
2215   }
2216
2217   return 0.0f; // Default
2218 }
2219
2220 void Actor::NegotiateDimension(Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack)
2221 {
2222   // Check if it needs to be negotiated
2223   if(IsLayoutDirty(dimension) && !IsLayoutNegotiated(dimension))
2224   {
2225     // Check that we havn't gotten into an infinite loop
2226     ActorDimensionPair searchActor    = ActorDimensionPair(this, dimension);
2227     bool               recursionFound = false;
2228     for(auto& element : recursionStack)
2229     {
2230       if(element == searchActor)
2231       {
2232         recursionFound = true;
2233         break;
2234       }
2235     }
2236
2237     if(!recursionFound)
2238     {
2239       // Record the path that we have taken
2240       recursionStack.push_back(ActorDimensionPair(this, dimension));
2241
2242       // Dimension dependency check
2243       for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2244       {
2245         Dimension::Type dimensionToCheck = static_cast<Dimension::Type>(1 << i);
2246
2247         if(RelayoutDependentOnDimension(dimension, dimensionToCheck))
2248         {
2249           NegotiateDimension(dimensionToCheck, allocatedSize, recursionStack);
2250         }
2251       }
2252
2253       // Parent dependency check
2254       Actor* parent = GetParent();
2255       if(parent && RelayoutDependentOnParent(dimension))
2256       {
2257         parent->NegotiateDimension(dimension, allocatedSize, recursionStack);
2258       }
2259
2260       // Children dependency check
2261       if(RelayoutDependentOnChildren(dimension))
2262       {
2263         for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2264         {
2265           ActorPtr child = GetChildAt(i);
2266
2267           // Only relayout child first if it is not dependent on this actor
2268           if(!child->RelayoutDependentOnParent(dimension))
2269           {
2270             child->NegotiateDimension(dimension, allocatedSize, recursionStack);
2271           }
2272         }
2273       }
2274
2275       // For deriving classes
2276       OnCalculateRelayoutSize(dimension);
2277
2278       // All dependencies checked, calculate the size and set negotiated flag
2279       const float newSize = Relayouter::ClampDimension(*this, CalculateSize(dimension, allocatedSize), dimension);
2280
2281       SetNegotiatedDimension(newSize, dimension);
2282       SetLayoutNegotiated(true, dimension);
2283
2284       // For deriving classes
2285       OnLayoutNegotiated(newSize, dimension);
2286
2287       // This actor has been successfully processed, pop it off the recursion stack
2288       recursionStack.pop_back();
2289     }
2290     else
2291     {
2292       // TODO: Break infinite loop
2293       SetLayoutNegotiated(true, dimension);
2294     }
2295   }
2296 }
2297
2298 void Actor::NegotiateDimensions(const Vector2& allocatedSize)
2299 {
2300   // Negotiate all dimensions that require it
2301   ActorDimensionStack recursionStack;
2302
2303   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2304   {
2305     const Dimension::Type dimension = static_cast<Dimension::Type>(1 << i);
2306
2307     // Negotiate
2308     NegotiateDimension(dimension, allocatedSize, recursionStack);
2309   }
2310 }
2311
2312 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2313 {
2314   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2315 }
2316
2317 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2318 {
2319   // Do the set actor size
2320   Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2321
2322   // Adjust for size set policy
2323   negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2324
2325   // Lock the flag to stop recursive relayouts on set size
2326   mRelayoutData->insideRelayout = true;
2327   SetSize(negotiatedSize);
2328   mRelayoutData->insideRelayout = false;
2329
2330   // Clear flags for all dimensions
2331   SetLayoutDirty(false);
2332
2333   // Give deriving classes a chance to respond
2334   OnRelayout(negotiatedSize, container);
2335
2336   if(!mOnRelayoutSignal.Empty())
2337   {
2338     Dali::Actor handle(this);
2339     mOnRelayoutSignal.Emit(handle);
2340   }
2341 }
2342
2343 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2344 {
2345   // Force a size negotiation for actors that has assigned size during relayout
2346   // This is required as otherwise the flags that force a relayout will not
2347   // necessarilly be set. This will occur if the actor has already been laid out.
2348   // The dirty flags are then cleared. Then if the actor is added back into the
2349   // relayout container afterwards, the dirty flags would still be clear...
2350   // causing a relayout to be skipped. Here we force any actors added to the
2351   // container to be relayed out.
2352   DALI_LOG_TIMER_START(NegSizeTimer1);
2353
2354   if(GetUseAssignedSize(Dimension::WIDTH))
2355   {
2356     SetLayoutNegotiated(false, Dimension::WIDTH);
2357   }
2358   if(GetUseAssignedSize(Dimension::HEIGHT))
2359   {
2360     SetLayoutNegotiated(false, Dimension::HEIGHT);
2361   }
2362
2363   // Do the negotiation
2364   NegotiateDimensions(allocatedSize);
2365
2366   // Set the actor size
2367   SetNegotiatedSize(container);
2368
2369   // Negotiate down to children
2370   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2371   {
2372     ActorPtr child = GetChildAt(i);
2373
2374     // Forces children that have already been laid out to be relayed out
2375     // if they have assigned size during relayout.
2376     if(child->GetUseAssignedSize(Dimension::WIDTH))
2377     {
2378       child->SetLayoutNegotiated(false, Dimension::WIDTH);
2379       child->SetLayoutDirty(true, Dimension::WIDTH);
2380     }
2381
2382     if(child->GetUseAssignedSize(Dimension::HEIGHT))
2383     {
2384       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2385       child->SetLayoutDirty(true, Dimension::HEIGHT);
2386     }
2387
2388     // Only relayout if required
2389     if(child->RelayoutRequired())
2390     {
2391       container.Add(Dali::Actor(child.Get()), mTargetSize.GetVectorXY());
2392     }
2393   }
2394   DALI_LOG_TIMER_END(NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2395 }
2396
2397 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2398 {
2399   if(mRelayoutData)
2400   {
2401     mRelayoutData->SetUseAssignedSize(use, dimension);
2402   }
2403 }
2404
2405 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2406 {
2407   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2408 }
2409
2410 void Actor::RelayoutRequest(Dimension::Type dimension)
2411 {
2412   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2413   if(relayoutController)
2414   {
2415     Dali::Actor self(this);
2416     relayoutController->RequestRelayout(self, dimension);
2417   }
2418 }
2419
2420 void Actor::SetPreferredSize(const Vector2& size)
2421 {
2422   EnsureRelayouter();
2423
2424   // If valid width or height, then set the resize policy to FIXED
2425   // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
2426   // then change to FIXED as well
2427
2428   if(size.width > 0.0f || GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DEFAULT)
2429   {
2430     SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
2431   }
2432
2433   if(size.height > 0.0f || GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DEFAULT)
2434   {
2435     SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
2436   }
2437
2438   mRelayoutData->preferredSize = size;
2439
2440   mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2441
2442   RelayoutRequest();
2443 }
2444
2445 Vector2 Actor::GetPreferredSize() const
2446 {
2447   if(mRelayoutData)
2448   {
2449     return Vector2(mRelayoutData->preferredSize);
2450   }
2451
2452   return Relayouter::DEFAULT_PREFERRED_SIZE;
2453 }
2454
2455 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2456 {
2457   EnsureRelayouter().SetMinimumSize(size, dimension);
2458   RelayoutRequest();
2459 }
2460
2461 float Actor::GetMinimumSize(Dimension::Type dimension) const
2462 {
2463   if(mRelayoutData)
2464   {
2465     return mRelayoutData->GetMinimumSize(dimension);
2466   }
2467
2468   return 0.0f; // Default
2469 }
2470
2471 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2472 {
2473   EnsureRelayouter().SetMaximumSize(size, dimension);
2474   RelayoutRequest();
2475 }
2476
2477 float Actor::GetMaximumSize(Dimension::Type dimension) const
2478 {
2479   if(mRelayoutData)
2480   {
2481     return mRelayoutData->GetMaximumSize(dimension);
2482   }
2483
2484   return FLT_MAX; // Default
2485 }
2486
2487 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2488 {
2489   if(mVisible != visible)
2490   {
2491     if(sendMessage == SendMessage::TRUE)
2492     {
2493       // node is being used in a separate thread; queue a message to set the value & base value
2494       SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2495     }
2496
2497     mVisible = visible;
2498
2499     // Emit the signal on this actor and all its children
2500     EmitVisibilityChangedSignalRecursively(this, visible, DevelActor::VisibilityChange::SELF);
2501   }
2502 }
2503
2504 void Actor::SetSiblingOrder(uint32_t order)
2505 {
2506   if(mParent)
2507   {
2508     ActorContainer& siblings     = *(mParent->mChildren);
2509     uint32_t        currentOrder = GetSiblingOrder();
2510
2511     if(order != currentOrder)
2512     {
2513       if(order == 0)
2514       {
2515         LowerToBottom();
2516       }
2517       else if(order < siblings.size() - 1)
2518       {
2519         if(order > currentOrder)
2520         {
2521           RaiseAbove(*siblings[order]);
2522         }
2523         else
2524         {
2525           LowerBelow(*siblings[order]);
2526         }
2527       }
2528       else
2529       {
2530         RaiseToTop();
2531       }
2532     }
2533   }
2534 }
2535
2536 uint32_t Actor::GetSiblingOrder() const
2537 {
2538   uint32_t order = 0;
2539
2540   if(mParent)
2541   {
2542     ActorContainer& siblings = *(mParent->mChildren);
2543     for(std::size_t i = 0; i < siblings.size(); ++i)
2544     {
2545       if(siblings[i] == this)
2546       {
2547         order = static_cast<uint32_t>(i);
2548         break;
2549       }
2550     }
2551   }
2552
2553   return order;
2554 }
2555
2556 void Actor::RequestRebuildDepthTree()
2557 {
2558   if(mIsOnScene)
2559   {
2560     if(mScene)
2561     {
2562       mScene->RequestRebuildDepthTree();
2563     }
2564   }
2565 }
2566
2567 void Actor::Raise()
2568 {
2569   if(mParent)
2570   {
2571     ActorContainer& siblings = *(mParent->mChildren);
2572     if(siblings.back() != this) // If not already at end
2573     {
2574       for(std::size_t i = 0; i < siblings.size(); ++i)
2575       {
2576         if(siblings[i] == this)
2577         {
2578           // Swap with next
2579           ActorPtr next   = siblings[i + 1];
2580           siblings[i + 1] = this;
2581           siblings[i]     = next;
2582           break;
2583         }
2584       }
2585     }
2586
2587     Dali::Actor handle(this);
2588     mParent->mChildOrderChangedSignal.Emit(handle);
2589
2590     RequestRebuildDepthTree();
2591   }
2592   else
2593   {
2594     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2595   }
2596 }
2597
2598 void Actor::Lower()
2599 {
2600   if(mParent)
2601   {
2602     ActorContainer& siblings = *(mParent->mChildren);
2603     if(siblings.front() != this) // If not already at beginning
2604     {
2605       for(std::size_t i = 1; i < siblings.size(); ++i)
2606       {
2607         if(siblings[i] == this)
2608         {
2609           // Swap with previous
2610           ActorPtr previous = siblings[i - 1];
2611           siblings[i - 1]   = this;
2612           siblings[i]       = previous;
2613           break;
2614         }
2615       }
2616     }
2617
2618     Dali::Actor handle(this);
2619     mParent->mChildOrderChangedSignal.Emit(handle);
2620
2621     RequestRebuildDepthTree();
2622   }
2623   else
2624   {
2625     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2626   }
2627 }
2628
2629 void Actor::RaiseToTop()
2630 {
2631   if(mParent)
2632   {
2633     ActorContainer& siblings = *(mParent->mChildren);
2634     if(siblings.back() != this) // If not already at end
2635     {
2636       auto iter = std::find(siblings.begin(), siblings.end(), this);
2637       if(iter != siblings.end())
2638       {
2639         siblings.erase(iter);
2640         siblings.push_back(ActorPtr(this));
2641       }
2642     }
2643
2644     Dali::Actor handle(this);
2645     mParent->mChildOrderChangedSignal.Emit(handle);
2646
2647     RequestRebuildDepthTree();
2648   }
2649   else
2650   {
2651     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2652   }
2653 }
2654
2655 void Actor::LowerToBottom()
2656 {
2657   if(mParent)
2658   {
2659     ActorContainer& siblings = *(mParent->mChildren);
2660     if(siblings.front() != this) // If not already at bottom,
2661     {
2662       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2663
2664       auto iter = std::find(siblings.begin(), siblings.end(), this);
2665       if(iter != siblings.end())
2666       {
2667         siblings.erase(iter);
2668         siblings.insert(siblings.begin(), thisPtr);
2669       }
2670     }
2671
2672     Dali::Actor handle(this);
2673     mParent->mChildOrderChangedSignal.Emit(handle);
2674
2675     RequestRebuildDepthTree();
2676   }
2677   else
2678   {
2679     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2680   }
2681 }
2682
2683 void Actor::RaiseAbove(Internal::Actor& target)
2684 {
2685   if(mParent)
2686   {
2687     ActorContainer& siblings = *(mParent->mChildren);
2688     if(siblings.back() != this && target.mParent == mParent) // If not already at top
2689     {
2690       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2691
2692       auto targetIter = std::find(siblings.begin(), siblings.end(), &target);
2693       auto thisIter   = std::find(siblings.begin(), siblings.end(), this);
2694       if(thisIter < targetIter)
2695       {
2696         siblings.erase(thisIter);
2697         // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2698         // invalidate thisIter)
2699         targetIter = std::find(siblings.begin(), siblings.end(), &target);
2700         ++targetIter;
2701         siblings.insert(targetIter, thisPtr);
2702       }
2703
2704       Dali::Actor handle(this);
2705       mParent->mChildOrderChangedSignal.Emit(handle);
2706
2707       RequestRebuildDepthTree();
2708     }
2709   }
2710   else
2711   {
2712     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2713   }
2714 }
2715
2716 void Actor::LowerBelow(Internal::Actor& target)
2717 {
2718   if(mParent)
2719   {
2720     ActorContainer& siblings = *(mParent->mChildren);
2721     if(siblings.front() != this && target.mParent == mParent) // If not already at bottom
2722     {
2723       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2724
2725       auto targetIter = std::find(siblings.begin(), siblings.end(), &target);
2726       auto thisIter   = std::find(siblings.begin(), siblings.end(), this);
2727
2728       if(thisIter > targetIter)
2729       {
2730         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2731         siblings.insert(targetIter, thisPtr);
2732       }
2733
2734       Dali::Actor handle(this);
2735       mParent->mChildOrderChangedSignal.Emit(handle);
2736
2737       RequestRebuildDepthTree();
2738     }
2739   }
2740   else
2741   {
2742     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2743   }
2744 }
2745
2746 void Actor::SetInheritLayoutDirection(bool inherit)
2747 {
2748   if(mInheritLayoutDirection != inherit)
2749   {
2750     mInheritLayoutDirection = inherit;
2751
2752     if(inherit && mParent)
2753     {
2754       InheritLayoutDirectionRecursively(this, mParent->mLayoutDirection);
2755     }
2756   }
2757 }
2758
2759 void Actor::InheritLayoutDirectionRecursively(ActorPtr actor, Dali::LayoutDirection::Type direction, bool set)
2760 {
2761   if(actor && (actor->mInheritLayoutDirection || set))
2762   {
2763     if(actor->mLayoutDirection != direction)
2764     {
2765       actor->mLayoutDirection = direction;
2766       actor->EmitLayoutDirectionChangedSignal(direction);
2767       actor->RelayoutRequest();
2768     }
2769
2770     if(actor->GetChildCount() > 0)
2771     {
2772       for(const auto& child : actor->GetChildrenInternal())
2773       {
2774         InheritLayoutDirectionRecursively(child, direction);
2775       }
2776     }
2777   }
2778 }
2779
2780 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2781 {
2782   // node is being used in a separate thread; queue a message to set the value & base value
2783   SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2784 }
2785
2786 } // namespace Internal
2787
2788 } // namespace Dali