Add TouchDelegateArea property.
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25
26 // INTERNAL INCLUDES
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/internal/event/actors/actor-property-handler.h>
36 #include <dali/internal/event/actors/actor-relayouter.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/thread-local-storage.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/integration-api/debug.h>
51
52 using Dali::Internal::SceneGraph::Node;
53 using Dali::Internal::SceneGraph::AnimatableProperty;
54 using Dali::Internal::SceneGraph::PropertyBase;
55
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
59 #endif
60
61 namespace Dali
62 {
63
64 namespace Internal
65 {
66
67 namespace // unnamed namespace
68 {
69
70 // Properties
71
72 /**
73  * We want to discourage the use of property strings (minimize string comparisons),
74  * particularly for the default properties.
75  *              Name                  Type   writable animatable constraint-input  enum for index-checking
76  */
77 DALI_PROPERTY_TABLE_BEGIN
78 DALI_PROPERTY( "parentOrigin",              VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
79 DALI_PROPERTY( "parentOriginX",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
80 DALI_PROPERTY( "parentOriginY",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
81 DALI_PROPERTY( "parentOriginZ",             FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
82 DALI_PROPERTY( "anchorPoint",               VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
83 DALI_PROPERTY( "anchorPointX",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
84 DALI_PROPERTY( "anchorPointY",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
85 DALI_PROPERTY( "anchorPointZ",              FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
86 DALI_PROPERTY( "size",                      VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
87 DALI_PROPERTY( "sizeWidth",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
88 DALI_PROPERTY( "sizeHeight",                FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
89 DALI_PROPERTY( "sizeDepth",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
90 DALI_PROPERTY( "position",                  VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
91 DALI_PROPERTY( "positionX",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
92 DALI_PROPERTY( "positionY",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
93 DALI_PROPERTY( "positionZ",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
94 DALI_PROPERTY( "worldPosition",             VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
95 DALI_PROPERTY( "worldPositionX",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
96 DALI_PROPERTY( "worldPositionY",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
97 DALI_PROPERTY( "worldPositionZ",            FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
98 DALI_PROPERTY( "orientation",               ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
99 DALI_PROPERTY( "worldOrientation",          ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
100 DALI_PROPERTY( "scale",                     VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
101 DALI_PROPERTY( "scaleX",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
102 DALI_PROPERTY( "scaleY",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
103 DALI_PROPERTY( "scaleZ",                    FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
104 DALI_PROPERTY( "worldScale",                VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
105 DALI_PROPERTY( "visible",                   BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
106 DALI_PROPERTY( "color",                     VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
107 DALI_PROPERTY( "colorRed",                  FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
108 DALI_PROPERTY( "colorGreen",                FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
109 DALI_PROPERTY( "colorBlue",                 FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
110 DALI_PROPERTY( "colorAlpha",                FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
111 DALI_PROPERTY( "worldColor",                VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
112 DALI_PROPERTY( "worldMatrix",               MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
113 DALI_PROPERTY( "name",                      STRING,   true,  false, false, Dali::Actor::Property::NAME )
114 DALI_PROPERTY( "sensitive",                 BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
115 DALI_PROPERTY( "leaveRequired",             BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
116 DALI_PROPERTY( "inheritOrientation",        BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
117 DALI_PROPERTY( "inheritScale",              BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
118 DALI_PROPERTY( "colorMode",                 INTEGER,  true,  false, false, Dali::Actor::Property::COLOR_MODE )
119 DALI_PROPERTY( "drawMode",                  INTEGER,  true,  false, false, Dali::Actor::Property::DRAW_MODE )
120 DALI_PROPERTY( "sizeModeFactor",            VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
121 DALI_PROPERTY( "widthResizePolicy",         STRING,   true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
122 DALI_PROPERTY( "heightResizePolicy",        STRING,   true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
123 DALI_PROPERTY( "sizeScalePolicy",           INTEGER,  true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
124 DALI_PROPERTY( "widthForHeight",            BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
125 DALI_PROPERTY( "heightForWidth",            BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
126 DALI_PROPERTY( "padding",                   VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
127 DALI_PROPERTY( "minimumSize",               VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
128 DALI_PROPERTY( "maximumSize",               VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
129 DALI_PROPERTY( "inheritPosition",           BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_POSITION )
130 DALI_PROPERTY( "clippingMode",              STRING,   true,  false, false, Dali::Actor::Property::CLIPPING_MODE )
131 DALI_PROPERTY( "layoutDirection",           STRING,   true,  false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
132 DALI_PROPERTY( "inheritLayoutDirection",    BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
133 DALI_PROPERTY( "opacity",                   FLOAT,    true,  true,  true,  Dali::Actor::Property::OPACITY )
134 DALI_PROPERTY( "screenPosition",            VECTOR2,  false, false, false, Dali::Actor::Property::SCREEN_POSITION )
135 DALI_PROPERTY( "positionUsesAnchorPoint",   BOOLEAN,  true,  false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
136 DALI_PROPERTY( "culled",                    BOOLEAN,  false, false, true,  Dali::Actor::Property::CULLED )
137 DALI_PROPERTY( "id",                        INTEGER,  false, false, false, Dali::Actor::Property::ID )
138 DALI_PROPERTY( "hierarchyDepth",            INTEGER,  false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
139 DALI_PROPERTY( "isRoot",                    BOOLEAN,  false, false, false, Dali::Actor::Property::IS_ROOT )
140 DALI_PROPERTY( "isLayer",                   BOOLEAN,  false, false, false, Dali::Actor::Property::IS_LAYER )
141 DALI_PROPERTY( "connectedToScene",          BOOLEAN,  false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
142 DALI_PROPERTY( "keyboardFocusable",         BOOLEAN,  true,  false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
143 DALI_PROPERTY( "siblingOrder",              INTEGER,  true,  false, false, Dali::DevelActor::Property::SIBLING_ORDER )
144 DALI_PROPERTY( "updateSizeHint",            VECTOR2,  true,  false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
145 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN,  true,  false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
146 DALI_PROPERTY( "touchDelegateArea",         VECTOR2,  true,  false, false, Dali::DevelActor::Property::TOUCH_DELEGATE_AREA )
147 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
148
149 // Signals
150
151 const char* const SIGNAL_HOVERED = "hovered";
152 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
153 const char* const SIGNAL_ON_SCENE = "onScene";
154 const char* const SIGNAL_OFF_SCENE = "offScene";
155 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
156 const char* const SIGNAL_TOUCHED = "touched";
157 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
158 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
159 const char* const SIGNAL_CHILD_ADDED = "childAdded";
160 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
161
162 // Actions
163
164 const char* const ACTION_SHOW = "show";
165 const char* const ACTION_HIDE = "hide";
166
167 BaseHandle CreateActor()
168 {
169   return Dali::Actor::New();
170 }
171
172 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
173
174 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
175 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
176 SignalConnectorType signalConnector4( mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal );
177 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal );
178 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
179 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
180 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
181 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
182 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
183 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
184
185 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
186 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
187
188 /**
189  * @brief Extract a given dimension from a Vector2
190  *
191  * @param[in] values The values to extract from
192  * @param[in] dimension The dimension to extract
193  * @return Return the value for the dimension
194  */
195 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
196 {
197   switch( dimension )
198   {
199     case Dimension::WIDTH:
200     {
201       return values.width;
202     }
203     case Dimension::HEIGHT:
204     {
205       return values.height;
206     }
207     default:
208     {
209       break;
210     }
211   }
212   return 0.0f;
213 }
214
215 /**
216  * @brief Extract a given dimension from a Vector3
217  *
218  * @param[in] values The values to extract from
219  * @param[in] dimension The dimension to extract
220  * @return Return the value for the dimension
221  */
222 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
223 {
224   return GetDimensionValue( values.GetVectorXY(), dimension );
225 }
226
227 /**
228  * @brief Recursively emits the visibility-changed-signal on the actor tree.
229  * @param[in] actor The actor to emit the signal on
230  * @param[in] visible The new visibility of the actor
231  * @param[in] type Whether the actor's visible property has changed or a parent's
232  */
233 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
234 {
235   if( actor )
236   {
237     actor->EmitVisibilityChangedSignal( visible, type );
238
239     if( actor->GetChildCount() > 0 )
240     {
241       for( ActorPtr& child : actor->GetChildrenInternal() )
242       {
243         EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
244       }
245     }
246   }
247 }
248
249 /// Helper for emitting a signal
250 template<typename Signal, typename Event>
251 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
252 {
253   bool consumed = false;
254
255   if( !signal.Empty() )
256   {
257     Dali::Actor handle( &actor );
258     consumed = signal.Emit( handle, event );
259   }
260
261   return consumed;
262 }
263
264 /// Helper for emitting signals with multiple parameters
265 template<typename Signal, typename... Param>
266 void EmitSignal( Actor& actor, Signal& signal, Param... params)
267 {
268   if( !signal.Empty() )
269   {
270     Dali::Actor handle( &actor );
271     signal.Emit( handle, params... );
272   }
273 }
274
275 bool ScreenToLocalInternal(
276     const Matrix& viewMatrix,
277     const Matrix& projectionMatrix,
278     const Matrix& worldMatrix,
279     const Viewport& viewport,
280     const Vector3& currentSize,
281     float& localX,
282     float& localY,
283     float screenX,
284     float screenY )
285 {
286   // Get the ModelView matrix
287   Matrix modelView;
288   Matrix::Multiply( modelView, worldMatrix, viewMatrix );
289
290   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
291   Matrix invertedMvp( false/*don't init*/);
292   Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
293   bool success = invertedMvp.Invert();
294
295   // Convert to GL coordinates
296   Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
297
298   Vector4 nearPos;
299   if( success )
300   {
301     success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
302   }
303
304   Vector4 farPos;
305   if( success )
306   {
307     screenPos.z = 1.0f;
308     success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
309   }
310
311   if( success )
312   {
313     Vector4 local;
314     if( XyPlaneIntersect( nearPos, farPos, local ) )
315     {
316       Vector3 size = currentSize;
317       localX = local.x + size.x * 0.5f;
318       localY = local.y + size.y * 0.5f;
319     }
320     else
321     {
322       success = false;
323     }
324   }
325
326   return success;
327 }
328
329 } // unnamed namespace
330
331 ActorPtr Actor::New()
332 {
333   // pass a reference to actor, actor does not own its node
334   ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
335
336   // Second-phase construction
337   actor->Initialize();
338
339   return actor;
340 }
341
342 const SceneGraph::Node* Actor::CreateNode()
343 {
344   // create node. Nodes are owned by the update manager
345   SceneGraph::Node* node = SceneGraph::Node::New();
346   OwnerPointer< SceneGraph::Node > transferOwnership( node );
347   Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
348
349   DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
350
351   AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
352
353   return node;
354 }
355
356 void Actor::SetName( const std::string& name )
357 {
358   mName = name;
359
360   // ATTENTION: string for debug purposes is not thread safe.
361   DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
362 }
363
364 uint32_t Actor::GetId() const
365 {
366   return GetNode().GetId();
367 }
368
369 Dali::Layer Actor::GetLayer()
370 {
371   Dali::Layer layer;
372
373   // Short-circuit for Layer derived actors
374   if( mIsLayer )
375   {
376     layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
377   }
378
379   // Find the immediate Layer parent
380   for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
381   {
382     if( parent->IsLayer() )
383     {
384       layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
385     }
386   }
387
388   return layer;
389 }
390
391 void Actor::Add( Actor& child )
392 {
393   DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
394   DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
395
396   if( !mChildren )
397   {
398     mChildren = new ActorContainer;
399   }
400
401   Actor* const oldParent( child.mParent );
402
403   // child might already be ours
404   if( this != oldParent )
405   {
406     // if we already have parent, unparent us first
407     if( oldParent )
408     {
409       oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
410
411       // Old parent may need to readjust to missing child
412       if( oldParent->RelayoutDependentOnChildren() )
413       {
414         oldParent->RelayoutRequest();
415       }
416     }
417
418     // Guard against Add() during previous OnChildRemove callback
419     if( !child.mParent )
420     {
421       // Do this first, since user callbacks from within SetParent() may need to remove child
422       mChildren->push_back( ActorPtr( &child ) );
423
424       // SetParent asserts that child can be added
425       child.SetParent( this );
426
427       // Notification for derived classes
428       OnChildAdd( child );
429       EmitChildAddedSignal( child );
430
431       InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
432
433       // Only put in a relayout request if there is a suitable dependency
434       if( RelayoutDependentOnChildren() )
435       {
436         RelayoutRequest();
437       }
438     }
439   }
440 }
441
442 void Actor::Remove( Actor& child )
443 {
444   if( (this == &child) || (!mChildren) )
445   {
446     // no children or removing itself
447     return;
448   }
449
450   ActorPtr removed;
451
452   // Find the child in mChildren, and unparent it
453   ActorIter end = mChildren->end();
454   for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
455   {
456     ActorPtr actor = (*iter);
457
458     if( actor.Get() == &child )
459     {
460       // Keep handle for OnChildRemove notification
461       removed = actor;
462
463       // Do this first, since user callbacks from within SetParent() may need to add the child
464       mChildren->erase( iter );
465
466       DALI_ASSERT_DEBUG( actor->GetParent() == this );
467       actor->SetParent( nullptr );
468
469       break;
470     }
471   }
472
473   if( removed )
474   {
475     // Only put in a relayout request if there is a suitable dependency
476     if( RelayoutDependentOnChildren() )
477     {
478       RelayoutRequest();
479     }
480   }
481
482   // Notification for derived classes
483   OnChildRemove( child );
484   EmitChildRemovedSignal( child );
485 }
486
487 void Actor::Unparent()
488 {
489   if( mParent )
490   {
491     // Remove this actor from the parent. The remove will put a relayout request in for
492     // the parent if required
493     mParent->Remove( *this );
494     // mParent is now NULL!
495   }
496 }
497
498 uint32_t Actor::GetChildCount() const
499 {
500   return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
501 }
502
503 ActorPtr Actor::GetChildAt( uint32_t index ) const
504 {
505   DALI_ASSERT_ALWAYS( index < GetChildCount() );
506
507   return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
508 }
509
510 ActorPtr Actor::FindChildByName( const std::string& actorName )
511 {
512   ActorPtr child = nullptr;
513   if( actorName == mName )
514   {
515     child = this;
516   }
517   else if( mChildren )
518   {
519     ActorIter end = mChildren->end();
520     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
521     {
522       child = (*iter)->FindChildByName( actorName );
523
524       if( child )
525       {
526         break;
527       }
528     }
529   }
530   return child;
531 }
532
533 ActorPtr Actor::FindChildById( const uint32_t id )
534 {
535   ActorPtr child = nullptr;
536   if( id == GetId() )
537   {
538     child = this;
539   }
540   else if( mChildren )
541   {
542     ActorIter end = mChildren->end();
543     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
544     {
545       child = (*iter)->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   uint32_t index = static_cast<uint32_t>( mRenderers->size() ); //  4,294,967,295 renderers per actor
1201   RendererPtr rendererPtr = RendererPtr( &renderer );
1202   mRenderers->push_back( rendererPtr );
1203   AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1204   return index;
1205 }
1206
1207 uint32_t Actor::GetRendererCount() const
1208 {
1209   uint32_t rendererCount(0);
1210   if( mRenderers )
1211   {
1212     rendererCount = static_cast<uint32_t>( mRenderers->size() ); //  4,294,967,295 renderers per actor
1213   }
1214
1215   return rendererCount;
1216 }
1217
1218 RendererPtr Actor::GetRendererAt( uint32_t index )
1219 {
1220   RendererPtr renderer;
1221   if( index < GetRendererCount() )
1222   {
1223     renderer = ( *mRenderers )[ index ];
1224   }
1225
1226   return renderer;
1227 }
1228
1229 void Actor::RemoveRenderer( Renderer& renderer )
1230 {
1231   if( mRenderers )
1232   {
1233     RendererIter end = mRenderers->end();
1234     for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1235     {
1236       if( (*iter).Get() == &renderer )
1237       {
1238         mRenderers->erase( iter );
1239         DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1240         break;
1241       }
1242     }
1243   }
1244 }
1245
1246 void Actor::RemoveRenderer( uint32_t index )
1247 {
1248   if( index < GetRendererCount() )
1249   {
1250     RendererPtr renderer = ( *mRenderers )[ index ];
1251     DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1252     mRenderers->erase( mRenderers->begin()+index );
1253   }
1254 }
1255
1256 void Actor::SetDrawMode( DrawMode::Type drawMode )
1257 {
1258   // this flag is not animatable so keep the value
1259   mDrawMode = drawMode;
1260
1261   // node is being used in a separate thread; queue a message to set the value
1262   SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1263 }
1264
1265 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1266 {
1267   // only valid when on-stage
1268   if( mScene && OnScene() )
1269   {
1270     const RenderTaskList& taskList = mScene->GetRenderTaskList();
1271
1272     Vector2 converted( screenX, screenY );
1273
1274     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1275     uint32_t taskCount = taskList.GetTaskCount();
1276     for( uint32_t i = taskCount; i > 0; --i )
1277     {
1278       RenderTaskPtr task = taskList.GetTask( i - 1 );
1279       if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1280       {
1281         // found a task where this conversion was ok so return
1282         return true;
1283       }
1284     }
1285   }
1286   return false;
1287 }
1288
1289 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1290 {
1291   bool retval = false;
1292   // only valid when on-stage
1293   if( OnScene() )
1294   {
1295     CameraActor* camera = renderTask.GetCameraActor();
1296     if( camera )
1297     {
1298       Viewport viewport;
1299       renderTask.GetViewport( viewport );
1300
1301       // need to translate coordinates to render tasks coordinate space
1302       Vector2 converted( screenX, screenY );
1303       if( renderTask.TranslateCoordinates( converted ) )
1304       {
1305         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1306       }
1307     }
1308   }
1309   return retval;
1310 }
1311
1312 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1313 {
1314   return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1315 }
1316
1317 ActorGestureData& Actor::GetGestureData()
1318 {
1319   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1320   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1321   if( nullptr == mGestureData )
1322   {
1323     mGestureData = new ActorGestureData;
1324   }
1325   return *mGestureData;
1326 }
1327
1328 bool Actor::IsGestureRequired( GestureType::Value type ) const
1329 {
1330   return mGestureData && mGestureData->IsGestureRequired( type );
1331 }
1332
1333 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1334 {
1335   return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1336 }
1337
1338 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1339 {
1340   return EmitConsumingSignal( *this, mTouchedSignal, touch );
1341 }
1342
1343 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1344 {
1345   return EmitConsumingSignal( *this, mHoveredSignal, event );
1346 }
1347
1348 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1349 {
1350   return EmitConsumingSignal( *this, mWheelEventSignal, event );
1351 }
1352
1353 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1354 {
1355   EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1356 }
1357
1358 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1359 {
1360   EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1361 }
1362
1363 void Actor::EmitChildAddedSignal( Actor& child )
1364 {
1365   EmitSignal( child, mChildAddedSignal );
1366 }
1367
1368 void Actor::EmitChildRemovedSignal( Actor& child )
1369 {
1370   EmitSignal( child, mChildRemovedSignal );
1371 }
1372
1373 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1374 {
1375   bool connected( true );
1376   Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1377
1378   if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1379   {
1380     actor->HoveredSignal().Connect( tracker, functor );
1381   }
1382   else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1383   {
1384     actor->WheelEventSignal().Connect( tracker, functor );
1385   }
1386   else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1387   {
1388     actor->OnSceneSignal().Connect( tracker, functor );
1389   }
1390   else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1391   {
1392     actor->OffSceneSignal().Connect( tracker, functor );
1393   }
1394   else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1395   {
1396     actor->OnRelayoutSignal().Connect( tracker, functor );
1397   }
1398   else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1399   {
1400     actor->TouchedSignal().Connect( tracker, functor );
1401   }
1402   else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1403   {
1404     actor->VisibilityChangedSignal().Connect( tracker, functor );
1405   }
1406   else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1407   {
1408     actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1409   }
1410   else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1411   {
1412     actor->ChildAddedSignal().Connect( tracker, functor );
1413   }
1414   else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1415   {
1416     actor->ChildRemovedSignal().Connect( tracker, functor );
1417   }
1418   else
1419   {
1420     // signalName does not match any signal
1421     connected = false;
1422   }
1423
1424   return connected;
1425 }
1426
1427 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1428 : Object( &node ),
1429   mScene( nullptr ),
1430   mParent( nullptr ),
1431   mChildren( nullptr ),
1432   mRenderers( nullptr ),
1433   mParentOrigin( nullptr ),
1434   mAnchorPoint( nullptr ),
1435   mRelayoutData( nullptr ),
1436   mGestureData( nullptr ),
1437   mInterceptTouchedSignal(),
1438   mTouchedSignal(),
1439   mHoveredSignal(),
1440   mWheelEventSignal(),
1441   mOnSceneSignal(),
1442   mOffSceneSignal(),
1443   mOnRelayoutSignal(),
1444   mVisibilityChangedSignal(),
1445   mLayoutDirectionChangedSignal(),
1446   mChildAddedSignal(),
1447   mChildRemovedSignal(),
1448   mChildOrderChangedSignal(),
1449   mTargetOrientation( Quaternion::IDENTITY ),
1450   mTargetColor( Color::WHITE ),
1451   mTargetSize( Vector3::ZERO ),
1452   mTargetPosition( Vector3::ZERO ),
1453   mTargetScale( Vector3::ONE ),
1454   mAnimatedSize( Vector3::ZERO ),
1455   mTouchDelegateArea( Vector2::ZERO ),
1456   mName(),
1457   mSortedDepth( 0u ),
1458   mDepth( 0u ),
1459   mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1460   mIsRoot( ROOT_LAYER == derivedType ),
1461   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1462   mIsOnScene( false ),
1463   mSensitive( true ),
1464   mLeaveRequired( false ),
1465   mKeyboardFocusable( false ),
1466   mOnSceneSignalled( false ),
1467   mInsideOnSizeSet( false ),
1468   mInheritPosition( true ),
1469   mInheritOrientation( true ),
1470   mInheritScale( true ),
1471   mPositionUsesAnchorPoint( true ),
1472   mVisible( true ),
1473   mInheritLayoutDirection( true ),
1474   mCaptureAllTouchAfterStart( false ),
1475   mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1476   mDrawMode( DrawMode::NORMAL ),
1477   mColorMode( Node::DEFAULT_COLOR_MODE ),
1478   mClippingMode( ClippingMode::DISABLED )
1479 {
1480 }
1481
1482 void Actor::Initialize()
1483 {
1484   OnInitialize();
1485
1486   GetEventThreadServices().RegisterObject( this );
1487 }
1488
1489 Actor::~Actor()
1490 {
1491   // Remove mParent pointers from children even if we're destroying core,
1492   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1493   if( mChildren )
1494   {
1495     ActorConstIter endIter = mChildren->end();
1496     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1497     {
1498       (*iter)->SetParent( nullptr );
1499     }
1500   }
1501   delete mChildren;
1502   delete mRenderers;
1503
1504   // Guard to allow handle destruction after Core has been destroyed
1505   if( EventThreadServices::IsCoreRunning() )
1506   {
1507     // Root layer will destroy its node in its own destructor
1508     if ( !mIsRoot )
1509     {
1510       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1511
1512       GetEventThreadServices().UnregisterObject( this );
1513     }
1514   }
1515
1516   // Cleanup optional gesture data
1517   delete mGestureData;
1518
1519   // Cleanup optional parent origin and anchor
1520   delete mParentOrigin;
1521   delete mAnchorPoint;
1522
1523   // Delete optional relayout data
1524   delete mRelayoutData;
1525 }
1526
1527 void Actor::ConnectToScene( uint32_t parentDepth )
1528 {
1529   // This container is used instead of walking the Actor hierarchy.
1530   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1531   ActorContainer connectionList;
1532
1533   if( mScene )
1534   {
1535     mScene->RequestRebuildDepthTree();
1536   }
1537
1538   // This stage is atomic i.e. not interrupted by user callbacks.
1539   RecursiveConnectToScene( connectionList, parentDepth + 1 );
1540
1541   // Notify applications about the newly connected actors.
1542   const ActorIter endIter = connectionList.end();
1543   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1544   {
1545     (*iter)->NotifyStageConnection();
1546   }
1547
1548   RelayoutRequest();
1549 }
1550
1551 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1552 {
1553   DALI_ASSERT_ALWAYS( !OnScene() );
1554
1555   mIsOnScene = true;
1556   mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1557
1558   ConnectToSceneGraph();
1559
1560   // Notification for internal derived classes
1561   OnSceneConnectionInternal();
1562
1563   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1564   connectionList.push_back( ActorPtr( this ) );
1565
1566   // Recursively connect children
1567   if( mChildren )
1568   {
1569     ActorConstIter endIter = mChildren->end();
1570     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1571     {
1572       (*iter)->SetScene( *mScene );
1573       (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1574     }
1575   }
1576 }
1577
1578 /**
1579  * This method is called when the Actor is connected to the Stage.
1580  * The parent must have added its Node to the scene-graph.
1581  * The child must connect its Node to the parent's Node.
1582  * This is recursive; the child calls ConnectToScene() for its children.
1583  */
1584 void Actor::ConnectToSceneGraph()
1585 {
1586   DALI_ASSERT_DEBUG( mParent != NULL);
1587
1588   // Reparent Node in next Update
1589   ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1590
1591   // Request relayout on all actors that are added to the scenegraph
1592   RelayoutRequest();
1593
1594   // Notification for Object::Observers
1595   OnSceneObjectAdd();
1596 }
1597
1598 void Actor::NotifyStageConnection()
1599 {
1600   // Actors can be removed (in a callback), before the on-stage stage is reported.
1601   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1602   if( OnScene() && !mOnSceneSignalled )
1603   {
1604     // Notification for external (CustomActor) derived classes
1605     OnSceneConnectionExternal( mDepth );
1606
1607     if( !mOnSceneSignal.Empty() )
1608     {
1609       Dali::Actor handle( this );
1610       mOnSceneSignal.Emit( handle );
1611     }
1612
1613     // Guard against Remove during callbacks
1614     if( OnScene() )
1615     {
1616       mOnSceneSignalled = true; // signal required next time Actor is removed
1617     }
1618   }
1619 }
1620
1621 void Actor::DisconnectFromStage()
1622 {
1623   // This container is used instead of walking the Actor hierachy.
1624   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1625   ActorContainer disconnectionList;
1626
1627   if( mScene )
1628   {
1629     mScene->RequestRebuildDepthTree();
1630   }
1631
1632   // This stage is atomic i.e. not interrupted by user callbacks
1633   RecursiveDisconnectFromStage( disconnectionList );
1634
1635   // Notify applications about the newly disconnected actors.
1636   const ActorIter endIter = disconnectionList.end();
1637   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1638   {
1639     (*iter)->NotifyStageDisconnection();
1640   }
1641 }
1642
1643 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1644 {
1645   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1646   mIsOnScene = false;
1647
1648   // Recursively disconnect children
1649   if( mChildren )
1650   {
1651     ActorConstIter endIter = mChildren->end();
1652     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1653     {
1654       (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1655     }
1656   }
1657
1658   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1659   disconnectionList.push_back( ActorPtr( this ) );
1660
1661   // Notification for internal derived classes
1662   OnSceneDisconnectionInternal();
1663
1664   DisconnectFromSceneGraph();
1665 }
1666
1667 /**
1668  * This method is called by an actor or its parent, before a node removal message is sent.
1669  * This is recursive; the child calls DisconnectFromStage() for its children.
1670  */
1671 void Actor::DisconnectFromSceneGraph()
1672 {
1673   // Notification for Object::Observers
1674   OnSceneObjectRemove();
1675 }
1676
1677 void Actor::NotifyStageDisconnection()
1678 {
1679   // Actors can be added (in a callback), before the off-stage state is reported.
1680   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1681   // only do this step if there is a stage, i.e. Core is not being shut down
1682   if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1683   {
1684     // Notification for external (CustomeActor) derived classes
1685     OnSceneDisconnectionExternal();
1686
1687     if( !mOffSceneSignal.Empty() )
1688     {
1689       Dali::Actor handle( this );
1690       mOffSceneSignal.Emit( handle );
1691     }
1692
1693     // Guard against Add during callbacks
1694     if( !OnScene() )
1695     {
1696       mOnSceneSignalled = false; // signal required next time Actor is added
1697     }
1698   }
1699 }
1700
1701 bool Actor::IsNodeConnected() const
1702 {
1703   bool connected( false );
1704
1705   if( OnScene() )
1706   {
1707     if( IsRoot() || GetNode().GetParent() )
1708     {
1709       connected = true;
1710     }
1711   }
1712
1713   return connected;
1714 }
1715
1716 // This method initiates traversal of the actor tree using depth-first
1717 // traversal to set a depth index based on traversal order. It sends a
1718 // single message to update manager to update all the actor's nodes in
1719 // this tree with the depth index. The sceneGraphNodeDepths vector's
1720 // elements are ordered by depth, and could be used to reduce sorting
1721 // in the update thread.
1722 void Actor::RebuildDepthTree()
1723 {
1724   DALI_LOG_TIMER_START(depthTimer);
1725
1726   // Vector of scene-graph nodes and their depths to send to UpdateManager
1727   // in a single message
1728   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1729
1730   int32_t depthIndex = 1;
1731   DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1732
1733   SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1734   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1735 }
1736
1737 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1738 {
1739   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1740   sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1741
1742   // Create/add to children of this node
1743   if( mChildren )
1744   {
1745     for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1746     {
1747       Actor* childActor = (*it).Get();
1748       ++depthIndex;
1749       childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1750     }
1751   }
1752 }
1753
1754 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1755 {
1756   PropertyHandler::SetDefaultProperty(*this, index, property);
1757 }
1758
1759 // TODO: This method needs to be removed
1760 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1761 {
1762   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1763 }
1764
1765 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1766 {
1767   Property::Value value;
1768
1769   if( ! GetCachedPropertyValue( index, value ) )
1770   {
1771     // If property value is not stored in the event-side, then it must be a scene-graph only property
1772     GetCurrentPropertyValue( index, value );
1773   }
1774
1775   return value;
1776 }
1777
1778 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1779 {
1780   Property::Value value;
1781
1782   if( ! GetCurrentPropertyValue( index, value ) )
1783   {
1784     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1785     GetCachedPropertyValue( index, value );
1786   }
1787
1788   return value;
1789 }
1790
1791 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1792 {
1793   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1794 }
1795
1796 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1797 {
1798   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1799   if( !property )
1800   {
1801     // not our property, ask base
1802     property = Object::GetSceneObjectAnimatableProperty( index );
1803   }
1804
1805   return property;
1806 }
1807
1808 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1809 {
1810   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1811   if( !property )
1812   {
1813     // reuse animatable property getter as animatable properties are inputs as well
1814     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1815     property = GetSceneObjectAnimatableProperty( index );
1816   }
1817
1818   return property;
1819 }
1820
1821 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1822 {
1823   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1824   if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1825   {
1826     // ask base
1827     componentIndex = Object::GetPropertyComponentIndex( index );
1828   }
1829
1830   return componentIndex;
1831 }
1832
1833 void Actor::SetParent( Actor* parent )
1834 {
1835   if( parent )
1836   {
1837     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1838
1839     mParent = parent;
1840
1841     mScene = parent->mScene;
1842
1843     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1844          parent->OnScene() )
1845     {
1846       // Instruct each actor to create a corresponding node in the scene graph
1847       ConnectToScene( parent->GetHierarchyDepth() );
1848     }
1849
1850     // Resolve the name and index for the child properties if any
1851     ResolveChildProperties();
1852   }
1853   else // parent being set to NULL
1854   {
1855     DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1856
1857     mParent = nullptr;
1858
1859     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1860          OnScene() )
1861     {
1862       // Disconnect the Node & its children from the scene-graph.
1863       DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1864
1865       // Instruct each actor to discard pointers to the scene-graph
1866       DisconnectFromStage();
1867     }
1868
1869     mScene = nullptr;
1870   }
1871 }
1872
1873 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1874 {
1875   bool done = false;
1876   Actor* actor = dynamic_cast< Actor* >( object );
1877
1878   if( actor )
1879   {
1880     if( 0 == actionName.compare( ACTION_SHOW ) )
1881     {
1882       actor->SetVisible( true );
1883       done = true;
1884     }
1885     else if( 0 == actionName.compare( ACTION_HIDE ) )
1886     {
1887       actor->SetVisible( false );
1888       done = true;
1889     }
1890   }
1891
1892   return done;
1893 }
1894
1895 Rect<> Actor::CalculateScreenExtents( ) const
1896 {
1897   auto screenPosition = GetCurrentScreenPosition();
1898   Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1899   Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1900   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1901   return { position.x, position.y, size.x, size.y };
1902 }
1903
1904 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1905 {
1906   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1907 }
1908
1909 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value  ) const
1910 {
1911   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1912 }
1913
1914 Actor::Relayouter& Actor::EnsureRelayouter()
1915 {
1916   // Assign relayouter
1917   if( !mRelayoutData )
1918   {
1919     mRelayoutData = new Relayouter();
1920   }
1921
1922   return *mRelayoutData;
1923 }
1924
1925 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1926 {
1927   // Check if actor is dependent on parent
1928   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1929   {
1930     if( ( dimension & ( 1 << i ) ) )
1931     {
1932       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1933       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1934       {
1935         return true;
1936       }
1937     }
1938   }
1939
1940   return false;
1941 }
1942
1943 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1944 {
1945   // Check if actor is dependent on children
1946   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1947   {
1948     if( ( dimension & ( 1 << i ) ) )
1949     {
1950       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1951       switch( resizePolicy )
1952       {
1953         case ResizePolicy::FIT_TO_CHILDREN:
1954         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
1955         {
1956           return true;
1957         }
1958
1959         default:
1960         {
1961           break;
1962         }
1963       }
1964     }
1965   }
1966
1967   return false;
1968 }
1969
1970 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1971 {
1972   return Actor::RelayoutDependentOnChildren( dimension );
1973 }
1974
1975 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1976 {
1977   // Check each possible dimension and see if it is dependent on the input one
1978   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1979   {
1980     if( dimension & ( 1 << i ) )
1981     {
1982       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1983     }
1984   }
1985
1986   return false;
1987 }
1988
1989 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1990 {
1991   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1992   {
1993     if( dimension & ( 1 << i ) )
1994     {
1995       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1996     }
1997   }
1998 }
1999
2000 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2001 {
2002   // If more than one dimension is requested, just return the first one found
2003   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2004   {
2005     if( ( dimension & ( 1 << i ) ) )
2006     {
2007       return mRelayoutData->negotiatedDimensions[ i ];
2008     }
2009   }
2010
2011   return 0.0f;   // Default
2012 }
2013
2014 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2015 {
2016   EnsureRelayouter().SetPadding( padding, dimension );
2017 }
2018
2019 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2020 {
2021   if ( mRelayoutData )
2022   {
2023     // If more than one dimension is requested, just return the first one found
2024     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2025     {
2026       if( ( dimension & ( 1 << i ) ) )
2027       {
2028         return mRelayoutData->dimensionPadding[ i ];
2029       }
2030     }
2031   }
2032
2033   return Relayouter::DEFAULT_DIMENSION_PADDING;
2034 }
2035
2036 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2037 {
2038   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2039 }
2040
2041 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2042 {
2043   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2044 }
2045
2046 float Actor::GetHeightForWidthBase( float width )
2047 {
2048   float height = 0.0f;
2049
2050   const Vector3 naturalSize = GetNaturalSize();
2051   if( naturalSize.width > 0.0f )
2052   {
2053     height = naturalSize.height * width / naturalSize.width;
2054   }
2055   else // we treat 0 as 1:1 aspect ratio
2056   {
2057     height = width;
2058   }
2059
2060   return height;
2061 }
2062
2063 float Actor::GetWidthForHeightBase( float height )
2064 {
2065   float width = 0.0f;
2066
2067   const Vector3 naturalSize = GetNaturalSize();
2068   if( naturalSize.height > 0.0f )
2069   {
2070     width = naturalSize.width * height / naturalSize.height;
2071   }
2072   else // we treat 0 as 1:1 aspect ratio
2073   {
2074     width = height;
2075   }
2076
2077   return width;
2078 }
2079
2080 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2081 {
2082   // Fill to parent, taking size mode factor into account
2083   switch( child.GetResizePolicy( dimension ) )
2084   {
2085     case ResizePolicy::FILL_TO_PARENT:
2086     {
2087       return GetLatestSize( dimension );
2088     }
2089
2090     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2091     {
2092       return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2093     }
2094
2095     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2096     {
2097       return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2098     }
2099
2100     default:
2101     {
2102       return GetLatestSize( dimension );
2103     }
2104   }
2105 }
2106
2107 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2108 {
2109   // Can be overridden in derived class
2110   return CalculateChildSizeBase( child, dimension );
2111 }
2112
2113 float Actor::GetHeightForWidth( float width )
2114 {
2115   // Can be overridden in derived class
2116   return GetHeightForWidthBase( width );
2117 }
2118
2119 float Actor::GetWidthForHeight( float height )
2120 {
2121   // Can be overridden in derived class
2122   return GetWidthForHeightBase( height );
2123 }
2124
2125 float Actor::GetLatestSize( Dimension::Type dimension ) const
2126 {
2127   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2128 }
2129
2130 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2131 {
2132   Vector2 padding = GetPadding( dimension );
2133
2134   return GetLatestSize( dimension ) + padding.x + padding.y;
2135 }
2136
2137 float Actor::NegotiateFromParent( Dimension::Type dimension )
2138 {
2139   Actor* parent = GetParent();
2140   if( parent )
2141   {
2142     Vector2 padding( GetPadding( dimension ) );
2143     Vector2 parentPadding( parent->GetPadding( dimension ) );
2144     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2145   }
2146
2147   return 0.0f;
2148 }
2149
2150 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2151 {
2152   float maxDimensionPoint = 0.0f;
2153
2154   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2155   {
2156     ActorPtr child = GetChildAt( i );
2157
2158     if( !child->RelayoutDependentOnParent( dimension ) )
2159     {
2160       // Calculate the min and max points that the children range across
2161       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2162       float dimensionSize = child->GetRelayoutSize( dimension );
2163       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2164     }
2165   }
2166
2167   return maxDimensionPoint;
2168 }
2169
2170 float Actor::GetSize( Dimension::Type dimension ) const
2171 {
2172   return GetDimensionValue( mTargetSize, dimension );
2173 }
2174
2175 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2176 {
2177   return GetDimensionValue( GetNaturalSize(), dimension );
2178 }
2179
2180 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2181 {
2182   switch( GetResizePolicy( dimension ) )
2183   {
2184     case ResizePolicy::USE_NATURAL_SIZE:
2185     {
2186       return GetNaturalSize( dimension );
2187     }
2188
2189     case ResizePolicy::FIXED:
2190     {
2191       return GetDimensionValue( GetPreferredSize(), dimension );
2192     }
2193
2194     case ResizePolicy::USE_ASSIGNED_SIZE:
2195     {
2196       return GetDimensionValue( maximumSize, dimension );
2197     }
2198
2199     case ResizePolicy::FILL_TO_PARENT:
2200     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2201     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2202     {
2203       return NegotiateFromParent( dimension );
2204     }
2205
2206     case ResizePolicy::FIT_TO_CHILDREN:
2207     {
2208       return NegotiateFromChildren( dimension );
2209     }
2210
2211     case ResizePolicy::DIMENSION_DEPENDENCY:
2212     {
2213       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2214
2215       // Custom rules
2216       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2217       {
2218         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2219       }
2220
2221       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2222       {
2223         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2224       }
2225
2226       break;
2227     }
2228
2229     default:
2230     {
2231       break;
2232     }
2233   }
2234
2235   return 0.0f;  // Default
2236 }
2237
2238 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2239 {
2240   // Check if it needs to be negotiated
2241   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2242   {
2243     // Check that we havn't gotten into an infinite loop
2244     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2245     bool recursionFound = false;
2246     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2247     {
2248       if( *it == searchActor )
2249       {
2250         recursionFound = true;
2251         break;
2252       }
2253     }
2254
2255     if( !recursionFound )
2256     {
2257       // Record the path that we have taken
2258       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2259
2260       // Dimension dependency check
2261       for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2262       {
2263         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2264
2265         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2266         {
2267           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2268         }
2269       }
2270
2271       // Parent dependency check
2272       Actor* parent = GetParent();
2273       if( parent && RelayoutDependentOnParent( dimension ) )
2274       {
2275         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2276       }
2277
2278       // Children dependency check
2279       if( RelayoutDependentOnChildren( dimension ) )
2280       {
2281         for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2282         {
2283           ActorPtr child = GetChildAt( i );
2284
2285           // Only relayout child first if it is not dependent on this actor
2286           if( !child->RelayoutDependentOnParent( dimension ) )
2287           {
2288             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2289           }
2290         }
2291       }
2292
2293       // For deriving classes
2294       OnCalculateRelayoutSize( dimension );
2295
2296       // All dependencies checked, calculate the size and set negotiated flag
2297       const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2298
2299       SetNegotiatedDimension( newSize, dimension );
2300       SetLayoutNegotiated( true, dimension );
2301
2302       // For deriving classes
2303       OnLayoutNegotiated( newSize, dimension );
2304
2305       // This actor has been successfully processed, pop it off the recursion stack
2306       recursionStack.pop_back();
2307     }
2308     else
2309     {
2310       // TODO: Break infinite loop
2311       SetLayoutNegotiated( true, dimension );
2312     }
2313   }
2314 }
2315
2316 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2317 {
2318   // Negotiate all dimensions that require it
2319   ActorDimensionStack recursionStack;
2320
2321   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2322   {
2323     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2324
2325     // Negotiate
2326     NegotiateDimension( dimension, allocatedSize, recursionStack );
2327   }
2328 }
2329
2330 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2331 {
2332   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2333 }
2334
2335 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2336 {
2337   // Do the set actor size
2338   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2339
2340   // Adjust for size set policy
2341   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2342
2343   // Lock the flag to stop recursive relayouts on set size
2344   mRelayoutData->insideRelayout = true;
2345   SetSize( negotiatedSize );
2346   mRelayoutData->insideRelayout = false;
2347
2348   // Clear flags for all dimensions
2349   SetLayoutDirty( false );
2350
2351   // Give deriving classes a chance to respond
2352   OnRelayout( negotiatedSize, container );
2353
2354   if( !mOnRelayoutSignal.Empty() )
2355   {
2356     Dali::Actor handle( this );
2357     mOnRelayoutSignal.Emit( handle );
2358   }
2359 }
2360
2361 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2362 {
2363   // Force a size negotiation for actors that has assigned size during relayout
2364   // This is required as otherwise the flags that force a relayout will not
2365   // necessarilly be set. This will occur if the actor has already been laid out.
2366   // The dirty flags are then cleared. Then if the actor is added back into the
2367   // relayout container afterwards, the dirty flags would still be clear...
2368   // causing a relayout to be skipped. Here we force any actors added to the
2369   // container to be relayed out.
2370   DALI_LOG_TIMER_START( NegSizeTimer1 );
2371
2372   if( GetUseAssignedSize(Dimension::WIDTH ) )
2373   {
2374     SetLayoutNegotiated( false, Dimension::WIDTH );
2375   }
2376   if( GetUseAssignedSize( Dimension::HEIGHT ) )
2377   {
2378     SetLayoutNegotiated( false, Dimension::HEIGHT );
2379   }
2380
2381   // Do the negotiation
2382   NegotiateDimensions( allocatedSize );
2383
2384   // Set the actor size
2385   SetNegotiatedSize( container );
2386
2387   // Negotiate down to children
2388   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2389   {
2390     ActorPtr child = GetChildAt( i );
2391
2392     // Forces children that have already been laid out to be relayed out
2393     // if they have assigned size during relayout.
2394     if( child->GetUseAssignedSize(Dimension::WIDTH) )
2395     {
2396       child->SetLayoutNegotiated(false, Dimension::WIDTH);
2397       child->SetLayoutDirty(true, Dimension::WIDTH);
2398     }
2399
2400     if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2401     {
2402       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2403       child->SetLayoutDirty(true, Dimension::HEIGHT);
2404     }
2405
2406     // Only relayout if required
2407     if( child->RelayoutRequired() )
2408     {
2409       container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2410     }
2411   }
2412   DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2413 }
2414
2415 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2416 {
2417   if( mRelayoutData )
2418   {
2419     mRelayoutData->SetUseAssignedSize(use, dimension);
2420   }
2421 }
2422
2423 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2424 {
2425   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2426 }
2427
2428 void Actor::RelayoutRequest( Dimension::Type dimension )
2429 {
2430   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2431   if( relayoutController )
2432   {
2433     Dali::Actor self( this );
2434     relayoutController->RequestRelayout( self, dimension );
2435   }
2436 }
2437
2438 void Actor::SetPreferredSize( const Vector2& size )
2439 {
2440   EnsureRelayouter();
2441
2442   // If valid width or height, then set the resize policy to FIXED
2443   // 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,
2444   // then change to FIXED as well
2445
2446   if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2447   {
2448     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2449   }
2450
2451   if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2452   {
2453     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2454   }
2455
2456   mRelayoutData->preferredSize = size;
2457
2458   mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2459
2460   RelayoutRequest();
2461 }
2462
2463 Vector2 Actor::GetPreferredSize() const
2464 {
2465   if ( mRelayoutData )
2466   {
2467     return Vector2( mRelayoutData->preferredSize );
2468   }
2469
2470   return Relayouter::DEFAULT_PREFERRED_SIZE;
2471 }
2472
2473 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2474 {
2475   EnsureRelayouter().SetMinimumSize(size, dimension);
2476   RelayoutRequest();
2477 }
2478
2479 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2480 {
2481   if ( mRelayoutData )
2482   {
2483     return mRelayoutData->GetMinimumSize(dimension);
2484   }
2485
2486   return 0.0f;  // Default
2487 }
2488
2489 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2490 {
2491   EnsureRelayouter().SetMaximumSize(size, dimension);
2492   RelayoutRequest();
2493 }
2494
2495 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2496 {
2497   if ( mRelayoutData )
2498   {
2499     return mRelayoutData->GetMaximumSize(dimension);
2500   }
2501
2502   return FLT_MAX;  // Default
2503 }
2504
2505 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2506 {
2507   if( mVisible != visible )
2508   {
2509     if( sendMessage == SendMessage::TRUE )
2510     {
2511       // node is being used in a separate thread; queue a message to set the value & base value
2512       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2513
2514       RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2515     }
2516
2517     mVisible = visible;
2518
2519     // Emit the signal on this actor and all its children
2520     EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2521   }
2522 }
2523
2524 void Actor::SetSiblingOrder( uint32_t order )
2525 {
2526   if ( mParent )
2527   {
2528     ActorContainer& siblings = *(mParent->mChildren);
2529     uint32_t currentOrder = GetSiblingOrder();
2530
2531     if( order != currentOrder )
2532     {
2533       if( order == 0 )
2534       {
2535         LowerToBottom();
2536       }
2537       else if( order < siblings.size() -1 )
2538       {
2539         if( order > currentOrder )
2540         {
2541           RaiseAbove( *siblings[order] );
2542         }
2543         else
2544         {
2545           LowerBelow( *siblings[order] );
2546         }
2547       }
2548       else
2549       {
2550         RaiseToTop();
2551       }
2552     }
2553   }
2554 }
2555
2556 uint32_t Actor::GetSiblingOrder() const
2557 {
2558   uint32_t order = 0;
2559
2560   if ( mParent )
2561   {
2562     ActorContainer& siblings = *(mParent->mChildren);
2563     for( std::size_t i = 0; i < siblings.size(); ++i )
2564     {
2565       if( siblings[i] == this )
2566       {
2567         order = static_cast<uint32_t>( i );
2568         break;
2569       }
2570     }
2571   }
2572
2573   return order;
2574 }
2575
2576 void Actor::RequestRebuildDepthTree()
2577 {
2578   if( mIsOnScene )
2579   {
2580     if( mScene )
2581     {
2582       mScene->RequestRebuildDepthTree();
2583     }
2584   }
2585 }
2586
2587 void Actor::Raise()
2588 {
2589   if ( mParent )
2590   {
2591     ActorContainer& siblings = *(mParent->mChildren);
2592     if( siblings.back() != this ) // If not already at end
2593     {
2594       for( std::size_t i=0; i<siblings.size(); ++i )
2595       {
2596         if( siblings[i] == this )
2597         {
2598           // Swap with next
2599           ActorPtr next = siblings[i+1];
2600           siblings[i+1] = this;
2601           siblings[i] = next;
2602           break;
2603         }
2604       }
2605     }
2606
2607     Dali::Actor handle( this );
2608     mParent->mChildOrderChangedSignal.Emit( handle );
2609
2610     RequestRebuildDepthTree();
2611   }
2612   else
2613   {
2614     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2615   }
2616 }
2617
2618 void Actor::Lower()
2619 {
2620   if ( mParent )
2621   {
2622     ActorContainer& siblings = *(mParent->mChildren);
2623     if( siblings.front() != this ) // If not already at beginning
2624     {
2625       for( std::size_t i=1; i<siblings.size(); ++i )
2626       {
2627         if( siblings[i] == this )
2628         {
2629           // Swap with previous
2630           ActorPtr previous = siblings[i-1];
2631           siblings[i-1] = this;
2632           siblings[i] = previous;
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::RaiseToTop()
2650 {
2651   if ( mParent )
2652   {
2653     ActorContainer& siblings = *(mParent->mChildren);
2654     if( siblings.back() != this ) // If not already at end
2655     {
2656       ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2657       if( iter != siblings.end() )
2658       {
2659         siblings.erase(iter);
2660         siblings.push_back(ActorPtr(this));
2661       }
2662     }
2663
2664     Dali::Actor handle( this );
2665     mParent->mChildOrderChangedSignal.Emit( handle );
2666
2667     RequestRebuildDepthTree();
2668   }
2669   else
2670   {
2671     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2672   }
2673 }
2674
2675 void Actor::LowerToBottom()
2676 {
2677   if ( mParent )
2678   {
2679     ActorContainer& siblings = *(mParent->mChildren);
2680     if( siblings.front() != this ) // If not already at bottom,
2681     {
2682       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2683
2684       ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2685       if( iter != siblings.end() )
2686       {
2687         siblings.erase(iter);
2688         siblings.insert(siblings.begin(), thisPtr);
2689       }
2690     }
2691
2692     Dali::Actor handle( this );
2693     mParent->mChildOrderChangedSignal.Emit( handle );
2694
2695     RequestRebuildDepthTree();
2696   }
2697   else
2698   {
2699     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2700   }
2701 }
2702
2703 void Actor::RaiseAbove( Internal::Actor& target )
2704 {
2705   if ( mParent )
2706   {
2707     ActorContainer& siblings = *(mParent->mChildren);
2708     if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2709     {
2710       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2711
2712       ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2713       ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2714       if( thisIter < targetIter )
2715       {
2716         siblings.erase(thisIter);
2717         // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2718         // invalidate thisIter)
2719         targetIter = std::find( siblings.begin(), siblings.end(), &target );
2720         ++targetIter;
2721         siblings.insert(targetIter, thisPtr);
2722       }
2723
2724       Dali::Actor handle( this );
2725       mParent->mChildOrderChangedSignal.Emit( handle );
2726
2727       RequestRebuildDepthTree();
2728     }
2729   }
2730   else
2731   {
2732     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2733   }
2734 }
2735
2736 void Actor::LowerBelow( Internal::Actor& target )
2737 {
2738   if ( mParent )
2739   {
2740     ActorContainer& siblings = *(mParent->mChildren);
2741     if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2742     {
2743       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2744
2745       ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2746       ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2747
2748       if( thisIter > targetIter )
2749       {
2750         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2751         siblings.insert(targetIter, thisPtr);
2752       }
2753
2754       Dali::Actor handle( this );
2755       mParent->mChildOrderChangedSignal.Emit( handle );
2756
2757       RequestRebuildDepthTree();
2758     }
2759   }
2760   else
2761   {
2762     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2763   }
2764 }
2765
2766 void Actor::SetInheritLayoutDirection( bool inherit )
2767 {
2768   if( mInheritLayoutDirection != inherit )
2769   {
2770     mInheritLayoutDirection = inherit;
2771
2772     if( inherit && mParent )
2773     {
2774       InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2775     }
2776   }
2777 }
2778
2779 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2780 {
2781   if( actor && ( actor->mInheritLayoutDirection || set ) )
2782   {
2783     if( actor->mLayoutDirection != direction )
2784     {
2785       actor->mLayoutDirection = direction;
2786       actor->EmitLayoutDirectionChangedSignal( direction );
2787       actor->RelayoutRequest();
2788     }
2789
2790     if( actor->GetChildCount() > 0 )
2791     {
2792       for( ActorPtr& child : actor->GetChildrenInternal() )
2793       {
2794         InheritLayoutDirectionRecursively( child, direction );
2795       }
2796     }
2797   }
2798 }
2799
2800 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2801 {
2802   // node is being used in a separate thread; queue a message to set the value & base value
2803   SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2804 }
2805
2806 } // namespace Internal
2807
2808 } // namespace Dali