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