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