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