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