[Tizen] Revert "Skip rendering if no animation is currently active"
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25
26 // INTERNAL INCLUDES
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/internal/event/actors/actor-property-handler.h>
36 #include <dali/internal/event/actors/actor-relayouter.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/thread-local-storage.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/integration-api/debug.h>
51
52 using Dali::Internal::SceneGraph::Node;
53 using Dali::Internal::SceneGraph::AnimatableProperty;
54 using Dali::Internal::SceneGraph::PropertyBase;
55
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
59 #endif
60
61 namespace Dali
62 {
63
64 namespace Internal
65 {
66
67 namespace // unnamed namespace
68 {
69
70 // Properties
71
72 /**
73  * We want to discourage the use of property strings (minimize string comparisons),
74  * particularly for the default properties.
75  *              Name                  Type   writable animatable constraint-input  enum for index-checking
76  */
77 DALI_PROPERTY_TABLE_BEGIN
78 DALI_PROPERTY( "parentOrigin",              VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
79 DALI_PROPERTY( "parentOriginX",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
80 DALI_PROPERTY( "parentOriginY",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
81 DALI_PROPERTY( "parentOriginZ",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
82 DALI_PROPERTY( "anchorPoint",               VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
83 DALI_PROPERTY( "anchorPointX",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
84 DALI_PROPERTY( "anchorPointY",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
85 DALI_PROPERTY( "anchorPointZ",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
86 DALI_PROPERTY( "size",                      VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
87 DALI_PROPERTY( "sizeWidth",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
88 DALI_PROPERTY( "sizeHeight",                FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
89 DALI_PROPERTY( "sizeDepth",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
90 DALI_PROPERTY( "position",                  VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
91 DALI_PROPERTY( "positionX",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
92 DALI_PROPERTY( "positionY",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
93 DALI_PROPERTY( "positionZ",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
94 DALI_PROPERTY( "worldPosition",             VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
95 DALI_PROPERTY( "worldPositionX",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
96 DALI_PROPERTY( "worldPositionY",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
97 DALI_PROPERTY( "worldPositionZ",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
98 DALI_PROPERTY( "orientation",               ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
99 DALI_PROPERTY( "worldOrientation",          ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
100 DALI_PROPERTY( "scale",                     VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
101 DALI_PROPERTY( "scaleX",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
102 DALI_PROPERTY( "scaleY",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
103 DALI_PROPERTY( "scaleZ",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
104 DALI_PROPERTY( "worldScale",                VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
105 DALI_PROPERTY( "visible",                   BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
106 DALI_PROPERTY( "color",                     VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
107 DALI_PROPERTY( "colorRed",                  FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
108 DALI_PROPERTY( "colorGreen",                FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
109 DALI_PROPERTY( "colorBlue",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
110 DALI_PROPERTY( "colorAlpha",                FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
111 DALI_PROPERTY( "worldColor",                VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
112 DALI_PROPERTY( "worldMatrix",               MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
113 DALI_PROPERTY( "name",                      STRING,   true,  false, false, Dali::Actor::Property::NAME )
114 DALI_PROPERTY( "sensitive",                 BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
115 DALI_PROPERTY( "leaveRequired",             BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
116 DALI_PROPERTY( "inheritOrientation",        BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
117 DALI_PROPERTY( "inheritScale",              BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
118 DALI_PROPERTY( "colorMode",                 INTEGER,  true,  false, false, Dali::Actor::Property::COLOR_MODE )
119 DALI_PROPERTY( "drawMode",                  INTEGER,  true,  false, false, Dali::Actor::Property::DRAW_MODE )
120 DALI_PROPERTY( "sizeModeFactor",            VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
121 DALI_PROPERTY( "widthResizePolicy",         STRING,   true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
122 DALI_PROPERTY( "heightResizePolicy",        STRING,   true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
123 DALI_PROPERTY( "sizeScalePolicy",           INTEGER,  true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
124 DALI_PROPERTY( "widthForHeight",            BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
125 DALI_PROPERTY( "heightForWidth",            BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
126 DALI_PROPERTY( "padding",                   VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
127 DALI_PROPERTY( "minimumSize",               VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
128 DALI_PROPERTY( "maximumSize",               VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
129 DALI_PROPERTY( "inheritPosition",           BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_POSITION )
130 DALI_PROPERTY( "clippingMode",              STRING,   true,  false, false, Dali::Actor::Property::CLIPPING_MODE )
131 DALI_PROPERTY( "layoutDirection",           STRING,   true,  false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
132 DALI_PROPERTY( "inheritLayoutDirection",    BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
133 DALI_PROPERTY( "opacity",                   FLOAT,    true,  true,  true,  Dali::Actor::Property::OPACITY )
134 DALI_PROPERTY( "screenPosition",            VECTOR2,  false, false, false, Dali::Actor::Property::SCREEN_POSITION )
135 DALI_PROPERTY( "positionUsesAnchorPoint",   BOOLEAN,  true,  false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
136 DALI_PROPERTY( "culled",                    BOOLEAN,  false, false, true,  Dali::Actor::Property::CULLED )
137 DALI_PROPERTY( "id",                        INTEGER,  false, false, false, Dali::Actor::Property::ID )
138 DALI_PROPERTY( "hierarchyDepth",            INTEGER,  false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
139 DALI_PROPERTY( "isRoot",                    BOOLEAN,  false, false, false, Dali::Actor::Property::IS_ROOT )
140 DALI_PROPERTY( "isLayer",                   BOOLEAN,  false, false, false, Dali::Actor::Property::IS_LAYER )
141 DALI_PROPERTY( "connectedToScene",          BOOLEAN,  false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
142 DALI_PROPERTY( "keyboardFocusable",         BOOLEAN,  true,  false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
143 DALI_PROPERTY( "siblingOrder",              INTEGER,  true,  false, false, Dali::DevelActor::Property::SIBLING_ORDER )
144 DALI_PROPERTY( "updateSizeHint",            VECTOR2,  true,  false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
145 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN,  true,  false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
146 DALI_PROPERTY( "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
840 float Actor::GetCurrentOpacity() const
841 {
842   // node is being used in a separate thread; copy the value from the previous update
843   return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
844 }
845
846 const Vector4& Actor::GetCurrentWorldColor() const
847 {
848   return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
849 }
850
851 void Actor::SetColor( const Vector4& color )
852 {
853   mTargetColor = color;
854
855   // node is being used in a separate thread; queue a message to set the value & base value
856   SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
857 }
858
859 void Actor::SetColorRed( float red )
860 {
861   mTargetColor.r = red;
862
863   // node is being used in a separate thread; queue a message to set the value & base value
864   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
865 }
866
867 void Actor::SetColorGreen( float green )
868 {
869   mTargetColor.g = green;
870
871   // node is being used in a separate thread; queue a message to set the value & base value
872   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
873 }
874
875 void Actor::SetColorBlue( float blue )
876 {
877   mTargetColor.b = blue;
878
879   // node is being used in a separate thread; queue a message to set the value & base value
880   SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
881 }
882
883 const Vector4& Actor::GetCurrentColor() const
884 {
885   // node is being used in a separate thread; copy the value from the previous update
886   return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
887 }
888
889 void Actor::SetInheritOrientation( bool inherit )
890 {
891   if( mInheritOrientation != inherit )
892   {
893     // non animatable so keep local copy
894     mInheritOrientation = inherit;
895     // node is being used in a separate thread; queue a message to set the value
896     SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
897   }
898 }
899
900 void Actor::SetSizeModeFactor( const Vector3& factor )
901 {
902   EnsureRelayouter();
903
904   mRelayoutData->sizeModeFactor = factor;
905 }
906
907 const Vector3& Actor::GetSizeModeFactor() const
908 {
909   if ( mRelayoutData )
910   {
911     return mRelayoutData->sizeModeFactor;
912   }
913
914   return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
915 }
916
917 void Actor::SetColorMode( ColorMode colorMode )
918 {
919   // non animatable so keep local copy
920   mColorMode = colorMode;
921   // node is being used in a separate thread; queue a message to set the value
922   SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
923 }
924
925 void Actor::SetSize( float width, float height )
926 {
927   SetSize( Vector2( width, height ) );
928 }
929
930 void Actor::SetSize( float width, float height, float depth )
931 {
932   SetSize( Vector3( width, height, depth ) );
933 }
934
935 void Actor::SetSize( const Vector2& size )
936 {
937   SetSize( Vector3( size.width, size.height, 0.f ) );
938 }
939
940 void Actor::SetSizeInternal( const Vector2& size )
941 {
942   SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
943 }
944
945 void Actor::SetSize( const Vector3& size )
946 {
947   if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
948   {
949     // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
950     SetPreferredSize( size.GetVectorXY() );
951   }
952   else
953   {
954     SetSizeInternal( size );
955   }
956 }
957
958 void Actor::SetSizeInternal( const Vector3& size )
959 {
960   // dont allow recursive loop
961   DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
962   // 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
963   if( ( fabsf( mTargetSize.width - size.width  ) > Math::MACHINE_EPSILON_1 )||
964       ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
965       ( fabsf( mTargetSize.depth - size.depth  ) > Math::MACHINE_EPSILON_1 ) )
966   {
967     mTargetSize = size;
968
969     // node is being used in a separate thread; queue a message to set the value & base value
970     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
971
972     // Notification for derived classes
973     mInsideOnSizeSet = true;
974     OnSizeSet( mTargetSize );
975     mInsideOnSizeSet = false;
976
977     // Raise a relayout request if the flag is not locked
978     if( mRelayoutData && !mRelayoutData->insideRelayout )
979     {
980       RelayoutRequest();
981     }
982   }
983 }
984
985 void Actor::SetWidth( float width )
986 {
987   if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
988   {
989     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
990     mRelayoutData->preferredSize.width = width;
991   }
992   else
993   {
994     mTargetSize.width = width;
995
996     // node is being used in a separate thread; queue a message to set the value & base value
997     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
998   }
999
1000   mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1001
1002   RelayoutRequest();
1003 }
1004
1005 void Actor::SetHeight( float height )
1006 {
1007   if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1008   {
1009     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1010     mRelayoutData->preferredSize.height = height;
1011   }
1012   else
1013   {
1014     mTargetSize.height = height;
1015
1016     // node is being used in a separate thread; queue a message to set the value & base value
1017     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1018   }
1019
1020   mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1021
1022   RelayoutRequest();
1023 }
1024
1025 void Actor::SetDepth( float depth )
1026 {
1027   mTargetSize.depth = depth;
1028
1029   mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1030
1031   // node is being used in a separate thread; queue a message to set the value & base value
1032   SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1033 }
1034
1035 Vector3 Actor::GetTargetSize() const
1036 {
1037   Vector3 size = mTargetSize;
1038
1039   if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1040   {
1041     // Should return animated size if size is animated
1042     size.width = mAnimatedSize.width;
1043   }
1044   else
1045   {
1046     // Should return preferred size if size is fixed as set by SetSize
1047     if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1048     {
1049       size.width = GetPreferredSize().width;
1050     }
1051   }
1052
1053   if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1054   {
1055     size.height = mAnimatedSize.height;
1056   }
1057   else
1058   {
1059     if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1060     {
1061       size.height = GetPreferredSize().height;
1062     }
1063   }
1064
1065   if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1066   {
1067     size.depth = mAnimatedSize.depth;
1068   }
1069
1070   return size;
1071 }
1072
1073 const Vector3& Actor::GetCurrentSize() const
1074 {
1075   // node is being used in a separate thread; copy the value from the previous update
1076   return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1077 }
1078
1079 Vector3 Actor::GetNaturalSize() const
1080 {
1081   // It is up to deriving classes to return the appropriate natural size
1082   return Vector3( 0.0f, 0.0f, 0.0f );
1083 }
1084
1085 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1086 {
1087   EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1088
1089   OnSetResizePolicy( policy, dimension );
1090
1091   // Trigger relayout on this control
1092   RelayoutRequest();
1093 }
1094
1095 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1096 {
1097   if ( mRelayoutData )
1098   {
1099     return mRelayoutData->GetResizePolicy(dimension);
1100   }
1101
1102   return ResizePolicy::DEFAULT;
1103 }
1104
1105 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1106 {
1107   EnsureRelayouter();
1108
1109   mRelayoutData->sizeSetPolicy = policy;
1110
1111   // Trigger relayout on this control
1112   RelayoutRequest();
1113 }
1114
1115 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1116 {
1117   if ( mRelayoutData )
1118   {
1119     return mRelayoutData->sizeSetPolicy;
1120   }
1121
1122   return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1123 }
1124
1125 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1126 {
1127   EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1128 }
1129
1130 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1131 {
1132   if ( mRelayoutData )
1133   {
1134     return mRelayoutData->GetDimensionDependency(dimension);
1135   }
1136
1137   return Dimension::ALL_DIMENSIONS;   // Default
1138 }
1139
1140 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1141 {
1142   // If relayout data has not been allocated yet and the client is requesting
1143   // to disable it, do nothing
1144   if( mRelayoutData || relayoutEnabled )
1145   {
1146     EnsureRelayouter();
1147
1148     DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1149
1150     mRelayoutData->relayoutEnabled = relayoutEnabled;
1151   }
1152 }
1153
1154 bool Actor::IsRelayoutEnabled() const
1155 {
1156   // Assume that if relayout data has not been allocated yet then
1157   // relayout is disabled
1158   return mRelayoutData && mRelayoutData->relayoutEnabled;
1159 }
1160
1161 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1162 {
1163   EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1164 }
1165
1166 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1167 {
1168   return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1169 }
1170
1171 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1172 {
1173   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1174 }
1175
1176 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1177 {
1178   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1179 }
1180
1181 uint32_t Actor::AddRenderer( Renderer& renderer )
1182 {
1183   if( !mRenderers )
1184   {
1185     mRenderers = new RendererContainer;
1186   }
1187
1188   uint32_t index = static_cast<uint32_t>( mRenderers->size() ); //  4,294,967,295 renderers per actor
1189   RendererPtr rendererPtr = RendererPtr( &renderer );
1190   mRenderers->push_back( rendererPtr );
1191   AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1192   return index;
1193 }
1194
1195 uint32_t Actor::GetRendererCount() const
1196 {
1197   uint32_t rendererCount(0);
1198   if( mRenderers )
1199   {
1200     rendererCount = static_cast<uint32_t>( mRenderers->size() ); //  4,294,967,295 renderers per actor
1201   }
1202
1203   return rendererCount;
1204 }
1205
1206 RendererPtr Actor::GetRendererAt( uint32_t index )
1207 {
1208   RendererPtr renderer;
1209   if( index < GetRendererCount() )
1210   {
1211     renderer = ( *mRenderers )[ index ];
1212   }
1213
1214   return renderer;
1215 }
1216
1217 void Actor::RemoveRenderer( Renderer& renderer )
1218 {
1219   if( mRenderers )
1220   {
1221     RendererIter end = mRenderers->end();
1222     for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1223     {
1224       if( (*iter).Get() == &renderer )
1225       {
1226         mRenderers->erase( iter );
1227         DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1228         break;
1229       }
1230     }
1231   }
1232 }
1233
1234 void Actor::RemoveRenderer( uint32_t index )
1235 {
1236   if( index < GetRendererCount() )
1237   {
1238     RendererPtr renderer = ( *mRenderers )[ index ];
1239     DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1240     mRenderers->erase( mRenderers->begin()+index );
1241   }
1242 }
1243
1244 void Actor::SetDrawMode( DrawMode::Type drawMode )
1245 {
1246   // this flag is not animatable so keep the value
1247   mDrawMode = drawMode;
1248
1249   // node is being used in a separate thread; queue a message to set the value
1250   SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1251 }
1252
1253 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1254 {
1255   // only valid when on-stage
1256   if( mScene && OnScene() )
1257   {
1258     const RenderTaskList& taskList = mScene->GetRenderTaskList();
1259
1260     Vector2 converted( screenX, screenY );
1261
1262     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1263     uint32_t taskCount = taskList.GetTaskCount();
1264     for( uint32_t i = taskCount; i > 0; --i )
1265     {
1266       RenderTaskPtr task = taskList.GetTask( i - 1 );
1267       if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1268       {
1269         // found a task where this conversion was ok so return
1270         return true;
1271       }
1272     }
1273   }
1274   return false;
1275 }
1276
1277 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1278 {
1279   bool retval = false;
1280   // only valid when on-stage
1281   if( OnScene() )
1282   {
1283     CameraActor* camera = renderTask.GetCameraActor();
1284     if( camera )
1285     {
1286       Viewport viewport;
1287       renderTask.GetViewport( viewport );
1288
1289       // need to translate coordinates to render tasks coordinate space
1290       Vector2 converted( screenX, screenY );
1291       if( renderTask.TranslateCoordinates( converted ) )
1292       {
1293         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1294       }
1295     }
1296   }
1297   return retval;
1298 }
1299
1300 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1301 {
1302   return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1303 }
1304
1305 ActorGestureData& Actor::GetGestureData()
1306 {
1307   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1308   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1309   if( nullptr == mGestureData )
1310   {
1311     mGestureData = new ActorGestureData;
1312   }
1313   return *mGestureData;
1314 }
1315
1316 bool Actor::IsGestureRequired( GestureType::Value type ) const
1317 {
1318   return mGestureData && mGestureData->IsGestureRequired( type );
1319 }
1320
1321 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1322 {
1323   return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1324 }
1325
1326 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1327 {
1328   return EmitConsumingSignal( *this, mTouchedSignal, touch );
1329 }
1330
1331 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1332 {
1333   return EmitConsumingSignal( *this, mHoveredSignal, event );
1334 }
1335
1336 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1337 {
1338   return EmitConsumingSignal( *this, mWheelEventSignal, event );
1339 }
1340
1341 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1342 {
1343   EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1344 }
1345
1346 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1347 {
1348   EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1349 }
1350
1351 void Actor::EmitChildAddedSignal( Actor& child )
1352 {
1353   EmitSignal( child, mChildAddedSignal );
1354 }
1355
1356 void Actor::EmitChildRemovedSignal( Actor& child )
1357 {
1358   EmitSignal( child, mChildRemovedSignal );
1359 }
1360
1361 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1362 {
1363   bool connected( true );
1364   Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1365
1366   if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1367   {
1368     actor->HoveredSignal().Connect( tracker, functor );
1369   }
1370   else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1371   {
1372     actor->WheelEventSignal().Connect( tracker, functor );
1373   }
1374   else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1375   {
1376     actor->OnSceneSignal().Connect( tracker, functor );
1377   }
1378   else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1379   {
1380     actor->OffSceneSignal().Connect( tracker, functor );
1381   }
1382   else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1383   {
1384     actor->OnRelayoutSignal().Connect( tracker, functor );
1385   }
1386   else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1387   {
1388     actor->TouchedSignal().Connect( tracker, functor );
1389   }
1390   else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1391   {
1392     actor->VisibilityChangedSignal().Connect( tracker, functor );
1393   }
1394   else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1395   {
1396     actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1397   }
1398   else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1399   {
1400     actor->ChildAddedSignal().Connect( tracker, functor );
1401   }
1402   else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1403   {
1404     actor->ChildRemovedSignal().Connect( tracker, functor );
1405   }
1406   else
1407   {
1408     // signalName does not match any signal
1409     connected = false;
1410   }
1411
1412   return connected;
1413 }
1414
1415 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1416 : Object( &node ),
1417   mScene( nullptr ),
1418   mParent( nullptr ),
1419   mChildren( nullptr ),
1420   mRenderers( nullptr ),
1421   mParentOrigin( nullptr ),
1422   mAnchorPoint( nullptr ),
1423   mRelayoutData( nullptr ),
1424   mGestureData( nullptr ),
1425   mInterceptTouchedSignal(),
1426   mTouchedSignal(),
1427   mHoveredSignal(),
1428   mWheelEventSignal(),
1429   mOnSceneSignal(),
1430   mOffSceneSignal(),
1431   mOnRelayoutSignal(),
1432   mVisibilityChangedSignal(),
1433   mLayoutDirectionChangedSignal(),
1434   mChildAddedSignal(),
1435   mChildRemovedSignal(),
1436   mChildOrderChangedSignal(),
1437   mTargetOrientation( Quaternion::IDENTITY ),
1438   mTargetColor( Color::WHITE ),
1439   mTargetSize( Vector3::ZERO ),
1440   mTargetPosition( Vector3::ZERO ),
1441   mTargetScale( Vector3::ONE ),
1442   mAnimatedSize( Vector3::ZERO ),
1443   mTouchDelegateArea( Vector2::ZERO ),
1444   mName(),
1445   mSortedDepth( 0u ),
1446   mDepth( 0u ),
1447   mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1448   mIsRoot( ROOT_LAYER == derivedType ),
1449   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1450   mIsOnScene( false ),
1451   mSensitive( true ),
1452   mLeaveRequired( false ),
1453   mKeyboardFocusable( false ),
1454   mOnSceneSignalled( false ),
1455   mInsideOnSizeSet( false ),
1456   mInheritPosition( true ),
1457   mInheritOrientation( true ),
1458   mInheritScale( true ),
1459   mPositionUsesAnchorPoint( true ),
1460   mVisible( true ),
1461   mInheritLayoutDirection( true ),
1462   mCaptureAllTouchAfterStart( false ),
1463   mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1464   mDrawMode( DrawMode::NORMAL ),
1465   mColorMode( Node::DEFAULT_COLOR_MODE ),
1466   mClippingMode( ClippingMode::DISABLED )
1467 {
1468 }
1469
1470 void Actor::Initialize()
1471 {
1472   OnInitialize();
1473
1474   GetEventThreadServices().RegisterObject( this );
1475 }
1476
1477 Actor::~Actor()
1478 {
1479   // Remove mParent pointers from children even if we're destroying core,
1480   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1481   if( mChildren )
1482   {
1483     for( const auto& actor : *mChildren )
1484     {
1485       actor->SetParent( nullptr );
1486     }
1487   }
1488   delete mChildren;
1489   delete mRenderers;
1490
1491   // Guard to allow handle destruction after Core has been destroyed
1492   if( EventThreadServices::IsCoreRunning() )
1493   {
1494     // Root layer will destroy its node in its own destructor
1495     if ( !mIsRoot )
1496     {
1497       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1498
1499       GetEventThreadServices().UnregisterObject( this );
1500     }
1501   }
1502
1503   // Cleanup optional gesture data
1504   delete mGestureData;
1505
1506   // Cleanup optional parent origin and anchor
1507   delete mParentOrigin;
1508   delete mAnchorPoint;
1509
1510   // Delete optional relayout data
1511   delete mRelayoutData;
1512 }
1513
1514 void Actor::ConnectToScene( uint32_t parentDepth )
1515 {
1516   // This container is used instead of walking the Actor hierarchy.
1517   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1518   ActorContainer connectionList;
1519
1520   if( mScene )
1521   {
1522     mScene->RequestRebuildDepthTree();
1523   }
1524
1525   // This stage is atomic i.e. not interrupted by user callbacks.
1526   RecursiveConnectToScene( connectionList, parentDepth + 1 );
1527
1528   // Notify applications about the newly connected actors.
1529   for( const auto& actor : connectionList )
1530   {
1531     actor->NotifyStageConnection();
1532   }
1533
1534   RelayoutRequest();
1535 }
1536
1537 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1538 {
1539   DALI_ASSERT_ALWAYS( !OnScene() );
1540
1541   mIsOnScene = true;
1542   mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1543
1544   ConnectToSceneGraph();
1545
1546   // Notification for internal derived classes
1547   OnSceneConnectionInternal();
1548
1549   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1550   connectionList.push_back( ActorPtr( this ) );
1551
1552   // Recursively connect children
1553   if( mChildren )
1554   {
1555     for( const auto& actor : *mChildren )
1556     {
1557       actor->SetScene( *mScene );
1558       actor->RecursiveConnectToScene( connectionList, depth + 1 );
1559     }
1560   }
1561 }
1562
1563 /**
1564  * This method is called when the Actor is connected to the Stage.
1565  * The parent must have added its Node to the scene-graph.
1566  * The child must connect its Node to the parent's Node.
1567  * This is recursive; the child calls ConnectToScene() for its children.
1568  */
1569 void Actor::ConnectToSceneGraph()
1570 {
1571   DALI_ASSERT_DEBUG( mParent != NULL);
1572
1573   // Reparent Node in next Update
1574   ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1575
1576   // Request relayout on all actors that are added to the scenegraph
1577   RelayoutRequest();
1578
1579   // Notification for Object::Observers
1580   OnSceneObjectAdd();
1581 }
1582
1583 void Actor::NotifyStageConnection()
1584 {
1585   // Actors can be removed (in a callback), before the on-stage stage is reported.
1586   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1587   if( OnScene() && !mOnSceneSignalled )
1588   {
1589     // Notification for external (CustomActor) derived classes
1590     OnSceneConnectionExternal( mDepth );
1591
1592     if( !mOnSceneSignal.Empty() )
1593     {
1594       Dali::Actor handle( this );
1595       mOnSceneSignal.Emit( handle );
1596     }
1597
1598     // Guard against Remove during callbacks
1599     if( OnScene() )
1600     {
1601       mOnSceneSignalled = true; // signal required next time Actor is removed
1602     }
1603   }
1604 }
1605
1606 void Actor::DisconnectFromStage()
1607 {
1608   // This container is used instead of walking the Actor hierachy.
1609   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1610   ActorContainer disconnectionList;
1611
1612   if( mScene )
1613   {
1614     mScene->RequestRebuildDepthTree();
1615   }
1616
1617   // This stage is atomic i.e. not interrupted by user callbacks
1618   RecursiveDisconnectFromStage( disconnectionList );
1619
1620   // Notify applications about the newly disconnected actors.
1621   for( const auto& actor : disconnectionList )
1622   {
1623     actor->NotifyStageDisconnection();
1624   }
1625 }
1626
1627 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1628 {
1629   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1630   mIsOnScene = false;
1631
1632   // Recursively disconnect children
1633   if( mChildren )
1634   {
1635     for( const auto& child : *mChildren )
1636     {
1637       child->RecursiveDisconnectFromStage( disconnectionList );
1638     }
1639   }
1640
1641   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1642   disconnectionList.push_back( ActorPtr( this ) );
1643
1644   // Notification for internal derived classes
1645   OnSceneDisconnectionInternal();
1646
1647   DisconnectFromSceneGraph();
1648 }
1649
1650 /**
1651  * This method is called by an actor or its parent, before a node removal message is sent.
1652  * This is recursive; the child calls DisconnectFromStage() for its children.
1653  */
1654 void Actor::DisconnectFromSceneGraph()
1655 {
1656   // Notification for Object::Observers
1657   OnSceneObjectRemove();
1658 }
1659
1660 void Actor::NotifyStageDisconnection()
1661 {
1662   // Actors can be added (in a callback), before the off-stage state is reported.
1663   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1664   // only do this step if there is a stage, i.e. Core is not being shut down
1665   if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1666   {
1667     // Notification for external (CustomeActor) derived classes
1668     OnSceneDisconnectionExternal();
1669
1670     if( !mOffSceneSignal.Empty() )
1671     {
1672       Dali::Actor handle( this );
1673       mOffSceneSignal.Emit( handle );
1674     }
1675
1676     // Guard against Add during callbacks
1677     if( !OnScene() )
1678     {
1679       mOnSceneSignalled = false; // signal required next time Actor is added
1680     }
1681   }
1682 }
1683
1684 bool Actor::IsNodeConnected() const
1685 {
1686   bool connected( false );
1687
1688   if( OnScene() )
1689   {
1690     if( IsRoot() || GetNode().GetParent() )
1691     {
1692       connected = true;
1693     }
1694   }
1695
1696   return connected;
1697 }
1698
1699 // This method initiates traversal of the actor tree using depth-first
1700 // traversal to set a depth index based on traversal order. It sends a
1701 // single message to update manager to update all the actor's nodes in
1702 // this tree with the depth index. The sceneGraphNodeDepths vector's
1703 // elements are ordered by depth, and could be used to reduce sorting
1704 // in the update thread.
1705 void Actor::RebuildDepthTree()
1706 {
1707   DALI_LOG_TIMER_START(depthTimer);
1708
1709   // Vector of scene-graph nodes and their depths to send to UpdateManager
1710   // in a single message
1711   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1712
1713   int32_t depthIndex = 1;
1714   DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1715
1716   SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1717   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1718 }
1719
1720 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1721 {
1722   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1723   sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1724
1725   // Create/add to children of this node
1726   if( mChildren )
1727   {
1728     for( const auto& child : *mChildren )
1729     {
1730       Actor* childActor = child.Get();
1731       ++depthIndex;
1732       childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1733     }
1734   }
1735 }
1736
1737 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1738 {
1739   PropertyHandler::SetDefaultProperty(*this, index, property);
1740 }
1741
1742 // TODO: This method needs to be removed
1743 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1744 {
1745   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1746 }
1747
1748 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1749 {
1750   Property::Value value;
1751
1752   if( ! GetCachedPropertyValue( index, value ) )
1753   {
1754     // If property value is not stored in the event-side, then it must be a scene-graph only property
1755     GetCurrentPropertyValue( index, value );
1756   }
1757
1758   return value;
1759 }
1760
1761 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1762 {
1763   Property::Value value;
1764
1765   if( ! GetCurrentPropertyValue( index, value ) )
1766   {
1767     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1768     GetCachedPropertyValue( index, value );
1769   }
1770
1771   return value;
1772 }
1773
1774 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1775 {
1776   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1777 }
1778
1779 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1780 {
1781   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1782   if( !property )
1783   {
1784     // not our property, ask base
1785     property = Object::GetSceneObjectAnimatableProperty( index );
1786   }
1787
1788   return property;
1789 }
1790
1791 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1792 {
1793   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1794   if( !property )
1795   {
1796     // reuse animatable property getter as animatable properties are inputs as well
1797     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1798     property = GetSceneObjectAnimatableProperty( index );
1799   }
1800
1801   return property;
1802 }
1803
1804 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1805 {
1806   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1807   if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1808   {
1809     // ask base
1810     componentIndex = Object::GetPropertyComponentIndex( index );
1811   }
1812
1813   return componentIndex;
1814 }
1815
1816 void Actor::SetParent( Actor* parent )
1817 {
1818   if( parent )
1819   {
1820     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1821
1822     mParent = parent;
1823
1824     mScene = parent->mScene;
1825
1826     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1827          parent->OnScene() )
1828     {
1829       // Instruct each actor to create a corresponding node in the scene graph
1830       ConnectToScene( parent->GetHierarchyDepth() );
1831     }
1832
1833     // Resolve the name and index for the child properties if any
1834     ResolveChildProperties();
1835   }
1836   else // parent being set to NULL
1837   {
1838     DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1839
1840     mParent = nullptr;
1841
1842     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1843          OnScene() )
1844     {
1845       // Disconnect the Node & its children from the scene-graph.
1846       DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1847
1848       // Instruct each actor to discard pointers to the scene-graph
1849       DisconnectFromStage();
1850     }
1851
1852     mScene = nullptr;
1853   }
1854 }
1855
1856 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1857 {
1858   bool done = false;
1859   Actor* actor = dynamic_cast< Actor* >( object );
1860
1861   if( actor )
1862   {
1863     if( 0 == actionName.compare( ACTION_SHOW ) )
1864     {
1865       actor->SetVisible( true );
1866       done = true;
1867     }
1868     else if( 0 == actionName.compare( ACTION_HIDE ) )
1869     {
1870       actor->SetVisible( false );
1871       done = true;
1872     }
1873   }
1874
1875   return done;
1876 }
1877
1878 Rect<> Actor::CalculateScreenExtents( ) const
1879 {
1880   auto screenPosition = GetCurrentScreenPosition();
1881   Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1882   Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1883   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1884   return { position.x, position.y, size.x, size.y };
1885 }
1886
1887 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1888 {
1889   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1890 }
1891
1892 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value  ) const
1893 {
1894   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1895 }
1896
1897 Actor::Relayouter& Actor::EnsureRelayouter()
1898 {
1899   // Assign relayouter
1900   if( !mRelayoutData )
1901   {
1902     mRelayoutData = new Relayouter();
1903   }
1904
1905   return *mRelayoutData;
1906 }
1907
1908 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1909 {
1910   // Check if actor is dependent on parent
1911   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1912   {
1913     if( ( dimension & ( 1 << i ) ) )
1914     {
1915       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1916       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1917       {
1918         return true;
1919       }
1920     }
1921   }
1922
1923   return false;
1924 }
1925
1926 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1927 {
1928   // Check if actor is dependent on children
1929   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1930   {
1931     if( ( dimension & ( 1 << i ) ) )
1932     {
1933       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1934       switch( resizePolicy )
1935       {
1936         case ResizePolicy::FIT_TO_CHILDREN:
1937         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
1938         {
1939           return true;
1940         }
1941
1942         default:
1943         {
1944           break;
1945         }
1946       }
1947     }
1948   }
1949
1950   return false;
1951 }
1952
1953 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1954 {
1955   return Actor::RelayoutDependentOnChildren( dimension );
1956 }
1957
1958 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1959 {
1960   // Check each possible dimension and see if it is dependent on the input one
1961   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1962   {
1963     if( dimension & ( 1 << i ) )
1964     {
1965       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1966     }
1967   }
1968
1969   return false;
1970 }
1971
1972 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1973 {
1974   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1975   {
1976     if( dimension & ( 1 << i ) )
1977     {
1978       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1979     }
1980   }
1981 }
1982
1983 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1984 {
1985   // If more than one dimension is requested, just return the first one found
1986   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1987   {
1988     if( ( dimension & ( 1 << i ) ) )
1989     {
1990       return mRelayoutData->negotiatedDimensions[ i ];
1991     }
1992   }
1993
1994   return 0.0f;   // Default
1995 }
1996
1997 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
1998 {
1999   EnsureRelayouter().SetPadding( padding, dimension );
2000 }
2001
2002 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2003 {
2004   if ( mRelayoutData )
2005   {
2006     // If more than one dimension is requested, just return the first one found
2007     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2008     {
2009       if( ( dimension & ( 1 << i ) ) )
2010       {
2011         return mRelayoutData->dimensionPadding[ i ];
2012       }
2013     }
2014   }
2015
2016   return Relayouter::DEFAULT_DIMENSION_PADDING;
2017 }
2018
2019 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2020 {
2021   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2022 }
2023
2024 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2025 {
2026   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2027 }
2028
2029 float Actor::GetHeightForWidthBase( float width )
2030 {
2031   float height = 0.0f;
2032
2033   const Vector3 naturalSize = GetNaturalSize();
2034   if( naturalSize.width > 0.0f )
2035   {
2036     height = naturalSize.height * width / naturalSize.width;
2037   }
2038   else // we treat 0 as 1:1 aspect ratio
2039   {
2040     height = width;
2041   }
2042
2043   return height;
2044 }
2045
2046 float Actor::GetWidthForHeightBase( float height )
2047 {
2048   float width = 0.0f;
2049
2050   const Vector3 naturalSize = GetNaturalSize();
2051   if( naturalSize.height > 0.0f )
2052   {
2053     width = naturalSize.width * height / naturalSize.height;
2054   }
2055   else // we treat 0 as 1:1 aspect ratio
2056   {
2057     width = height;
2058   }
2059
2060   return width;
2061 }
2062
2063 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2064 {
2065   // Fill to parent, taking size mode factor into account
2066   switch( child.GetResizePolicy( dimension ) )
2067   {
2068     case ResizePolicy::FILL_TO_PARENT:
2069     {
2070       return GetLatestSize( dimension );
2071     }
2072
2073     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2074     {
2075       return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2076     }
2077
2078     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2079     {
2080       return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2081     }
2082
2083     default:
2084     {
2085       return GetLatestSize( dimension );
2086     }
2087   }
2088 }
2089
2090 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2091 {
2092   // Can be overridden in derived class
2093   return CalculateChildSizeBase( child, dimension );
2094 }
2095
2096 float Actor::GetHeightForWidth( float width )
2097 {
2098   // Can be overridden in derived class
2099   return GetHeightForWidthBase( width );
2100 }
2101
2102 float Actor::GetWidthForHeight( float height )
2103 {
2104   // Can be overridden in derived class
2105   return GetWidthForHeightBase( height );
2106 }
2107
2108 float Actor::GetLatestSize( Dimension::Type dimension ) const
2109 {
2110   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2111 }
2112
2113 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2114 {
2115   Vector2 padding = GetPadding( dimension );
2116
2117   return GetLatestSize( dimension ) + padding.x + padding.y;
2118 }
2119
2120 float Actor::NegotiateFromParent( Dimension::Type dimension )
2121 {
2122   Actor* parent = GetParent();
2123   if( parent )
2124   {
2125     Vector2 padding( GetPadding( dimension ) );
2126     Vector2 parentPadding( parent->GetPadding( dimension ) );
2127     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2128   }
2129
2130   return 0.0f;
2131 }
2132
2133 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2134 {
2135   float maxDimensionPoint = 0.0f;
2136
2137   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2138   {
2139     ActorPtr child = GetChildAt( i );
2140
2141     if( !child->RelayoutDependentOnParent( dimension ) )
2142     {
2143       // Calculate the min and max points that the children range across
2144       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2145       float dimensionSize = child->GetRelayoutSize( dimension );
2146       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2147     }
2148   }
2149
2150   return maxDimensionPoint;
2151 }
2152
2153 float Actor::GetSize( Dimension::Type dimension ) const
2154 {
2155   return GetDimensionValue( mTargetSize, dimension );
2156 }
2157
2158 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2159 {
2160   return GetDimensionValue( GetNaturalSize(), dimension );
2161 }
2162
2163 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2164 {
2165   switch( GetResizePolicy( dimension ) )
2166   {
2167     case ResizePolicy::USE_NATURAL_SIZE:
2168     {
2169       return GetNaturalSize( dimension );
2170     }
2171
2172     case ResizePolicy::FIXED:
2173     {
2174       return GetDimensionValue( GetPreferredSize(), dimension );
2175     }
2176
2177     case ResizePolicy::USE_ASSIGNED_SIZE:
2178     {
2179       return GetDimensionValue( maximumSize, dimension );
2180     }
2181
2182     case ResizePolicy::FILL_TO_PARENT:
2183     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2184     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2185     {
2186       return NegotiateFromParent( dimension );
2187     }
2188
2189     case ResizePolicy::FIT_TO_CHILDREN:
2190     {
2191       return NegotiateFromChildren( dimension );
2192     }
2193
2194     case ResizePolicy::DIMENSION_DEPENDENCY:
2195     {
2196       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2197
2198       // Custom rules
2199       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2200       {
2201         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2202       }
2203
2204       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2205       {
2206         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2207       }
2208
2209       break;
2210     }
2211
2212     default:
2213     {
2214       break;
2215     }
2216   }
2217
2218   return 0.0f;  // Default
2219 }
2220
2221 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2222 {
2223   // Check if it needs to be negotiated
2224   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2225   {
2226     // Check that we havn't gotten into an infinite loop
2227     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2228     bool recursionFound = false;
2229     for( auto& element : recursionStack )
2230     {
2231       if( element == searchActor )
2232       {
2233         recursionFound = true;
2234         break;
2235       }
2236     }
2237
2238     if( !recursionFound )
2239     {
2240       // Record the path that we have taken
2241       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2242
2243       // Dimension dependency check
2244       for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2245       {
2246         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2247
2248         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2249         {
2250           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2251         }
2252       }
2253
2254       // Parent dependency check
2255       Actor* parent = GetParent();
2256       if( parent && RelayoutDependentOnParent( dimension ) )
2257       {
2258         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2259       }
2260
2261       // Children dependency check
2262       if( RelayoutDependentOnChildren( dimension ) )
2263       {
2264         for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2265         {
2266           ActorPtr child = GetChildAt( i );
2267
2268           // Only relayout child first if it is not dependent on this actor
2269           if( !child->RelayoutDependentOnParent( dimension ) )
2270           {
2271             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2272           }
2273         }
2274       }
2275
2276       // For deriving classes
2277       OnCalculateRelayoutSize( dimension );
2278
2279       // All dependencies checked, calculate the size and set negotiated flag
2280       const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2281
2282       SetNegotiatedDimension( newSize, dimension );
2283       SetLayoutNegotiated( true, dimension );
2284
2285       // For deriving classes
2286       OnLayoutNegotiated( newSize, dimension );
2287
2288       // This actor has been successfully processed, pop it off the recursion stack
2289       recursionStack.pop_back();
2290     }
2291     else
2292     {
2293       // TODO: Break infinite loop
2294       SetLayoutNegotiated( true, dimension );
2295     }
2296   }
2297 }
2298
2299 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2300 {
2301   // Negotiate all dimensions that require it
2302   ActorDimensionStack recursionStack;
2303
2304   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2305   {
2306     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2307
2308     // Negotiate
2309     NegotiateDimension( dimension, allocatedSize, recursionStack );
2310   }
2311 }
2312
2313 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2314 {
2315   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2316 }
2317
2318 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2319 {
2320   // Do the set actor size
2321   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2322
2323   // Adjust for size set policy
2324   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2325
2326   // Lock the flag to stop recursive relayouts on set size
2327   mRelayoutData->insideRelayout = true;
2328   SetSize( negotiatedSize );
2329   mRelayoutData->insideRelayout = false;
2330
2331   // Clear flags for all dimensions
2332   SetLayoutDirty( false );
2333
2334   // Give deriving classes a chance to respond
2335   OnRelayout( negotiatedSize, container );
2336
2337   if( !mOnRelayoutSignal.Empty() )
2338   {
2339     Dali::Actor handle( this );
2340     mOnRelayoutSignal.Emit( handle );
2341   }
2342 }
2343
2344 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2345 {
2346   // Force a size negotiation for actors that has assigned size during relayout
2347   // This is required as otherwise the flags that force a relayout will not
2348   // necessarilly be set. This will occur if the actor has already been laid out.
2349   // The dirty flags are then cleared. Then if the actor is added back into the
2350   // relayout container afterwards, the dirty flags would still be clear...
2351   // causing a relayout to be skipped. Here we force any actors added to the
2352   // container to be relayed out.
2353   DALI_LOG_TIMER_START( NegSizeTimer1 );
2354
2355   if( GetUseAssignedSize(Dimension::WIDTH ) )
2356   {
2357     SetLayoutNegotiated( false, Dimension::WIDTH );
2358   }
2359   if( GetUseAssignedSize( Dimension::HEIGHT ) )
2360   {
2361     SetLayoutNegotiated( false, Dimension::HEIGHT );
2362   }
2363
2364   // Do the negotiation
2365   NegotiateDimensions( allocatedSize );
2366
2367   // Set the actor size
2368   SetNegotiatedSize( container );
2369
2370   // Negotiate down to children
2371   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2372   {
2373     ActorPtr child = GetChildAt( i );
2374
2375     // Forces children that have already been laid out to be relayed out
2376     // if they have assigned size during relayout.
2377     if( child->GetUseAssignedSize(Dimension::WIDTH) )
2378     {
2379       child->SetLayoutNegotiated(false, Dimension::WIDTH);
2380       child->SetLayoutDirty(true, Dimension::WIDTH);
2381     }
2382
2383     if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2384     {
2385       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2386       child->SetLayoutDirty(true, Dimension::HEIGHT);
2387     }
2388
2389     // Only relayout if required
2390     if( child->RelayoutRequired() )
2391     {
2392       container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2393     }
2394   }
2395   DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2396 }
2397
2398 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2399 {
2400   if( mRelayoutData )
2401   {
2402     mRelayoutData->SetUseAssignedSize(use, dimension);
2403   }
2404 }
2405
2406 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2407 {
2408   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2409 }
2410
2411 void Actor::RelayoutRequest( Dimension::Type dimension )
2412 {
2413   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2414   if( relayoutController )
2415   {
2416     Dali::Actor self( this );
2417     relayoutController->RequestRelayout( self, dimension );
2418   }
2419 }
2420
2421 void Actor::SetPreferredSize( const Vector2& size )
2422 {
2423   EnsureRelayouter();
2424
2425   // If valid width or height, then set the resize policy to FIXED
2426   // 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,
2427   // then change to FIXED as well
2428
2429   if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2430   {
2431     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2432   }
2433
2434   if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2435   {
2436     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2437   }
2438
2439   mRelayoutData->preferredSize = size;
2440
2441   mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2442
2443   RelayoutRequest();
2444 }
2445
2446 Vector2 Actor::GetPreferredSize() const
2447 {
2448   if ( mRelayoutData )
2449   {
2450     return Vector2( mRelayoutData->preferredSize );
2451   }
2452
2453   return Relayouter::DEFAULT_PREFERRED_SIZE;
2454 }
2455
2456 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2457 {
2458   EnsureRelayouter().SetMinimumSize(size, dimension);
2459   RelayoutRequest();
2460 }
2461
2462 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2463 {
2464   if ( mRelayoutData )
2465   {
2466     return mRelayoutData->GetMinimumSize(dimension);
2467   }
2468
2469   return 0.0f;  // Default
2470 }
2471
2472 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2473 {
2474   EnsureRelayouter().SetMaximumSize(size, dimension);
2475   RelayoutRequest();
2476 }
2477
2478 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2479 {
2480   if ( mRelayoutData )
2481   {
2482     return mRelayoutData->GetMaximumSize(dimension);
2483   }
2484
2485   return FLT_MAX;  // Default
2486 }
2487
2488 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2489 {
2490   if( mVisible != visible )
2491   {
2492     if( sendMessage == SendMessage::TRUE )
2493     {
2494       // node is being used in a separate thread; queue a message to set the value & base value
2495       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2496     }
2497
2498     mVisible = visible;
2499
2500     // Emit the signal on this actor and all its children
2501     EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2502   }
2503 }
2504
2505 void Actor::SetSiblingOrder( uint32_t order )
2506 {
2507   if ( mParent )
2508   {
2509     ActorContainer& siblings = *(mParent->mChildren);
2510     uint32_t currentOrder = GetSiblingOrder();
2511
2512     if( order != currentOrder )
2513     {
2514       if( order == 0 )
2515       {
2516         LowerToBottom();
2517       }
2518       else if( order < siblings.size() -1 )
2519       {
2520         if( order > currentOrder )
2521         {
2522           RaiseAbove( *siblings[order] );
2523         }
2524         else
2525         {
2526           LowerBelow( *siblings[order] );
2527         }
2528       }
2529       else
2530       {
2531         RaiseToTop();
2532       }
2533     }
2534   }
2535 }
2536
2537 uint32_t Actor::GetSiblingOrder() const
2538 {
2539   uint32_t order = 0;
2540
2541   if ( mParent )
2542   {
2543     ActorContainer& siblings = *(mParent->mChildren);
2544     for( std::size_t i = 0; i < siblings.size(); ++i )
2545     {
2546       if( siblings[i] == this )
2547       {
2548         order = static_cast<uint32_t>( i );
2549         break;
2550       }
2551     }
2552   }
2553
2554   return order;
2555 }
2556
2557 void Actor::RequestRebuildDepthTree()
2558 {
2559   if( mIsOnScene )
2560   {
2561     if( mScene )
2562     {
2563       mScene->RequestRebuildDepthTree();
2564     }
2565   }
2566 }
2567
2568 void Actor::Raise()
2569 {
2570   if ( mParent )
2571   {
2572     ActorContainer& siblings = *(mParent->mChildren);
2573     if( siblings.back() != this ) // If not already at end
2574     {
2575       for( std::size_t i=0; i<siblings.size(); ++i )
2576       {
2577         if( siblings[i] == this )
2578         {
2579           // Swap with next
2580           ActorPtr next = siblings[i+1];
2581           siblings[i+1] = this;
2582           siblings[i] = next;
2583           break;
2584         }
2585       }
2586     }
2587
2588     Dali::Actor handle( this );
2589     mParent->mChildOrderChangedSignal.Emit( handle );
2590
2591     RequestRebuildDepthTree();
2592   }
2593   else
2594   {
2595     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2596   }
2597 }
2598
2599 void Actor::Lower()
2600 {
2601   if ( mParent )
2602   {
2603     ActorContainer& siblings = *(mParent->mChildren);
2604     if( siblings.front() != this ) // If not already at beginning
2605     {
2606       for( std::size_t i=1; i<siblings.size(); ++i )
2607       {
2608         if( siblings[i] == this )
2609         {
2610           // Swap with previous
2611           ActorPtr previous = siblings[i-1];
2612           siblings[i-1] = this;
2613           siblings[i] = previous;
2614           break;
2615         }
2616       }
2617     }
2618
2619     Dali::Actor handle( this );
2620     mParent->mChildOrderChangedSignal.Emit( handle );
2621
2622     RequestRebuildDepthTree();
2623   }
2624   else
2625   {
2626     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2627   }
2628 }
2629
2630 void Actor::RaiseToTop()
2631 {
2632   if ( mParent )
2633   {
2634     ActorContainer& siblings = *(mParent->mChildren);
2635     if( siblings.back() != this ) // If not already at end
2636     {
2637       auto iter = std::find( siblings.begin(), siblings.end(), this );
2638       if( iter != siblings.end() )
2639       {
2640         siblings.erase(iter);
2641         siblings.push_back(ActorPtr(this));
2642       }
2643     }
2644
2645     Dali::Actor handle( this );
2646     mParent->mChildOrderChangedSignal.Emit( handle );
2647
2648     RequestRebuildDepthTree();
2649   }
2650   else
2651   {
2652     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2653   }
2654 }
2655
2656 void Actor::LowerToBottom()
2657 {
2658   if ( mParent )
2659   {
2660     ActorContainer& siblings = *(mParent->mChildren);
2661     if( siblings.front() != this ) // If not already at bottom,
2662     {
2663       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2664
2665       auto iter = std::find( siblings.begin(), siblings.end(), this );
2666       if( iter != siblings.end() )
2667       {
2668         siblings.erase(iter);
2669         siblings.insert(siblings.begin(), thisPtr);
2670       }
2671     }
2672
2673     Dali::Actor handle( this );
2674     mParent->mChildOrderChangedSignal.Emit( handle );
2675
2676     RequestRebuildDepthTree();
2677   }
2678   else
2679   {
2680     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2681   }
2682 }
2683
2684 void Actor::RaiseAbove( Internal::Actor& target )
2685 {
2686   if ( mParent )
2687   {
2688     ActorContainer& siblings = *(mParent->mChildren);
2689     if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2690     {
2691       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2692
2693       auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2694       auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
2695       if( thisIter < targetIter )
2696       {
2697         siblings.erase(thisIter);
2698         // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2699         // invalidate thisIter)
2700         targetIter = std::find( siblings.begin(), siblings.end(), &target );
2701         ++targetIter;
2702         siblings.insert(targetIter, thisPtr);
2703       }
2704
2705       Dali::Actor handle( this );
2706       mParent->mChildOrderChangedSignal.Emit( handle );
2707
2708       RequestRebuildDepthTree();
2709     }
2710   }
2711   else
2712   {
2713     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2714   }
2715 }
2716
2717 void Actor::LowerBelow( Internal::Actor& target )
2718 {
2719   if ( mParent )
2720   {
2721     ActorContainer& siblings = *(mParent->mChildren);
2722     if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2723     {
2724       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2725
2726       auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2727       auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
2728
2729       if( thisIter > targetIter )
2730       {
2731         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2732         siblings.insert(targetIter, thisPtr);
2733       }
2734
2735       Dali::Actor handle( this );
2736       mParent->mChildOrderChangedSignal.Emit( handle );
2737
2738       RequestRebuildDepthTree();
2739     }
2740   }
2741   else
2742   {
2743     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2744   }
2745 }
2746
2747 void Actor::SetInheritLayoutDirection( bool inherit )
2748 {
2749   if( mInheritLayoutDirection != inherit )
2750   {
2751     mInheritLayoutDirection = inherit;
2752
2753     if( inherit && mParent )
2754     {
2755       InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2756     }
2757   }
2758 }
2759
2760 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2761 {
2762   if( actor && ( actor->mInheritLayoutDirection || set ) )
2763   {
2764     if( actor->mLayoutDirection != direction )
2765     {
2766       actor->mLayoutDirection = direction;
2767       actor->EmitLayoutDirectionChangedSignal( direction );
2768       actor->RelayoutRequest();
2769     }
2770
2771     if( actor->GetChildCount() > 0 )
2772     {
2773       for( const auto& child : actor->GetChildrenInternal() )
2774       {
2775         InheritLayoutDirectionRecursively( child, direction );
2776       }
2777     }
2778   }
2779 }
2780
2781 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2782 {
2783   // node is being used in a separate thread; queue a message to set the value & base value
2784   SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2785 }
2786
2787 } // namespace Internal
2788
2789 } // namespace Dali