Make blend for the opaque renderer when advanced blend equation is applied.
[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/actors/actor-property-handler.h>
37 #include <dali/internal/event/actors/actor-relayouter.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/event/events/actor-gesture-data.h>
51 #include <dali/integration-api/debug.h>
52
53 using Dali::Internal::SceneGraph::Node;
54 using Dali::Internal::SceneGraph::AnimatableProperty;
55 using Dali::Internal::SceneGraph::PropertyBase;
56
57 #if defined(DEBUG_ENABLED)
58 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
59 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_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 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2271 {
2272   // Check if it needs to be negotiated
2273   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2274   {
2275     // Check that we havn't gotten into an infinite loop
2276     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2277     bool recursionFound = false;
2278     for( auto& element : recursionStack )
2279     {
2280       if( element == searchActor )
2281       {
2282         recursionFound = true;
2283         break;
2284       }
2285     }
2286
2287     if( !recursionFound )
2288     {
2289       // Record the path that we have taken
2290       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2291
2292       // Dimension dependency check
2293       for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2294       {
2295         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2296
2297         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2298         {
2299           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2300         }
2301       }
2302
2303       // Parent dependency check
2304       Actor* parent = GetParent();
2305       if( parent && RelayoutDependentOnParent( dimension ) )
2306       {
2307         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2308       }
2309
2310       // Children dependency check
2311       if( RelayoutDependentOnChildren( dimension ) )
2312       {
2313         for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2314         {
2315           ActorPtr child = GetChildAt( i );
2316
2317           // Only relayout child first if it is not dependent on this actor
2318           if( !child->RelayoutDependentOnParent( dimension ) )
2319           {
2320             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2321           }
2322         }
2323       }
2324
2325       // For deriving classes
2326       OnCalculateRelayoutSize( dimension );
2327
2328       // All dependencies checked, calculate the size and set negotiated flag
2329       const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2330
2331       SetNegotiatedDimension( newSize, dimension );
2332       SetLayoutNegotiated( true, dimension );
2333
2334       // For deriving classes
2335       OnLayoutNegotiated( newSize, dimension );
2336
2337       // This actor has been successfully processed, pop it off the recursion stack
2338       recursionStack.pop_back();
2339     }
2340     else
2341     {
2342       // TODO: Break infinite loop
2343       SetLayoutNegotiated( true, dimension );
2344     }
2345   }
2346 }
2347
2348 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2349 {
2350   // Negotiate all dimensions that require it
2351   ActorDimensionStack recursionStack;
2352
2353   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2354   {
2355     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2356
2357     // Negotiate
2358     NegotiateDimension( dimension, allocatedSize, recursionStack );
2359   }
2360 }
2361
2362 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2363 {
2364   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2365 }
2366
2367 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2368 {
2369   // Do the set actor size
2370   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2371
2372   // Adjust for size set policy
2373   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2374
2375   // Lock the flag to stop recursive relayouts on set size
2376   mRelayoutData->insideRelayout = true;
2377   SetSize( negotiatedSize );
2378   mRelayoutData->insideRelayout = false;
2379
2380   // Clear flags for all dimensions
2381   SetLayoutDirty( false );
2382
2383   // Give deriving classes a chance to respond
2384   OnRelayout( negotiatedSize, container );
2385
2386   if( !mOnRelayoutSignal.Empty() )
2387   {
2388     Dali::Actor handle( this );
2389     mOnRelayoutSignal.Emit( handle );
2390   }
2391 }
2392
2393 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2394 {
2395   // Force a size negotiation for actors that has assigned size during relayout
2396   // This is required as otherwise the flags that force a relayout will not
2397   // necessarilly be set. This will occur if the actor has already been laid out.
2398   // The dirty flags are then cleared. Then if the actor is added back into the
2399   // relayout container afterwards, the dirty flags would still be clear...
2400   // causing a relayout to be skipped. Here we force any actors added to the
2401   // container to be relayed out.
2402   DALI_LOG_TIMER_START( NegSizeTimer1 );
2403
2404   if( GetUseAssignedSize(Dimension::WIDTH ) )
2405   {
2406     SetLayoutNegotiated( false, Dimension::WIDTH );
2407   }
2408   if( GetUseAssignedSize( Dimension::HEIGHT ) )
2409   {
2410     SetLayoutNegotiated( false, Dimension::HEIGHT );
2411   }
2412
2413   // Do the negotiation
2414   NegotiateDimensions( allocatedSize );
2415
2416   // Set the actor size
2417   SetNegotiatedSize( container );
2418
2419   // Negotiate down to children
2420   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2421   {
2422     ActorPtr child = GetChildAt( i );
2423
2424     // Forces children that have already been laid out to be relayed out
2425     // if they have assigned size during relayout.
2426     if( child->GetUseAssignedSize(Dimension::WIDTH) )
2427     {
2428       child->SetLayoutNegotiated(false, Dimension::WIDTH);
2429       child->SetLayoutDirty(true, Dimension::WIDTH);
2430     }
2431
2432     if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2433     {
2434       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2435       child->SetLayoutDirty(true, Dimension::HEIGHT);
2436     }
2437
2438     // Only relayout if required
2439     if( child->RelayoutRequired() )
2440     {
2441       container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2442     }
2443   }
2444   DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2445 }
2446
2447 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2448 {
2449   if( mRelayoutData )
2450   {
2451     mRelayoutData->SetUseAssignedSize(use, dimension);
2452   }
2453 }
2454
2455 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2456 {
2457   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2458 }
2459
2460 void Actor::RelayoutRequest( Dimension::Type dimension )
2461 {
2462   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2463   if( relayoutController )
2464   {
2465     Dali::Actor self( this );
2466     relayoutController->RequestRelayout( self, dimension );
2467   }
2468 }
2469
2470 void Actor::SetPreferredSize( const Vector2& size )
2471 {
2472   EnsureRelayouter();
2473
2474   // If valid width or height, then set the resize policy to FIXED
2475   // 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,
2476   // then change to FIXED as well
2477
2478   if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2479   {
2480     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2481   }
2482
2483   if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2484   {
2485     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2486   }
2487
2488   mRelayoutData->preferredSize = size;
2489
2490   mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2491
2492   RelayoutRequest();
2493 }
2494
2495 Vector2 Actor::GetPreferredSize() const
2496 {
2497   if ( mRelayoutData )
2498   {
2499     return Vector2( mRelayoutData->preferredSize );
2500   }
2501
2502   return Relayouter::DEFAULT_PREFERRED_SIZE;
2503 }
2504
2505 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2506 {
2507   EnsureRelayouter().SetMinimumSize(size, dimension);
2508   RelayoutRequest();
2509 }
2510
2511 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2512 {
2513   if ( mRelayoutData )
2514   {
2515     return mRelayoutData->GetMinimumSize(dimension);
2516   }
2517
2518   return 0.0f;  // Default
2519 }
2520
2521 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2522 {
2523   EnsureRelayouter().SetMaximumSize(size, dimension);
2524   RelayoutRequest();
2525 }
2526
2527 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2528 {
2529   if ( mRelayoutData )
2530   {
2531     return mRelayoutData->GetMaximumSize(dimension);
2532   }
2533
2534   return FLT_MAX;  // Default
2535 }
2536
2537 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2538 {
2539   if( mVisible != visible )
2540   {
2541     if( sendMessage == SendMessage::TRUE )
2542     {
2543       // node is being used in a separate thread; queue a message to set the value & base value
2544       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2545
2546       RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2547     }
2548
2549     mVisible = visible;
2550
2551     // Emit the signal on this actor and all its children
2552     EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2553   }
2554 }
2555
2556 void Actor::SetSiblingOrder( uint32_t order )
2557 {
2558   if ( mParent )
2559   {
2560     ActorContainer& siblings = *(mParent->mChildren);
2561     uint32_t currentOrder = GetSiblingOrder();
2562
2563     if( order != currentOrder )
2564     {
2565       if( order == 0 )
2566       {
2567         LowerToBottom();
2568       }
2569       else if( order < siblings.size() -1 )
2570       {
2571         if( order > currentOrder )
2572         {
2573           RaiseAbove( *siblings[order] );
2574         }
2575         else
2576         {
2577           LowerBelow( *siblings[order] );
2578         }
2579       }
2580       else
2581       {
2582         RaiseToTop();
2583       }
2584     }
2585   }
2586 }
2587
2588 uint32_t Actor::GetSiblingOrder() const
2589 {
2590   uint32_t order = 0;
2591
2592   if ( mParent )
2593   {
2594     ActorContainer& siblings = *(mParent->mChildren);
2595     for( std::size_t i = 0; i < siblings.size(); ++i )
2596     {
2597       if( siblings[i] == this )
2598       {
2599         order = static_cast<uint32_t>( i );
2600         break;
2601       }
2602     }
2603   }
2604
2605   return order;
2606 }
2607
2608 void Actor::RequestRebuildDepthTree()
2609 {
2610   if( mIsOnScene )
2611   {
2612     if( mScene )
2613     {
2614       mScene->RequestRebuildDepthTree();
2615     }
2616   }
2617 }
2618
2619 void Actor::Raise()
2620 {
2621   if ( mParent )
2622   {
2623     ActorContainer& siblings = *(mParent->mChildren);
2624     if( siblings.back() != this ) // If not already at end
2625     {
2626       for( std::size_t i=0; i<siblings.size(); ++i )
2627       {
2628         if( siblings[i] == this )
2629         {
2630           // Swap with next
2631           ActorPtr next = siblings[i+1];
2632           siblings[i+1] = this;
2633           siblings[i] = next;
2634           break;
2635         }
2636       }
2637     }
2638
2639     Dali::Actor handle( this );
2640     mParent->mChildOrderChangedSignal.Emit( handle );
2641
2642     RequestRebuildDepthTree();
2643   }
2644   else
2645   {
2646     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2647   }
2648 }
2649
2650 void Actor::Lower()
2651 {
2652   if ( mParent )
2653   {
2654     ActorContainer& siblings = *(mParent->mChildren);
2655     if( siblings.front() != this ) // If not already at beginning
2656     {
2657       for( std::size_t i=1; i<siblings.size(); ++i )
2658       {
2659         if( siblings[i] == this )
2660         {
2661           // Swap with previous
2662           ActorPtr previous = siblings[i-1];
2663           siblings[i-1] = this;
2664           siblings[i] = previous;
2665           break;
2666         }
2667       }
2668     }
2669
2670     Dali::Actor handle( this );
2671     mParent->mChildOrderChangedSignal.Emit( handle );
2672
2673     RequestRebuildDepthTree();
2674   }
2675   else
2676   {
2677     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2678   }
2679 }
2680
2681 void Actor::RaiseToTop()
2682 {
2683   if ( mParent )
2684   {
2685     ActorContainer& siblings = *(mParent->mChildren);
2686     if( siblings.back() != this ) // If not already at end
2687     {
2688       auto iter = std::find( siblings.begin(), siblings.end(), this );
2689       if( iter != siblings.end() )
2690       {
2691         siblings.erase(iter);
2692         siblings.push_back(ActorPtr(this));
2693       }
2694     }
2695
2696     Dali::Actor handle( this );
2697     mParent->mChildOrderChangedSignal.Emit( handle );
2698
2699     RequestRebuildDepthTree();
2700   }
2701   else
2702   {
2703     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2704   }
2705 }
2706
2707 void Actor::LowerToBottom()
2708 {
2709   if ( mParent )
2710   {
2711     ActorContainer& siblings = *(mParent->mChildren);
2712     if( siblings.front() != this ) // If not already at bottom,
2713     {
2714       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2715
2716       auto iter = std::find( siblings.begin(), siblings.end(), this );
2717       if( iter != siblings.end() )
2718       {
2719         siblings.erase(iter);
2720         siblings.insert(siblings.begin(), thisPtr);
2721       }
2722     }
2723
2724     Dali::Actor handle( this );
2725     mParent->mChildOrderChangedSignal.Emit( handle );
2726
2727     RequestRebuildDepthTree();
2728   }
2729   else
2730   {
2731     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2732   }
2733 }
2734
2735 void Actor::RaiseAbove( Internal::Actor& target )
2736 {
2737   if ( mParent )
2738   {
2739     ActorContainer& siblings = *(mParent->mChildren);
2740     if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2741     {
2742       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2743
2744       auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2745       auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
2746       if( thisIter < targetIter )
2747       {
2748         siblings.erase(thisIter);
2749         // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2750         // invalidate thisIter)
2751         targetIter = std::find( siblings.begin(), siblings.end(), &target );
2752         ++targetIter;
2753         siblings.insert(targetIter, thisPtr);
2754       }
2755
2756       Dali::Actor handle( this );
2757       mParent->mChildOrderChangedSignal.Emit( handle );
2758
2759       RequestRebuildDepthTree();
2760     }
2761   }
2762   else
2763   {
2764     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2765   }
2766 }
2767
2768 void Actor::LowerBelow( Internal::Actor& target )
2769 {
2770   if ( mParent )
2771   {
2772     ActorContainer& siblings = *(mParent->mChildren);
2773     if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2774     {
2775       ActorPtr thisPtr(this); // ensure this actor remains referenced.
2776
2777       auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2778       auto thisIter   = std::find( siblings.begin(), siblings.end(), this );
2779
2780       if( thisIter > targetIter )
2781       {
2782         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2783         siblings.insert(targetIter, thisPtr);
2784       }
2785
2786       Dali::Actor handle( this );
2787       mParent->mChildOrderChangedSignal.Emit( handle );
2788
2789       RequestRebuildDepthTree();
2790     }
2791   }
2792   else
2793   {
2794     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2795   }
2796 }
2797
2798 void Actor::SetInheritLayoutDirection( bool inherit )
2799 {
2800   if( mInheritLayoutDirection != inherit )
2801   {
2802     mInheritLayoutDirection = inherit;
2803
2804     if( inherit && mParent )
2805     {
2806       InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2807     }
2808   }
2809 }
2810
2811 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2812 {
2813   if( actor && ( actor->mInheritLayoutDirection || set ) )
2814   {
2815     if( actor->mLayoutDirection != direction )
2816     {
2817       actor->mLayoutDirection = direction;
2818       actor->EmitLayoutDirectionChangedSignal( direction );
2819       actor->RelayoutRequest();
2820     }
2821
2822     if( actor->GetChildCount() > 0 )
2823     {
2824       for( const auto& child : actor->GetChildrenInternal() )
2825       {
2826         InheritLayoutDirectionRecursively( child, direction );
2827       }
2828     }
2829   }
2830 }
2831
2832 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2833 {
2834   // node is being used in a separate thread; queue a message to set the value & base value
2835   SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2836 }
2837
2838 } // namespace Internal
2839
2840 } // namespace Dali