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