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