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