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