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