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