Fixed Svace defect
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2015 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
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/scripting/scripting.h>
35
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
55
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
59
60 namespace Dali
61 {
62 namespace ResizePolicy
63 {
64
65 namespace
66 {
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
68 DALI_ENUM_TO_STRING( FIXED )
69 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
70 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
73 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
74 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
75 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
76 DALI_ENUM_TO_STRING_TABLE_END( Type )
77
78 } // unnamed namespace
79 } // ResizePolicy
80
81 namespace SizeScalePolicy
82 {
83 namespace
84 {
85 // Enumeration to / from string conversion tables
86 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
87 DALI_ENUM_TO_STRING( USE_SIZE_SET )
88 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING_TABLE_END( Type )
91 } // unnamed namespace
92 } // SizeScalePolicy
93
94 namespace Internal
95 {
96
97 unsigned int Actor::mActorCounter = 0;
98
99 namespace
100 {
101 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
102 inline const Vector3& GetDefaultSizeModeFactor()
103 {
104   return Vector3::ONE;
105 }
106
107 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
108 inline const Vector2& GetDefaultPreferredSize()
109 {
110   return Vector2::ZERO;
111 }
112
113 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
114 inline const Vector2& GetDefaultDimensionPadding()
115 {
116   return Vector2::ZERO;
117 }
118
119 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
120
121 } // unnamed namespace
122
123 /**
124  * Struct to collect relayout variables
125  */
126 struct Actor::RelayoutData
127 {
128   RelayoutData()
129     : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
130   {
131     // Set size negotiation defaults
132     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
133     {
134       resizePolicies[ i ] = ResizePolicy::DEFAULT;
135       negotiatedDimensions[ i ] = 0.0f;
136       dimensionNegotiated[ i ] = false;
137       dimensionDirty[ i ] = false;
138       dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
139       dimensionPadding[ i ] = GetDefaultDimensionPadding();
140       minimumSize[ i ] = 0.0f;
141       maximumSize[ i ] = FLT_MAX;
142     }
143   }
144
145   ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ];      ///< Resize policies
146
147   Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ];  ///< A list of dimension dependencies
148
149   Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ];         ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
150
151   float negotiatedDimensions[ Dimension::DIMENSION_COUNT ];       ///< Storage for when a dimension is negotiated but before set on actor
152
153   float minimumSize[ Dimension::DIMENSION_COUNT ];                ///< The minimum size an actor can be
154   float maximumSize[ Dimension::DIMENSION_COUNT ];                ///< The maximum size an actor can be
155
156   bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ];         ///< Has the dimension been negotiated
157   bool dimensionDirty[ Dimension::DIMENSION_COUNT ];              ///< Flags indicating whether the layout dimension is dirty or not
158
159   Vector3 sizeModeFactor;                              ///< Factor of size used for certain SizeModes
160
161   Vector2 preferredSize;                               ///< The preferred size of the actor
162
163   SizeScalePolicy::Type sizeSetPolicy :3;            ///< Policy to apply when setting size. Enough room for the enum
164
165   bool relayoutEnabled :1;                   ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
166   bool insideRelayout :1;                    ///< Locking flag to prevent recursive relayouts on size set
167 };
168
169 namespace // unnamed namespace
170 {
171
172 // Properties
173
174 /**
175  * We want to discourage the use of property strings (minimize string comparisons),
176  * particularly for the default properties.
177  *              Name                Type   writable animatable constraint-input  enum for index-checking
178  */
179 DALI_PROPERTY_TABLE_BEGIN
180 DALI_PROPERTY( "parentOrigin",      VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parentOriginX",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parentOriginY",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parentOriginZ",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchorPoint",       VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchorPointX",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchorPointY",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchorPointZ",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size",              VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "sizeWidth",         FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "sizeHeight",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "sizeDepth",         FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position",          VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "positionX",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "positionY",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "positionZ",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "worldPosition",     VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "worldPositionX",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "worldPositionY",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "worldPositionZ",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation",       ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "worldOrientation",  ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale",             VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scaleX",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scaleY",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scaleZ",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "worldScale",        VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible",           BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color",             VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "colorRed",          FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "colorGreen",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "colorBlue",         FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "colorAlpha",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "worldColor",        VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "worldMatrix",       MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name",              STRING,   true,  false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive",         BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leaveRequired",     BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inheritScale",      BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "colorMode",         STRING,   true,  false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "positionInheritance", STRING, true,  false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "drawMode",          STRING,   true,  false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "sizeModeFactor",    VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "widthResizePolicy",  STRING,  true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "heightResizePolicy",  STRING, true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "sizeScalePolicy",   STRING,   true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "widthForHeight",    BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "heightForWidth",    BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding",           VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimumSize",       VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximumSize",       VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
232 DALI_PROPERTY( "inheritPosition",   BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_POSITION )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
234
235 // Signals
236
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
243
244 // Actions
245
246 const char* const ACTION_SHOW = "show";
247 const char* const ACTION_HIDE = "hide";
248
249 BaseHandle CreateActor()
250 {
251   return Dali::Actor::New();
252 }
253
254 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
255
256 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
262
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
265
266 /**
267  * @brief Extract a given dimension from a Vector2
268  *
269  * @param[in] values The values to extract from
270  * @param[in] dimension The dimension to extract
271  * @return Return the value for the dimension
272  */
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
274 {
275   switch( dimension )
276   {
277     case Dimension::WIDTH:
278     {
279       return values.width;
280     }
281     case Dimension::HEIGHT:
282     {
283       return values.height;
284     }
285     default:
286     {
287       break;
288     }
289   }
290   return 0.0f;
291 }
292
293 /**
294  * @brief Extract a given dimension from a Vector3
295  *
296  * @param[in] values The values to extract from
297  * @param[in] dimension The dimension to extract
298  * @return Return the value for the dimension
299  */
300 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
301 {
302   return GetDimensionValue( values.GetVectorXY(), dimension );
303 }
304
305
306 } // unnamed namespace
307
308 ActorPtr Actor::New()
309 {
310   ActorPtr actor( new Actor( BASIC ) );
311
312   // Second-phase construction
313   actor->Initialize();
314
315   return actor;
316 }
317
318 const std::string& Actor::GetName() const
319 {
320   return mName;
321 }
322
323 void Actor::SetName( const std::string& name )
324 {
325   mName = name;
326
327   if( NULL != mNode )
328   {
329     // ATTENTION: string for debug purposes is not thread safe.
330     DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
331   }
332 }
333
334 unsigned int Actor::GetId() const
335 {
336   return mId;
337 }
338
339 void Actor::Attach( ActorAttachment& attachment )
340 {
341   DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
342
343   if( OnStage() )
344   {
345     attachment.Connect();
346   }
347
348   mAttachment = ActorAttachmentPtr( &attachment );
349 }
350
351 ActorAttachmentPtr Actor::GetAttachment()
352 {
353   return mAttachment;
354 }
355
356 bool Actor::OnStage() const
357 {
358   return mIsOnStage;
359 }
360
361 Dali::Layer Actor::GetLayer()
362 {
363   Dali::Layer layer;
364
365   // Short-circuit for Layer derived actors
366   if( mIsLayer )
367   {
368     layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
369   }
370
371   // Find the immediate Layer parent
372   for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
373   {
374     if( parent->IsLayer() )
375     {
376       layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
377     }
378   }
379
380   return layer;
381 }
382
383 void Actor::Add( Actor& child )
384 {
385   DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
386   DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
387
388   if( !mChildren )
389   {
390     mChildren = new ActorContainer;
391   }
392
393   Actor* const oldParent( child.mParent );
394
395   // child might already be ours
396   if( this != oldParent )
397   {
398     // if we already have parent, unparent us first
399     if( oldParent )
400     {
401       oldParent->Remove( child ); // This causes OnChildRemove callback
402
403       // Old parent may need to readjust to missing child
404       if( oldParent->RelayoutDependentOnChildren() )
405       {
406         oldParent->RelayoutRequest();
407       }
408     }
409
410     // Guard against Add() during previous OnChildRemove callback
411     if( !child.mParent )
412     {
413       // Do this first, since user callbacks from within SetParent() may need to remove child
414       mChildren->push_back( ActorPtr( &child ) );
415
416       // SetParent asserts that child can be added
417       child.SetParent( this );
418
419       // Notification for derived classes
420       OnChildAdd( child );
421
422       // Only put in a relayout request if there is a suitable dependency
423       if( RelayoutDependentOnChildren() )
424       {
425         RelayoutRequest();
426       }
427     }
428   }
429 }
430
431 void Actor::Remove( Actor& child )
432 {
433   if( (this == &child) || (!mChildren) )
434   {
435     // no children or removing itself
436     return;
437   }
438
439   ActorPtr removed;
440
441   // Find the child in mChildren, and unparent it
442   ActorIter end = mChildren->end();
443   for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
444   {
445     ActorPtr actor = (*iter);
446
447     if( actor.Get() == &child )
448     {
449       // Keep handle for OnChildRemove notification
450       removed = actor;
451
452       // Do this first, since user callbacks from within SetParent() may need to add the child
453       mChildren->erase( iter );
454
455       DALI_ASSERT_DEBUG( actor->GetParent() == this );
456       actor->SetParent( NULL );
457
458       break;
459     }
460   }
461
462   if( removed )
463   {
464     // Notification for derived classes
465     OnChildRemove( *(removed.Get()) );
466
467     // Only put in a relayout request if there is a suitable dependency
468     if( RelayoutDependentOnChildren() )
469     {
470       RelayoutRequest();
471     }
472   }
473 }
474
475 void Actor::Unparent()
476 {
477   if( mParent )
478   {
479     // Remove this actor from the parent. The remove will put a relayout request in for
480     // the parent if required
481     mParent->Remove( *this );
482     // mParent is now NULL!
483   }
484 }
485
486 unsigned int Actor::GetChildCount() const
487 {
488   return ( NULL != mChildren ) ? mChildren->size() : 0;
489 }
490
491 ActorPtr Actor::GetChildAt( unsigned int index ) const
492 {
493   DALI_ASSERT_ALWAYS( index < GetChildCount() );
494
495   return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
496 }
497
498 ActorPtr Actor::FindChildByName( const std::string& actorName )
499 {
500   ActorPtr child = 0;
501   if( actorName == mName )
502   {
503     child = this;
504   }
505   else if( mChildren )
506   {
507     ActorIter end = mChildren->end();
508     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
509     {
510       child = (*iter)->FindChildByName( actorName );
511
512       if( child )
513       {
514         break;
515       }
516     }
517   }
518   return child;
519 }
520
521 ActorPtr Actor::FindChildById( const unsigned int id )
522 {
523   ActorPtr child = 0;
524   if( id == mId )
525   {
526     child = this;
527   }
528   else if( mChildren )
529   {
530     ActorIter end = mChildren->end();
531     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
532     {
533       child = (*iter)->FindChildById( id );
534
535       if( child )
536       {
537         break;
538       }
539     }
540   }
541   return child;
542 }
543
544 void Actor::SetParentOrigin( const Vector3& origin )
545 {
546   if( NULL != mNode )
547   {
548     // mNode is being used in a separate thread; queue a message to set the value & base value
549     SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
550   }
551
552   // Cache for event-thread access
553   if( !mParentOrigin )
554   {
555     // not allocated, check if different from default
556     if( ParentOrigin::DEFAULT != origin )
557     {
558       mParentOrigin = new Vector3( origin );
559     }
560   }
561   else
562   {
563     // check if different from current costs more than just set
564     *mParentOrigin = origin;
565   }
566 }
567
568 void Actor::SetParentOriginX( float x )
569 {
570   const Vector3& current = GetCurrentParentOrigin();
571
572   SetParentOrigin( Vector3( x, current.y, current.z ) );
573 }
574
575 void Actor::SetParentOriginY( float y )
576 {
577   const Vector3& current = GetCurrentParentOrigin();
578
579   SetParentOrigin( Vector3( current.x, y, current.z ) );
580 }
581
582 void Actor::SetParentOriginZ( float z )
583 {
584   const Vector3& current = GetCurrentParentOrigin();
585
586   SetParentOrigin( Vector3( current.x, current.y, z ) );
587 }
588
589 const Vector3& Actor::GetCurrentParentOrigin() const
590 {
591   // Cached for event-thread access
592   return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
593 }
594
595 void Actor::SetAnchorPoint( const Vector3& anchor )
596 {
597   if( NULL != mNode )
598   {
599     // mNode is being used in a separate thread; queue a message to set the value & base value
600     SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
601   }
602
603   // Cache for event-thread access
604   if( !mAnchorPoint )
605   {
606     // not allocated, check if different from default
607     if( AnchorPoint::DEFAULT != anchor )
608     {
609       mAnchorPoint = new Vector3( anchor );
610     }
611   }
612   else
613   {
614     // check if different from current costs more than just set
615     *mAnchorPoint = anchor;
616   }
617 }
618
619 void Actor::SetAnchorPointX( float x )
620 {
621   const Vector3& current = GetCurrentAnchorPoint();
622
623   SetAnchorPoint( Vector3( x, current.y, current.z ) );
624 }
625
626 void Actor::SetAnchorPointY( float y )
627 {
628   const Vector3& current = GetCurrentAnchorPoint();
629
630   SetAnchorPoint( Vector3( current.x, y, current.z ) );
631 }
632
633 void Actor::SetAnchorPointZ( float z )
634 {
635   const Vector3& current = GetCurrentAnchorPoint();
636
637   SetAnchorPoint( Vector3( current.x, current.y, z ) );
638 }
639
640 const Vector3& Actor::GetCurrentAnchorPoint() const
641 {
642   // Cached for event-thread access
643   return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
644 }
645
646 void Actor::SetPosition( float x, float y )
647 {
648   SetPosition( Vector3( x, y, 0.0f ) );
649 }
650
651 void Actor::SetPosition( float x, float y, float z )
652 {
653   SetPosition( Vector3( x, y, z ) );
654 }
655
656 void Actor::SetPosition( const Vector3& position )
657 {
658   mTargetPosition = position;
659
660   if( NULL != mNode )
661   {
662     // mNode is being used in a separate thread; queue a message to set the value & base value
663     SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
664   }
665 }
666
667 void Actor::SetX( float x )
668 {
669   mTargetPosition.x = x;
670
671   if( NULL != mNode )
672   {
673     // mNode is being used in a separate thread; queue a message to set the value & base value
674     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
675   }
676 }
677
678 void Actor::SetY( float y )
679 {
680   mTargetPosition.y = y;
681
682   if( NULL != mNode )
683   {
684     // mNode is being used in a separate thread; queue a message to set the value & base value
685     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
686   }
687 }
688
689 void Actor::SetZ( float z )
690 {
691   mTargetPosition.z = z;
692
693   if( NULL != mNode )
694   {
695     // mNode is being used in a separate thread; queue a message to set the value & base value
696     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
697   }
698 }
699
700 void Actor::TranslateBy( const Vector3& distance )
701 {
702   mTargetPosition += distance;
703
704   if( NULL != mNode )
705   {
706     // mNode is being used in a separate thread; queue a message to set the value & base value
707     SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
708   }
709 }
710
711 const Vector3& Actor::GetCurrentPosition() const
712 {
713   if( NULL != mNode )
714   {
715     // mNode is being used in a separate thread; copy the value from the previous update
716     return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
717   }
718
719   return Vector3::ZERO;
720 }
721
722 const Vector3& Actor::GetTargetPosition() const
723 {
724   return mTargetPosition;
725 }
726
727 const Vector3& Actor::GetCurrentWorldPosition() const
728 {
729   if( NULL != mNode )
730   {
731     // mNode is being used in a separate thread; copy the value from the previous update
732     return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
733   }
734
735   return Vector3::ZERO;
736 }
737
738 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
739 {
740   // this flag is not animatable so keep the value
741   mPositionInheritanceMode = mode;
742   if( NULL != mNode )
743   {
744     // mNode is being used in a separate thread; queue a message to set the value
745     SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
746   }
747 }
748
749 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
750 {
751   // Cached for event-thread access
752   return mPositionInheritanceMode;
753 }
754
755 void Actor::SetInheritPosition( bool inherit )
756 {
757   mInheritPosition = inherit;
758   if( NULL != mNode )
759   {
760     SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
761   }
762 }
763
764 bool Actor::IsPositionInherited() const
765 {
766   return mInheritPosition;
767 }
768
769 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
770 {
771   Vector3 normalizedAxis( axis.x, axis.y, axis.z );
772   normalizedAxis.Normalize();
773
774   Quaternion orientation( angle, normalizedAxis );
775
776   SetOrientation( orientation );
777 }
778
779 void Actor::SetOrientation( const Quaternion& orientation )
780 {
781   if( NULL != mNode )
782   {
783     // mNode is being used in a separate thread; queue a message to set the value & base value
784     SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
785   }
786 }
787
788 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
789 {
790   if( NULL != mNode )
791   {
792     // mNode is being used in a separate thread; queue a message to set the value & base value
793     SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
794   }
795 }
796
797 void Actor::RotateBy( const Quaternion& relativeRotation )
798 {
799   if( NULL != mNode )
800   {
801     // mNode is being used in a separate thread; queue a message to set the value & base value
802     SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
803   }
804 }
805
806 const Quaternion& Actor::GetCurrentOrientation() const
807 {
808   if( NULL != mNode )
809   {
810     // mNode is being used in a separate thread; copy the value from the previous update
811     return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
812   }
813
814   return Quaternion::IDENTITY;
815 }
816
817 const Quaternion& Actor::GetCurrentWorldOrientation() const
818 {
819   if( NULL != mNode )
820   {
821     // mNode is being used in a separate thread; copy the value from the previous update
822     return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
823   }
824
825   return Quaternion::IDENTITY;
826 }
827
828 void Actor::SetScale( float scale )
829 {
830   SetScale( Vector3( scale, scale, scale ) );
831 }
832
833 void Actor::SetScale( float x, float y, float z )
834 {
835   SetScale( Vector3( x, y, z ) );
836 }
837
838 void Actor::SetScale( const Vector3& scale )
839 {
840   if( NULL != mNode )
841   {
842     // mNode is being used in a separate thread; queue a message to set the value & base value
843     SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
844   }
845 }
846
847 void Actor::SetScaleX( float x )
848 {
849   if( NULL != mNode )
850   {
851     // mNode is being used in a separate thread; queue a message to set the value & base value
852     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
853   }
854 }
855
856 void Actor::SetScaleY( float y )
857 {
858   if( NULL != mNode )
859   {
860     // mNode is being used in a separate thread; queue a message to set the value & base value
861     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
862   }
863 }
864
865 void Actor::SetScaleZ( float z )
866 {
867   if( NULL != mNode )
868   {
869     // mNode is being used in a separate thread; queue a message to set the value & base value
870     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
871   }
872 }
873
874 void Actor::ScaleBy(const Vector3& relativeScale)
875 {
876   if( NULL != mNode )
877   {
878     // mNode is being used in a separate thread; queue a message to set the value & base value
879     SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
880   }
881 }
882
883 const Vector3& Actor::GetCurrentScale() const
884 {
885   if( NULL != mNode )
886   {
887     // mNode is being used in a separate thread; copy the value from the previous update
888     return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
889   }
890
891   return Vector3::ONE;
892 }
893
894 const Vector3& Actor::GetCurrentWorldScale() const
895 {
896   if( NULL != mNode )
897   {
898     // mNode is being used in a separate thread; copy the value from the previous update
899     return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
900   }
901
902   return Vector3::ONE;
903 }
904
905 void Actor::SetInheritScale( bool inherit )
906 {
907   // non animateable so keep local copy
908   mInheritScale = inherit;
909   if( NULL != mNode )
910   {
911     // mNode is being used in a separate thread; queue a message to set the value
912     SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
913   }
914 }
915
916 bool Actor::IsScaleInherited() const
917 {
918   return mInheritScale;
919 }
920
921 Matrix Actor::GetCurrentWorldMatrix() const
922 {
923   if( NULL != mNode )
924   {
925     // World matrix is no longer updated unless there is something observing the node.
926     // Need to calculate it from node's world position, orientation and scale:
927     BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
928     Matrix worldMatrix(false);
929     worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
930                                         mNode->GetWorldOrientation( updateBufferIndex ),
931                                         mNode->GetWorldPosition( updateBufferIndex ) );
932     return worldMatrix;
933   }
934
935   return Matrix::IDENTITY;
936 }
937
938 void Actor::SetVisible( bool visible )
939 {
940   if( NULL != mNode )
941   {
942     // mNode is being used in a separate thread; queue a message to set the value & base value
943     SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
944   }
945 }
946
947 bool Actor::IsVisible() const
948 {
949   if( NULL != mNode )
950   {
951     // mNode is being used in a separate thread; copy the value from the previous update
952     return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
953   }
954
955   return true;
956 }
957
958 void Actor::SetOpacity( float opacity )
959 {
960   if( NULL != mNode )
961   {
962     // mNode is being used in a separate thread; queue a message to set the value & base value
963     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
964   }
965 }
966
967 float Actor::GetCurrentOpacity() const
968 {
969   if( NULL != mNode )
970   {
971     // mNode is being used in a separate thread; copy the value from the previous update
972     return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
973   }
974
975   return 1.0f;
976 }
977
978 const Vector4& Actor::GetCurrentWorldColor() const
979 {
980   if( NULL != mNode )
981   {
982     return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
983   }
984
985   return Color::WHITE;
986 }
987
988 void Actor::SetColor( const Vector4& color )
989 {
990   if( NULL != mNode )
991   {
992     // mNode is being used in a separate thread; queue a message to set the value & base value
993     SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
994   }
995 }
996
997 void Actor::SetColorRed( float red )
998 {
999   if( NULL != mNode )
1000   {
1001     // mNode is being used in a separate thread; queue a message to set the value & base value
1002     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1003   }
1004 }
1005
1006 void Actor::SetColorGreen( float green )
1007 {
1008   if( NULL != mNode )
1009   {
1010     // mNode is being used in a separate thread; queue a message to set the value & base value
1011     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1012   }
1013 }
1014
1015 void Actor::SetColorBlue( float blue )
1016 {
1017   if( NULL != mNode )
1018   {
1019     // mNode is being used in a separate thread; queue a message to set the value & base value
1020     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1021   }
1022 }
1023
1024 const Vector4& Actor::GetCurrentColor() const
1025 {
1026   if( NULL != mNode )
1027   {
1028     // mNode is being used in a separate thread; copy the value from the previous update
1029     return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1030   }
1031
1032   return Color::WHITE;
1033 }
1034
1035 void Actor::SetInheritOrientation( bool inherit )
1036 {
1037   // non animateable so keep local copy
1038   mInheritOrientation = inherit;
1039   if( NULL != mNode )
1040   {
1041     // mNode is being used in a separate thread; queue a message to set the value
1042     SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1043   }
1044 }
1045
1046 bool Actor::IsOrientationInherited() const
1047 {
1048   return mInheritOrientation;
1049 }
1050
1051 void Actor::SetSizeModeFactor( const Vector3& factor )
1052 {
1053   EnsureRelayoutData();
1054
1055   mRelayoutData->sizeModeFactor = factor;
1056 }
1057
1058 const Vector3& Actor::GetSizeModeFactor() const
1059 {
1060   if ( mRelayoutData )
1061   {
1062     return mRelayoutData->sizeModeFactor;
1063   }
1064
1065   return GetDefaultSizeModeFactor();
1066 }
1067
1068 void Actor::SetColorMode( ColorMode colorMode )
1069 {
1070   // non animateable so keep local copy
1071   mColorMode = colorMode;
1072   if( NULL != mNode )
1073   {
1074     // mNode is being used in a separate thread; queue a message to set the value
1075     SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1076   }
1077 }
1078
1079 ColorMode Actor::GetColorMode() const
1080 {
1081   // we have cached copy
1082   return mColorMode;
1083 }
1084
1085 void Actor::SetSize( float width, float height )
1086 {
1087   SetSize( Vector2( width, height ) );
1088 }
1089
1090 void Actor::SetSize( float width, float height, float depth )
1091 {
1092   SetSize( Vector3( width, height, depth ) );
1093 }
1094
1095 void Actor::SetSize( const Vector2& size )
1096 {
1097   SetSize( Vector3( size.width, size.height, 0.f ) );
1098 }
1099
1100 void Actor::SetSizeInternal( const Vector2& size )
1101 {
1102   SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1103 }
1104
1105 void Actor::SetSize( const Vector3& size )
1106 {
1107   if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1108   {
1109     // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1110     SetPreferredSize( size.GetVectorXY() );
1111   }
1112   else
1113   {
1114     SetSizeInternal( size );
1115   }
1116 }
1117
1118 void Actor::SetSizeInternal( const Vector3& size )
1119 {
1120   // dont allow recursive loop
1121   DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1122   // 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
1123   if( ( NULL != mNode )&&
1124       ( ( fabsf( mTargetSize.width - size.width  ) > Math::MACHINE_EPSILON_1 )||
1125         ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1126         ( fabsf( mTargetSize.depth - size.depth  ) > Math::MACHINE_EPSILON_1 ) ) )
1127   {
1128     mTargetSize = size;
1129
1130     // mNode is being used in a separate thread; queue a message to set the value & base value
1131     SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1132
1133     // Notification for derived classes
1134     mInsideOnSizeSet = true;
1135     OnSizeSet( mTargetSize );
1136     mInsideOnSizeSet = false;
1137
1138     // Raise a relayout request if the flag is not locked
1139     if( mRelayoutData && !mRelayoutData->insideRelayout )
1140     {
1141       RelayoutRequest();
1142     }
1143   }
1144 }
1145
1146 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1147 {
1148   mTargetSize = targetSize;
1149
1150   // Notify deriving classes
1151   OnSizeAnimation( animation, mTargetSize );
1152 }
1153
1154 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1155 {
1156   if ( Dali::Actor::Property::SIZE_WIDTH == property )
1157   {
1158     mTargetSize.width = targetSize;
1159   }
1160   else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1161   {
1162     mTargetSize.height = targetSize;
1163   }
1164   else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1165   {
1166     mTargetSize.depth = targetSize;
1167   }
1168   // Notify deriving classes
1169   OnSizeAnimation( animation, mTargetSize );
1170 }
1171
1172 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1173 {
1174   mTargetPosition = targetPosition;
1175 }
1176
1177 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1178 {
1179   if ( Dali::Actor::Property::POSITION_X == property )
1180   {
1181     mTargetPosition.x = targetPosition;
1182   }
1183   else if ( Dali::Actor::Property::POSITION_Y == property )
1184   {
1185     mTargetPosition.y = targetPosition;
1186   }
1187   else if ( Dali::Actor::Property::POSITION_Z == property )
1188   {
1189     mTargetPosition.z = targetPosition;
1190   }
1191 }
1192
1193 void Actor::SetWidth( float width )
1194 {
1195   mTargetSize.width = width;
1196
1197   if( NULL != mNode )
1198   {
1199     // mNode is being used in a separate thread; queue a message to set the value & base value
1200     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1201   }
1202 }
1203
1204 void Actor::SetHeight( float height )
1205 {
1206   mTargetSize.height = height;
1207
1208   if( NULL != mNode )
1209   {
1210     // mNode is being used in a separate thread; queue a message to set the value & base value
1211     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1212   }
1213 }
1214
1215 void Actor::SetDepth( float depth )
1216 {
1217   mTargetSize.depth = depth;
1218
1219   if( NULL != mNode )
1220   {
1221     // mNode is being used in a separate thread; queue a message to set the value & base value
1222     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1223   }
1224 }
1225
1226 const Vector3& Actor::GetTargetSize() const
1227 {
1228   return mTargetSize;
1229 }
1230
1231 const Vector3& Actor::GetCurrentSize() const
1232 {
1233   if( NULL != mNode )
1234   {
1235     // mNode is being used in a separate thread; copy the value from the previous update
1236     return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1237   }
1238
1239   return Vector3::ZERO;
1240 }
1241
1242 Vector3 Actor::GetNaturalSize() const
1243 {
1244   // It is up to deriving classes to return the appropriate natural size
1245   return Vector3( 0.0f, 0.0f, 0.0f );
1246 }
1247
1248 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1249 {
1250   EnsureRelayoutData();
1251
1252   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1253   {
1254     if( dimension & ( 1 << i ) )
1255     {
1256       mRelayoutData->resizePolicies[ i ] = policy;
1257     }
1258   }
1259
1260   if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1261   {
1262     if( dimension & Dimension::WIDTH )
1263     {
1264       SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1265     }
1266
1267     if( dimension & Dimension::HEIGHT )
1268     {
1269       SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1270     }
1271   }
1272
1273   // If calling SetResizePolicy, assume we want relayout enabled
1274   SetRelayoutEnabled( true );
1275
1276   OnSetResizePolicy( policy, dimension );
1277
1278   // Trigger relayout on this control
1279   RelayoutRequest();
1280 }
1281
1282 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1283 {
1284   if ( mRelayoutData )
1285   {
1286     // If more than one dimension is requested, just return the first one found
1287     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1288     {
1289       if( ( dimension & ( 1 << i ) ) )
1290       {
1291         return mRelayoutData->resizePolicies[ i ];
1292       }
1293     }
1294   }
1295
1296   return ResizePolicy::DEFAULT;
1297 }
1298
1299 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1300 {
1301   EnsureRelayoutData();
1302
1303   mRelayoutData->sizeSetPolicy = policy;
1304 }
1305
1306 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1307 {
1308   if ( mRelayoutData )
1309   {
1310     return mRelayoutData->sizeSetPolicy;
1311   }
1312
1313   return DEFAULT_SIZE_SCALE_POLICY;
1314 }
1315
1316 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1317 {
1318   EnsureRelayoutData();
1319
1320   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1321   {
1322     if( dimension & ( 1 << i ) )
1323     {
1324       mRelayoutData->dimensionDependencies[ i ] = dependency;
1325     }
1326   }
1327 }
1328
1329 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1330 {
1331   if ( mRelayoutData )
1332   {
1333     // If more than one dimension is requested, just return the first one found
1334     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1335     {
1336       if( ( dimension & ( 1 << i ) ) )
1337       {
1338         return mRelayoutData->dimensionDependencies[ i ];
1339       }
1340     }
1341   }
1342
1343   return Dimension::ALL_DIMENSIONS;   // Default
1344 }
1345
1346 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1347 {
1348   // If relayout data has not been allocated yet and the client is requesting
1349   // to disable it, do nothing
1350   if( mRelayoutData || relayoutEnabled )
1351   {
1352     EnsureRelayoutData();
1353
1354     mRelayoutData->relayoutEnabled = relayoutEnabled;
1355   }
1356 }
1357
1358 bool Actor::IsRelayoutEnabled() const
1359 {
1360   // Assume that if relayout data has not been allocated yet then
1361   // relayout is disabled
1362   return mRelayoutData && mRelayoutData->relayoutEnabled;
1363 }
1364
1365 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1366 {
1367   EnsureRelayoutData();
1368
1369   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1370   {
1371     if( dimension & ( 1 << i ) )
1372     {
1373       mRelayoutData->dimensionDirty[ i ] = dirty;
1374     }
1375   }
1376 }
1377
1378 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1379 {
1380   if ( mRelayoutData )
1381   {
1382     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1383     {
1384       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1385       {
1386         return true;
1387       }
1388     }
1389   }
1390
1391   return false;
1392 }
1393
1394 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1395 {
1396   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1397 }
1398
1399 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1400 {
1401   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1402 }
1403
1404 unsigned int Actor::AddRenderer( Renderer& renderer )
1405 {
1406   if( !mRenderers )
1407   {
1408     mRenderers = new RendererContainer;
1409   }
1410
1411   unsigned int index = mRenderers->size();
1412   RendererPtr rendererPtr = RendererPtr( &renderer );
1413   mRenderers->push_back( rendererPtr );
1414   AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1415
1416   if( mIsOnStage)
1417   {
1418     rendererPtr->Connect();
1419   }
1420
1421   return index;
1422 }
1423
1424 unsigned int Actor::GetRendererCount() const
1425 {
1426   unsigned int rendererCount(0);
1427   if( mRenderers )
1428   {
1429     rendererCount = mRenderers->size();
1430   }
1431
1432   return rendererCount;
1433 }
1434
1435 RendererPtr Actor::GetRendererAt( unsigned int index )
1436 {
1437   RendererPtr renderer;
1438   if( index < GetRendererCount() )
1439   {
1440     renderer = ( *mRenderers )[ index ];
1441   }
1442
1443   return renderer;
1444 }
1445
1446 void Actor::RemoveRenderer( Renderer& renderer )
1447 {
1448   if( mRenderers )
1449   {
1450     RendererIter end = mRenderers->end();
1451     for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1452     {
1453       if( (*iter).Get() == &renderer )
1454       {
1455         mRenderers->erase( iter );
1456         RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1457         break;
1458       }
1459     }
1460   }
1461 }
1462
1463 void Actor::RemoveRenderer( unsigned int index )
1464 {
1465   if( index < GetRendererCount() )
1466   {
1467     RendererPtr renderer = ( *mRenderers )[ index ];
1468     RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1469     mRenderers->erase( mRenderers->begin()+index );
1470   }
1471 }
1472
1473 void Actor::SetOverlay( bool enable )
1474 {
1475   // Setting STENCIL will override OVERLAY_2D
1476   if( DrawMode::STENCIL != mDrawMode )
1477   {
1478     SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1479   }
1480 }
1481
1482 bool Actor::IsOverlay() const
1483 {
1484   return ( DrawMode::OVERLAY_2D == mDrawMode );
1485 }
1486
1487 void Actor::SetDrawMode( DrawMode::Type drawMode )
1488 {
1489   // this flag is not animatable so keep the value
1490   mDrawMode = drawMode;
1491   if( NULL != mNode )
1492   {
1493     // mNode is being used in a separate thread; queue a message to set the value
1494     SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1495   }
1496 }
1497
1498 DrawMode::Type Actor::GetDrawMode() const
1499 {
1500   return mDrawMode;
1501 }
1502
1503 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1504 {
1505   // only valid when on-stage
1506   StagePtr stage = Stage::GetCurrent();
1507   if( stage && OnStage() )
1508   {
1509     const RenderTaskList& taskList = stage->GetRenderTaskList();
1510
1511     Vector2 converted( screenX, screenY );
1512
1513     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1514     const int taskCount = taskList.GetTaskCount();
1515     for( int i = taskCount - 1; i >= 0; --i )
1516     {
1517       Dali::RenderTask task = taskList.GetTask( i );
1518       if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1519       {
1520         // found a task where this conversion was ok so return
1521         return true;
1522       }
1523     }
1524   }
1525   return false;
1526 }
1527
1528 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1529 {
1530   bool retval = false;
1531   // only valid when on-stage
1532   if( OnStage() )
1533   {
1534     CameraActor* camera = renderTask.GetCameraActor();
1535     if( camera )
1536     {
1537       Viewport viewport;
1538       renderTask.GetViewport( viewport );
1539
1540       // need to translate coordinates to render tasks coordinate space
1541       Vector2 converted( screenX, screenY );
1542       if( renderTask.TranslateCoordinates( converted ) )
1543       {
1544         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1545       }
1546     }
1547   }
1548   return retval;
1549 }
1550
1551 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1552 {
1553   // Early-out if mNode is NULL
1554   if( !OnStage() )
1555   {
1556     return false;
1557   }
1558
1559   BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1560
1561   // Calculate the ModelView matrix
1562   Matrix modelView( false/*don't init*/);
1563   // need to use the components as world matrix is only updated for actors that need it
1564   modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1565   Matrix::Multiply( modelView, modelView, viewMatrix );
1566
1567   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1568   Matrix invertedMvp( false/*don't init*/);
1569   Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1570   bool success = invertedMvp.Invert();
1571
1572   // Convert to GL coordinates
1573   Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1574
1575   Vector4 nearPos;
1576   if( success )
1577   {
1578     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1579   }
1580
1581   Vector4 farPos;
1582   if( success )
1583   {
1584     screenPos.z = 1.0f;
1585     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1586   }
1587
1588   if( success )
1589   {
1590     Vector4 local;
1591     if( XyPlaneIntersect( nearPos, farPos, local ) )
1592     {
1593       Vector3 size = GetCurrentSize();
1594       localX = local.x + size.x * 0.5f;
1595       localY = local.y + size.y * 0.5f;
1596     }
1597     else
1598     {
1599       success = false;
1600     }
1601   }
1602
1603   return success;
1604 }
1605
1606 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1607 {
1608   /*
1609    http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1610
1611    Mathematical Formulation
1612
1613    Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1614
1615    ( p - c ) dot ( p - c ) = r^2
1616
1617    Given a ray with a point of origin 'o', and a direction vector 'd':
1618
1619    ray(t) = o + td, t >= 0
1620
1621    we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1622
1623    (o + td - c ) dot ( o + td - c ) = r^2
1624
1625    To solve for t we first expand the above into a more recognisable quadratic equation form
1626
1627    ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1628
1629    or
1630
1631    At2 + Bt + C = 0
1632
1633    where
1634
1635    A = d dot d
1636    B = 2( o - c ) dot d
1637    C = ( o - c ) dot ( o - c ) - r^2
1638
1639    which can be solved using a standard quadratic formula.
1640
1641    Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1642
1643    Practical Simplification
1644
1645    In a renderer, we often differentiate between world space and object space. In the object space
1646    of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1647    into object space, the mathematical solution presented above can be simplified significantly.
1648
1649    If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1650
1651    p dot p = r^2
1652
1653    and we can find the t at which the (transformed) ray intersects the sphere by
1654
1655    ( o + td ) dot ( o + td ) = r^2
1656
1657    According to the reasoning above, we expand the above quadratic equation into the general form
1658
1659    At2 + Bt + C = 0
1660
1661    which now has coefficients:
1662
1663    A = d dot d
1664    B = 2( d dot o )
1665    C = o dot o - r^2
1666    */
1667
1668   // Early out if mNode is NULL
1669   if( !mNode )
1670   {
1671     return false;
1672   }
1673
1674   BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1675
1676   // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1677   const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1678   Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1679
1680   // Compute the radius is not needed, square radius it's enough.
1681   const Vector3& size( mNode->GetSize( bufferIndex ) );
1682
1683   // Scale the sphere.
1684   const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1685
1686   const float width = size.width * scale.width;
1687   const float height = size.height * scale.height;
1688
1689   float squareSphereRadius = 0.5f * ( width * width + height * height );
1690
1691   float a = rayDir.Dot( rayDir );                                       // a
1692   float b2 = rayDir.Dot( rayOriginLocal );                              // b/2
1693   float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius;  // c
1694
1695   return ( b2 * b2 - a * c ) >= 0.f;
1696 }
1697
1698 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1699 {
1700   bool hit = false;
1701
1702   if( OnStage() &&
1703   NULL != mNode )
1704   {
1705     // Transforms the ray to the local reference system.
1706     // Calculate the inverse of Model matrix
1707     Matrix invModelMatrix( false/*don't init*/);
1708
1709     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1710     // need to use the components as world matrix is only updated for actors that need it
1711     invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1712
1713     Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1714     Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1715
1716     // Test with the actor's XY plane (Normal = 0 0 1 1).
1717
1718     float a = -rayOriginLocal.z;
1719     float b = rayDirLocal.z;
1720
1721     if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1722     {
1723       // Ray travels distance * rayDirLocal to intersect with plane.
1724       distance = a / b;
1725
1726       const Vector3& size = mNode->GetSize( bufferIndex );
1727
1728       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1729       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1730
1731       // Test with the actor's geometry.
1732       hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1733     }
1734   }
1735
1736   return hit;
1737 }
1738
1739 void Actor::SetLeaveRequired( bool required )
1740 {
1741   mLeaveRequired = required;
1742 }
1743
1744 bool Actor::GetLeaveRequired() const
1745 {
1746   return mLeaveRequired;
1747 }
1748
1749 void Actor::SetKeyboardFocusable( bool focusable )
1750 {
1751   mKeyboardFocusable = focusable;
1752 }
1753
1754 bool Actor::IsKeyboardFocusable() const
1755 {
1756   return mKeyboardFocusable;
1757 }
1758
1759 bool Actor::GetTouchRequired() const
1760 {
1761   return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1762 }
1763
1764 bool Actor::GetHoverRequired() const
1765 {
1766   return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1767 }
1768
1769 bool Actor::GetWheelEventRequired() const
1770 {
1771   return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1772 }
1773
1774 bool Actor::IsHittable() const
1775 {
1776   return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1777 }
1778
1779 ActorGestureData& Actor::GetGestureData()
1780 {
1781   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1782   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1783   if( NULL == mGestureData )
1784   {
1785     mGestureData = new ActorGestureData;
1786   }
1787   return *mGestureData;
1788 }
1789
1790 bool Actor::IsGestureRequred( Gesture::Type type ) const
1791 {
1792   return mGestureData && mGestureData->IsGestureRequred( type );
1793 }
1794
1795 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1796 {
1797   bool consumed = false;
1798
1799   if( !mTouchedSignal.Empty() )
1800   {
1801     Dali::Actor handle( this );
1802     consumed = mTouchedSignal.Emit( handle, event );
1803   }
1804
1805   if( !consumed )
1806   {
1807     // Notification for derived classes
1808     consumed = OnTouchEvent( event );
1809   }
1810
1811   return consumed;
1812 }
1813
1814 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1815 {
1816   bool consumed = false;
1817
1818   if( !mHoveredSignal.Empty() )
1819   {
1820     Dali::Actor handle( this );
1821     consumed = mHoveredSignal.Emit( handle, event );
1822   }
1823
1824   if( !consumed )
1825   {
1826     // Notification for derived classes
1827     consumed = OnHoverEvent( event );
1828   }
1829
1830   return consumed;
1831 }
1832
1833 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1834 {
1835   bool consumed = false;
1836
1837   if( !mWheelEventSignal.Empty() )
1838   {
1839     Dali::Actor handle( this );
1840     consumed = mWheelEventSignal.Emit( handle, event );
1841   }
1842
1843   if( !consumed )
1844   {
1845     // Notification for derived classes
1846     consumed = OnWheelEvent( event );
1847   }
1848
1849   return consumed;
1850 }
1851
1852 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1853 {
1854   return mTouchedSignal;
1855 }
1856
1857 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1858 {
1859   return mHoveredSignal;
1860 }
1861
1862 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1863 {
1864   return mWheelEventSignal;
1865 }
1866
1867 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1868 {
1869   return mOnStageSignal;
1870 }
1871
1872 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1873 {
1874   return mOffStageSignal;
1875 }
1876
1877 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1878 {
1879   return mOnRelayoutSignal;
1880 }
1881
1882 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1883 {
1884   bool connected( true );
1885   Actor* actor = dynamic_cast< Actor* >( object );
1886
1887   if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1888   {
1889     actor->TouchedSignal().Connect( tracker, functor );
1890   }
1891   else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1892   {
1893     actor->HoveredSignal().Connect( tracker, functor );
1894   }
1895   else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1896   {
1897     actor->WheelEventSignal().Connect( tracker, functor );
1898   }
1899   else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1900   {
1901     actor->OnStageSignal().Connect( tracker, functor );
1902   }
1903   else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1904   {
1905     actor->OffStageSignal().Connect( tracker, functor );
1906   }
1907   else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1908   {
1909     actor->OnRelayoutSignal().Connect( tracker, functor );
1910   }
1911   else
1912   {
1913     // signalName does not match any signal
1914     connected = false;
1915   }
1916
1917   return connected;
1918 }
1919
1920 Actor::Actor( DerivedType derivedType )
1921 : mParent( NULL ),
1922   mChildren( NULL ),
1923   mRenderers( NULL ),
1924   mNode( NULL ),
1925   mParentOrigin( NULL ),
1926   mAnchorPoint( NULL ),
1927   mRelayoutData( NULL ),
1928   mGestureData( NULL ),
1929   mAttachment(),
1930   mTargetSize( 0.0f, 0.0f, 0.0f ),
1931   mName(),
1932   mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1933   mDepth( 0u ),
1934   mIsRoot( ROOT_LAYER == derivedType ),
1935   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1936   mIsOnStage( false ),
1937   mSensitive( true ),
1938   mLeaveRequired( false ),
1939   mKeyboardFocusable( false ),
1940   mDerivedRequiresTouch( false ),
1941   mDerivedRequiresHover( false ),
1942   mDerivedRequiresWheelEvent( false ),
1943   mOnStageSignalled( false ),
1944   mInsideOnSizeSet( false ),
1945   mInheritPosition( true ),
1946   mInheritOrientation( true ),
1947   mInheritScale( true ),
1948   mDrawMode( DrawMode::NORMAL ),
1949   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1950   mColorMode( Node::DEFAULT_COLOR_MODE )
1951 {
1952 }
1953
1954 void Actor::Initialize()
1955 {
1956   // Node creation
1957   SceneGraph::Node* node = CreateNode();
1958
1959   AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1960   mNode = node; // Keep raw-pointer to Node
1961
1962   OnInitialize();
1963
1964   GetEventThreadServices().RegisterObject( this );
1965 }
1966
1967 Actor::~Actor()
1968 {
1969   // Remove mParent pointers from children even if we're destroying core,
1970   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1971   if( mChildren )
1972   {
1973     ActorConstIter endIter = mChildren->end();
1974     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1975     {
1976       (*iter)->SetParent( NULL );
1977     }
1978   }
1979   delete mChildren;
1980   delete mRenderers;
1981
1982   // Guard to allow handle destruction after Core has been destroyed
1983   if( EventThreadServices::IsCoreRunning() )
1984   {
1985     if( NULL != mNode )
1986     {
1987       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1988       mNode = NULL; // Node is about to be destroyed
1989     }
1990
1991     GetEventThreadServices().UnregisterObject( this );
1992   }
1993
1994   // Cleanup optional gesture data
1995   delete mGestureData;
1996
1997   // Cleanup optional parent origin and anchor
1998   delete mParentOrigin;
1999   delete mAnchorPoint;
2000
2001   // Delete optional relayout data
2002   if( mRelayoutData )
2003   {
2004     delete mRelayoutData;
2005   }
2006 }
2007
2008 void Actor::ConnectToStage( unsigned int parentDepth )
2009 {
2010   // This container is used instead of walking the Actor hierarchy.
2011   // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2012   ActorContainer connectionList;
2013
2014   // This stage is atomic i.e. not interrupted by user callbacks.
2015   RecursiveConnectToStage( connectionList, parentDepth + 1 );
2016
2017   // Notify applications about the newly connected actors.
2018   const ActorIter endIter = connectionList.end();
2019   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2020   {
2021     (*iter)->NotifyStageConnection();
2022   }
2023
2024   RelayoutRequest();
2025 }
2026
2027 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2028 {
2029   DALI_ASSERT_ALWAYS( !OnStage() );
2030
2031   mIsOnStage = true;
2032   mDepth = depth;
2033
2034   ConnectToSceneGraph();
2035
2036   // Notification for internal derived classes
2037   OnStageConnectionInternal();
2038
2039   // This stage is atomic; avoid emitting callbacks until all Actors are connected
2040   connectionList.push_back( ActorPtr( this ) );
2041
2042   // Recursively connect children
2043   if( mChildren )
2044   {
2045     ActorConstIter endIter = mChildren->end();
2046     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2047     {
2048       (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2049     }
2050   }
2051 }
2052
2053 /**
2054  * This method is called when the Actor is connected to the Stage.
2055  * The parent must have added its Node to the scene-graph.
2056  * The child must connect its Node to the parent's Node.
2057  * This is recursive; the child calls ConnectToStage() for its children.
2058  */
2059 void Actor::ConnectToSceneGraph()
2060 {
2061   DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2062
2063   if( NULL != mNode )
2064   {
2065     // Reparent Node in next Update
2066     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2067   }
2068
2069   // Notify attachment
2070   if( mAttachment )
2071   {
2072     mAttachment->Connect();
2073   }
2074
2075   unsigned int rendererCount( GetRendererCount() );
2076   for( unsigned int i(0); i<rendererCount; ++i )
2077   {
2078     GetRendererAt(i)->Connect();
2079   }
2080
2081   // Request relayout on all actors that are added to the scenegraph
2082   RelayoutRequest();
2083
2084   // Notification for Object::Observers
2085   OnSceneObjectAdd();
2086 }
2087
2088 void Actor::NotifyStageConnection()
2089 {
2090   // Actors can be removed (in a callback), before the on-stage stage is reported.
2091   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2092   if( OnStage() && !mOnStageSignalled )
2093   {
2094     // Notification for external (CustomActor) derived classes
2095     OnStageConnectionExternal( mDepth );
2096
2097     if( !mOnStageSignal.Empty() )
2098     {
2099       Dali::Actor handle( this );
2100       mOnStageSignal.Emit( handle );
2101     }
2102
2103     // Guard against Remove during callbacks
2104     if( OnStage() )
2105     {
2106       mOnStageSignalled = true; // signal required next time Actor is removed
2107     }
2108   }
2109 }
2110
2111 void Actor::DisconnectFromStage()
2112 {
2113   // This container is used instead of walking the Actor hierachy.
2114   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2115   ActorContainer disconnectionList;
2116
2117   // This stage is atomic i.e. not interrupted by user callbacks
2118   RecursiveDisconnectFromStage( disconnectionList );
2119
2120   // Notify applications about the newly disconnected actors.
2121   const ActorIter endIter = disconnectionList.end();
2122   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2123   {
2124     (*iter)->NotifyStageDisconnection();
2125   }
2126 }
2127
2128 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2129 {
2130   DALI_ASSERT_ALWAYS( OnStage() );
2131
2132   // Recursively disconnect children
2133   if( mChildren )
2134   {
2135     ActorConstIter endIter = mChildren->end();
2136     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2137     {
2138       (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2139     }
2140   }
2141
2142   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2143   disconnectionList.push_back( ActorPtr( this ) );
2144
2145   // Notification for internal derived classes
2146   OnStageDisconnectionInternal();
2147
2148   DisconnectFromSceneGraph();
2149
2150   mIsOnStage = false;
2151 }
2152
2153 /**
2154  * This method is called by an actor or its parent, before a node removal message is sent.
2155  * This is recursive; the child calls DisconnectFromStage() for its children.
2156  */
2157 void Actor::DisconnectFromSceneGraph()
2158 {
2159   // Notification for Object::Observers
2160   OnSceneObjectRemove();
2161
2162   // Notify attachment
2163   if( mAttachment )
2164   {
2165     mAttachment->Disconnect();
2166   }
2167
2168   unsigned int rendererCount( GetRendererCount() );
2169   for( unsigned int i(0); i<rendererCount; ++i )
2170   {
2171     GetRendererAt(i)->Disconnect();
2172   }
2173 }
2174
2175 void Actor::NotifyStageDisconnection()
2176 {
2177   // Actors can be added (in a callback), before the off-stage state is reported.
2178   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2179   // only do this step if there is a stage, i.e. Core is not being shut down
2180   if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2181   {
2182     // Notification for external (CustomeActor) derived classes
2183     OnStageDisconnectionExternal();
2184
2185     if( !mOffStageSignal.Empty() )
2186     {
2187       Dali::Actor handle( this );
2188       mOffStageSignal.Emit( handle );
2189     }
2190
2191     // Guard against Add during callbacks
2192     if( !OnStage() )
2193     {
2194       mOnStageSignalled = false; // signal required next time Actor is added
2195     }
2196   }
2197 }
2198
2199 bool Actor::IsNodeConnected() const
2200 {
2201   bool connected( false );
2202
2203   if( OnStage() && ( NULL != mNode ) )
2204   {
2205     if( IsRoot() || mNode->GetParent() )
2206     {
2207       connected = true;
2208     }
2209   }
2210
2211   return connected;
2212 }
2213
2214 unsigned int Actor::GetDefaultPropertyCount() const
2215 {
2216   return DEFAULT_PROPERTY_COUNT;
2217 }
2218
2219 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2220 {
2221   indices.Reserve( DEFAULT_PROPERTY_COUNT );
2222
2223   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2224   {
2225     indices.PushBack( i );
2226   }
2227 }
2228
2229 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2230 {
2231   if( index < DEFAULT_PROPERTY_COUNT )
2232   {
2233     return DEFAULT_PROPERTY_DETAILS[ index ].name;
2234   }
2235
2236   return NULL;
2237 }
2238
2239 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2240 {
2241   Property::Index index = Property::INVALID_INDEX;
2242
2243   // Look for name in default properties
2244   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2245   {
2246     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2247     if( 0 == name.compare( property->name ) )
2248     {
2249       index = i;
2250       break;
2251     }
2252   }
2253
2254   return index;
2255 }
2256
2257 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2258 {
2259   if( index < DEFAULT_PROPERTY_COUNT )
2260   {
2261     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2262   }
2263
2264   return false;
2265 }
2266
2267 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2268 {
2269   if( index < DEFAULT_PROPERTY_COUNT )
2270   {
2271     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2272   }
2273
2274   return false;
2275 }
2276
2277 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2278 {
2279   if( index < DEFAULT_PROPERTY_COUNT )
2280   {
2281     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2282   }
2283
2284   return false;
2285 }
2286
2287 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2288 {
2289   if( index < DEFAULT_PROPERTY_COUNT )
2290   {
2291     return DEFAULT_PROPERTY_DETAILS[ index ].type;
2292   }
2293
2294   // index out of range...return Property::NONE
2295   return Property::NONE;
2296 }
2297
2298 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2299 {
2300   switch( index )
2301   {
2302     case Dali::Actor::Property::PARENT_ORIGIN:
2303     {
2304       SetParentOrigin( property.Get< Vector3 >() );
2305       break;
2306     }
2307
2308     case Dali::Actor::Property::PARENT_ORIGIN_X:
2309     {
2310       SetParentOriginX( property.Get< float >() );
2311       break;
2312     }
2313
2314     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2315     {
2316       SetParentOriginY( property.Get< float >() );
2317       break;
2318     }
2319
2320     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2321     {
2322       SetParentOriginZ( property.Get< float >() );
2323       break;
2324     }
2325
2326     case Dali::Actor::Property::ANCHOR_POINT:
2327     {
2328       SetAnchorPoint( property.Get< Vector3 >() );
2329       break;
2330     }
2331
2332     case Dali::Actor::Property::ANCHOR_POINT_X:
2333     {
2334       SetAnchorPointX( property.Get< float >() );
2335       break;
2336     }
2337
2338     case Dali::Actor::Property::ANCHOR_POINT_Y:
2339     {
2340       SetAnchorPointY( property.Get< float >() );
2341       break;
2342     }
2343
2344     case Dali::Actor::Property::ANCHOR_POINT_Z:
2345     {
2346       SetAnchorPointZ( property.Get< float >() );
2347       break;
2348     }
2349
2350     case Dali::Actor::Property::SIZE:
2351     {
2352       SetSize( property.Get< Vector3 >() );
2353       break;
2354     }
2355
2356     case Dali::Actor::Property::SIZE_WIDTH:
2357     {
2358       SetWidth( property.Get< float >() );
2359       break;
2360     }
2361
2362     case Dali::Actor::Property::SIZE_HEIGHT:
2363     {
2364       SetHeight( property.Get< float >() );
2365       break;
2366     }
2367
2368     case Dali::Actor::Property::SIZE_DEPTH:
2369     {
2370       SetDepth( property.Get< float >() );
2371       break;
2372     }
2373
2374     case Dali::Actor::Property::POSITION:
2375     {
2376       SetPosition( property.Get< Vector3 >() );
2377       break;
2378     }
2379
2380     case Dali::Actor::Property::POSITION_X:
2381     {
2382       SetX( property.Get< float >() );
2383       break;
2384     }
2385
2386     case Dali::Actor::Property::POSITION_Y:
2387     {
2388       SetY( property.Get< float >() );
2389       break;
2390     }
2391
2392     case Dali::Actor::Property::POSITION_Z:
2393     {
2394       SetZ( property.Get< float >() );
2395       break;
2396     }
2397
2398     case Dali::Actor::Property::ORIENTATION:
2399     {
2400       SetOrientation( property.Get< Quaternion >() );
2401       break;
2402     }
2403
2404     case Dali::Actor::Property::SCALE:
2405     {
2406       SetScale( property.Get< Vector3 >() );
2407       break;
2408     }
2409
2410     case Dali::Actor::Property::SCALE_X:
2411     {
2412       SetScaleX( property.Get< float >() );
2413       break;
2414     }
2415
2416     case Dali::Actor::Property::SCALE_Y:
2417     {
2418       SetScaleY( property.Get< float >() );
2419       break;
2420     }
2421
2422     case Dali::Actor::Property::SCALE_Z:
2423     {
2424       SetScaleZ( property.Get< float >() );
2425       break;
2426     }
2427
2428     case Dali::Actor::Property::VISIBLE:
2429     {
2430       SetVisible( property.Get< bool >() );
2431       break;
2432     }
2433
2434     case Dali::Actor::Property::COLOR:
2435     {
2436       SetColor( property.Get< Vector4 >() );
2437       break;
2438     }
2439
2440     case Dali::Actor::Property::COLOR_RED:
2441     {
2442       SetColorRed( property.Get< float >() );
2443       break;
2444     }
2445
2446     case Dali::Actor::Property::COLOR_GREEN:
2447     {
2448       SetColorGreen( property.Get< float >() );
2449       break;
2450     }
2451
2452     case Dali::Actor::Property::COLOR_BLUE:
2453     {
2454       SetColorBlue( property.Get< float >() );
2455       break;
2456     }
2457
2458     case Dali::Actor::Property::COLOR_ALPHA:
2459     {
2460       SetOpacity( property.Get< float >() );
2461       break;
2462     }
2463
2464     case Dali::Actor::Property::NAME:
2465     {
2466       SetName( property.Get< std::string >() );
2467       break;
2468     }
2469
2470     case Dali::Actor::Property::SENSITIVE:
2471     {
2472       SetSensitive( property.Get< bool >() );
2473       break;
2474     }
2475
2476     case Dali::Actor::Property::LEAVE_REQUIRED:
2477     {
2478       SetLeaveRequired( property.Get< bool >() );
2479       break;
2480     }
2481
2482     case Dali::Actor::Property::INHERIT_POSITION:
2483     {
2484       SetInheritPosition( property.Get< bool >() );
2485       break;
2486     }
2487
2488     case Dali::Actor::Property::INHERIT_ORIENTATION:
2489     {
2490       SetInheritOrientation( property.Get< bool >() );
2491       break;
2492     }
2493
2494     case Dali::Actor::Property::INHERIT_SCALE:
2495     {
2496       SetInheritScale( property.Get< bool >() );
2497       break;
2498     }
2499
2500     case Dali::Actor::Property::COLOR_MODE:
2501     {
2502       SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2503       break;
2504     }
2505
2506     case Dali::Actor::Property::POSITION_INHERITANCE:
2507     {
2508       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2509       break;
2510     }
2511
2512     case Dali::Actor::Property::DRAW_MODE:
2513     {
2514       SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2515       break;
2516     }
2517
2518     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2519     {
2520       SetSizeModeFactor( property.Get< Vector3 >() );
2521       break;
2522     }
2523
2524     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2525     {
2526       ResizePolicy::Type type;
2527       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2528       {
2529         SetResizePolicy( type, Dimension::WIDTH );
2530       }
2531       break;
2532     }
2533
2534     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2535     {
2536       ResizePolicy::Type type;
2537       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2538       {
2539         SetResizePolicy( type, Dimension::HEIGHT );
2540       }
2541       break;
2542     }
2543
2544     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2545     {
2546       SizeScalePolicy::Type type;
2547       if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2548       {
2549         SetSizeScalePolicy( type );
2550       }
2551       break;
2552     }
2553
2554     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2555     {
2556       if( property.Get< bool >() )
2557       {
2558         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2559       }
2560       break;
2561     }
2562
2563     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2564     {
2565       if( property.Get< bool >() )
2566       {
2567         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2568       }
2569       break;
2570     }
2571
2572     case Dali::Actor::Property::PADDING:
2573     {
2574       Vector4 padding = property.Get< Vector4 >();
2575       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2576       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2577       break;
2578     }
2579
2580     case Dali::Actor::Property::MINIMUM_SIZE:
2581     {
2582       Vector2 size = property.Get< Vector2 >();
2583       SetMinimumSize( size.x, Dimension::WIDTH );
2584       SetMinimumSize( size.y, Dimension::HEIGHT );
2585       break;
2586     }
2587
2588     case Dali::Actor::Property::MAXIMUM_SIZE:
2589     {
2590       Vector2 size = property.Get< Vector2 >();
2591       SetMaximumSize( size.x, Dimension::WIDTH );
2592       SetMaximumSize( size.y, Dimension::HEIGHT );
2593       break;
2594     }
2595
2596     default:
2597     {
2598       // this can happen in the case of a non-animatable default property so just do nothing
2599       break;
2600     }
2601   }
2602 }
2603
2604 // TODO: This method needs to be removed
2605 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2606 {
2607   switch( entry.GetType() )
2608   {
2609     case Property::BOOLEAN:
2610     {
2611       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2612       DALI_ASSERT_DEBUG( NULL != property );
2613
2614       // property is being used in a separate thread; queue a message to set the property
2615       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2616
2617       break;
2618     }
2619
2620     case Property::INTEGER:
2621     {
2622       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2623       DALI_ASSERT_DEBUG( NULL != property );
2624
2625       // property is being used in a separate thread; queue a message to set the property
2626       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2627
2628       break;
2629     }
2630
2631     case Property::FLOAT:
2632     {
2633       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2634       DALI_ASSERT_DEBUG( NULL != property );
2635
2636       // property is being used in a separate thread; queue a message to set the property
2637       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2638
2639       break;
2640     }
2641
2642     case Property::VECTOR2:
2643     {
2644       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2645       DALI_ASSERT_DEBUG( NULL != property );
2646
2647       // property is being used in a separate thread; queue a message to set the property
2648       if(entry.componentIndex == 0)
2649       {
2650         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2651       }
2652       else if(entry.componentIndex == 1)
2653       {
2654         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2655       }
2656       else
2657       {
2658         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2659       }
2660
2661       break;
2662     }
2663
2664     case Property::VECTOR3:
2665     {
2666       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2667       DALI_ASSERT_DEBUG( NULL != property );
2668
2669       // property is being used in a separate thread; queue a message to set the property
2670       if(entry.componentIndex == 0)
2671       {
2672         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2673       }
2674       else if(entry.componentIndex == 1)
2675       {
2676         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2677       }
2678       else if(entry.componentIndex == 2)
2679       {
2680         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2681       }
2682       else
2683       {
2684         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2685       }
2686
2687       break;
2688     }
2689
2690     case Property::VECTOR4:
2691     {
2692       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2693       DALI_ASSERT_DEBUG( NULL != property );
2694
2695       // property is being used in a separate thread; queue a message to set the property
2696       if(entry.componentIndex == 0)
2697       {
2698         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2699       }
2700       else if(entry.componentIndex == 1)
2701       {
2702         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2703       }
2704       else if(entry.componentIndex == 2)
2705       {
2706         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2707       }
2708       else if(entry.componentIndex == 3)
2709       {
2710         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2711       }
2712       else
2713       {
2714         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2715       }
2716
2717       break;
2718     }
2719
2720     case Property::ROTATION:
2721     {
2722       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2723       DALI_ASSERT_DEBUG( NULL != property );
2724
2725       // property is being used in a separate thread; queue a message to set the property
2726       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
2727
2728       break;
2729     }
2730
2731     case Property::MATRIX:
2732     {
2733       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2734       DALI_ASSERT_DEBUG( NULL != property );
2735
2736       // property is being used in a separate thread; queue a message to set the property
2737       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
2738
2739       break;
2740     }
2741
2742     case Property::MATRIX3:
2743     {
2744       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2745       DALI_ASSERT_DEBUG( NULL != property );
2746
2747       // property is being used in a separate thread; queue a message to set the property
2748       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
2749
2750       break;
2751     }
2752
2753     default:
2754     {
2755       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2756       break;
2757     }
2758   } // entry.GetType
2759 }
2760
2761 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2762 {
2763   Property::Value value;
2764
2765   switch( index )
2766   {
2767     case Dali::Actor::Property::PARENT_ORIGIN:
2768     {
2769       value = GetCurrentParentOrigin();
2770       break;
2771     }
2772
2773     case Dali::Actor::Property::PARENT_ORIGIN_X:
2774     {
2775       value = GetCurrentParentOrigin().x;
2776       break;
2777     }
2778
2779     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2780     {
2781       value = GetCurrentParentOrigin().y;
2782       break;
2783     }
2784
2785     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2786     {
2787       value = GetCurrentParentOrigin().z;
2788       break;
2789     }
2790
2791     case Dali::Actor::Property::ANCHOR_POINT:
2792     {
2793       value = GetCurrentAnchorPoint();
2794       break;
2795     }
2796
2797     case Dali::Actor::Property::ANCHOR_POINT_X:
2798     {
2799       value = GetCurrentAnchorPoint().x;
2800       break;
2801     }
2802
2803     case Dali::Actor::Property::ANCHOR_POINT_Y:
2804     {
2805       value = GetCurrentAnchorPoint().y;
2806       break;
2807     }
2808
2809     case Dali::Actor::Property::ANCHOR_POINT_Z:
2810     {
2811       value = GetCurrentAnchorPoint().z;
2812       break;
2813     }
2814
2815     case Dali::Actor::Property::SIZE:
2816     {
2817       value = GetTargetSize();
2818       break;
2819     }
2820
2821     case Dali::Actor::Property::SIZE_WIDTH:
2822     {
2823       value = GetTargetSize().width;
2824       break;
2825     }
2826
2827     case Dali::Actor::Property::SIZE_HEIGHT:
2828     {
2829       value = GetTargetSize().height;
2830       break;
2831     }
2832
2833     case Dali::Actor::Property::SIZE_DEPTH:
2834     {
2835       value = GetTargetSize().depth;
2836       break;
2837     }
2838
2839     case Dali::Actor::Property::POSITION:
2840     {
2841       value = GetTargetPosition();
2842       break;
2843     }
2844
2845     case Dali::Actor::Property::POSITION_X:
2846     {
2847       value = GetTargetPosition().x;
2848       break;
2849     }
2850
2851     case Dali::Actor::Property::POSITION_Y:
2852     {
2853       value = GetTargetPosition().y;
2854       break;
2855     }
2856
2857     case Dali::Actor::Property::POSITION_Z:
2858     {
2859       value = GetTargetPosition().z;
2860       break;
2861     }
2862
2863     case Dali::Actor::Property::WORLD_POSITION:
2864     {
2865       value = GetCurrentWorldPosition();
2866       break;
2867     }
2868
2869     case Dali::Actor::Property::WORLD_POSITION_X:
2870     {
2871       value = GetCurrentWorldPosition().x;
2872       break;
2873     }
2874
2875     case Dali::Actor::Property::WORLD_POSITION_Y:
2876     {
2877       value = GetCurrentWorldPosition().y;
2878       break;
2879     }
2880
2881     case Dali::Actor::Property::WORLD_POSITION_Z:
2882     {
2883       value = GetCurrentWorldPosition().z;
2884       break;
2885     }
2886
2887     case Dali::Actor::Property::ORIENTATION:
2888     {
2889       value = GetCurrentOrientation();
2890       break;
2891     }
2892
2893     case Dali::Actor::Property::WORLD_ORIENTATION:
2894     {
2895       value = GetCurrentWorldOrientation();
2896       break;
2897     }
2898
2899     case Dali::Actor::Property::SCALE:
2900     {
2901       value = GetCurrentScale();
2902       break;
2903     }
2904
2905     case Dali::Actor::Property::SCALE_X:
2906     {
2907       value = GetCurrentScale().x;
2908       break;
2909     }
2910
2911     case Dali::Actor::Property::SCALE_Y:
2912     {
2913       value = GetCurrentScale().y;
2914       break;
2915     }
2916
2917     case Dali::Actor::Property::SCALE_Z:
2918     {
2919       value = GetCurrentScale().z;
2920       break;
2921     }
2922
2923     case Dali::Actor::Property::WORLD_SCALE:
2924     {
2925       value = GetCurrentWorldScale();
2926       break;
2927     }
2928
2929     case Dali::Actor::Property::VISIBLE:
2930     {
2931       value = IsVisible();
2932       break;
2933     }
2934
2935     case Dali::Actor::Property::COLOR:
2936     {
2937       value = GetCurrentColor();
2938       break;
2939     }
2940
2941     case Dali::Actor::Property::COLOR_RED:
2942     {
2943       value = GetCurrentColor().r;
2944       break;
2945     }
2946
2947     case Dali::Actor::Property::COLOR_GREEN:
2948     {
2949       value = GetCurrentColor().g;
2950       break;
2951     }
2952
2953     case Dali::Actor::Property::COLOR_BLUE:
2954     {
2955       value = GetCurrentColor().b;
2956       break;
2957     }
2958
2959     case Dali::Actor::Property::COLOR_ALPHA:
2960     {
2961       value = GetCurrentColor().a;
2962       break;
2963     }
2964
2965     case Dali::Actor::Property::WORLD_COLOR:
2966     {
2967       value = GetCurrentWorldColor();
2968       break;
2969     }
2970
2971     case Dali::Actor::Property::WORLD_MATRIX:
2972     {
2973       value = GetCurrentWorldMatrix();
2974       break;
2975     }
2976
2977     case Dali::Actor::Property::NAME:
2978     {
2979       value = GetName();
2980       break;
2981     }
2982
2983     case Dali::Actor::Property::SENSITIVE:
2984     {
2985       value = IsSensitive();
2986       break;
2987     }
2988
2989     case Dali::Actor::Property::LEAVE_REQUIRED:
2990     {
2991       value = GetLeaveRequired();
2992       break;
2993     }
2994
2995     case Dali::Actor::Property::INHERIT_POSITION:
2996     {
2997       value = IsPositionInherited();
2998       break;
2999     }
3000
3001     case Dali::Actor::Property::INHERIT_ORIENTATION:
3002     {
3003       value = IsOrientationInherited();
3004       break;
3005     }
3006
3007     case Dali::Actor::Property::INHERIT_SCALE:
3008     {
3009       value = IsScaleInherited();
3010       break;
3011     }
3012
3013     case Dali::Actor::Property::COLOR_MODE:
3014     {
3015       value = Scripting::GetColorMode( GetColorMode() );
3016       break;
3017     }
3018
3019     case Dali::Actor::Property::POSITION_INHERITANCE:
3020     {
3021       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3022       break;
3023     }
3024
3025     case Dali::Actor::Property::DRAW_MODE:
3026     {
3027       value = Scripting::GetDrawMode( GetDrawMode() );
3028       break;
3029     }
3030
3031     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3032     {
3033       value = GetSizeModeFactor();
3034       break;
3035     }
3036
3037     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3038     {
3039       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3040       break;
3041     }
3042
3043     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3044     {
3045       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3046       break;
3047     }
3048
3049     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3050     {
3051       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3052       break;
3053     }
3054
3055     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3056     {
3057       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3058       break;
3059     }
3060
3061     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3062     {
3063       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3064       break;
3065     }
3066
3067     case Dali::Actor::Property::PADDING:
3068     {
3069       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3070       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3071       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3072       break;
3073     }
3074
3075     case Dali::Actor::Property::MINIMUM_SIZE:
3076     {
3077       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3078       break;
3079     }
3080
3081     case Dali::Actor::Property::MAXIMUM_SIZE:
3082     {
3083       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3084       break;
3085     }
3086
3087     default:
3088     {
3089       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3090       break;
3091     }
3092   }
3093
3094   return value;
3095 }
3096
3097 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3098 {
3099   return mNode;
3100 }
3101
3102 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3103 {
3104   // This method should only return an object connected to the scene-graph
3105   return OnStage() ? mNode : NULL;
3106 }
3107
3108 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3109 {
3110   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3111
3112   const PropertyBase* property( NULL );
3113
3114   // This method should only return a property of an object connected to the scene-graph
3115   if( !OnStage() )
3116   {
3117     return property;
3118   }
3119
3120   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3121   {
3122     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3123     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3124
3125     property = animatable->GetSceneGraphProperty();
3126   }
3127   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3128   {
3129     CustomPropertyMetadata* custom = FindCustomProperty( index );
3130     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3131
3132     property = custom->GetSceneGraphProperty();
3133   }
3134   else if( NULL != mNode )
3135   {
3136     switch( index )
3137     {
3138       case Dali::Actor::Property::SIZE:
3139         property = &mNode->mSize;
3140         break;
3141
3142       case Dali::Actor::Property::SIZE_WIDTH:
3143         property = &mNode->mSize;
3144         break;
3145
3146       case Dali::Actor::Property::SIZE_HEIGHT:
3147         property = &mNode->mSize;
3148         break;
3149
3150       case Dali::Actor::Property::SIZE_DEPTH:
3151         property = &mNode->mSize;
3152         break;
3153
3154       case Dali::Actor::Property::POSITION:
3155         property = &mNode->mPosition;
3156         break;
3157
3158       case Dali::Actor::Property::POSITION_X:
3159         property = &mNode->mPosition;
3160         break;
3161
3162       case Dali::Actor::Property::POSITION_Y:
3163         property = &mNode->mPosition;
3164         break;
3165
3166       case Dali::Actor::Property::POSITION_Z:
3167         property = &mNode->mPosition;
3168         break;
3169
3170       case Dali::Actor::Property::ORIENTATION:
3171         property = &mNode->mOrientation;
3172         break;
3173
3174       case Dali::Actor::Property::SCALE:
3175         property = &mNode->mScale;
3176         break;
3177
3178       case Dali::Actor::Property::SCALE_X:
3179         property = &mNode->mScale;
3180         break;
3181
3182       case Dali::Actor::Property::SCALE_Y:
3183         property = &mNode->mScale;
3184         break;
3185
3186       case Dali::Actor::Property::SCALE_Z:
3187         property = &mNode->mScale;
3188         break;
3189
3190       case Dali::Actor::Property::VISIBLE:
3191         property = &mNode->mVisible;
3192         break;
3193
3194       case Dali::Actor::Property::COLOR:
3195         property = &mNode->mColor;
3196         break;
3197
3198       case Dali::Actor::Property::COLOR_RED:
3199         property = &mNode->mColor;
3200         break;
3201
3202       case Dali::Actor::Property::COLOR_GREEN:
3203         property = &mNode->mColor;
3204         break;
3205
3206       case Dali::Actor::Property::COLOR_BLUE:
3207         property = &mNode->mColor;
3208         break;
3209
3210       case Dali::Actor::Property::COLOR_ALPHA:
3211         property = &mNode->mColor;
3212         break;
3213
3214       default:
3215         break;
3216     }
3217   }
3218
3219   return property;
3220 }
3221
3222 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3223 {
3224   const PropertyInputImpl* property( NULL );
3225
3226   // This method should only return a property of an object connected to the scene-graph
3227   if( !OnStage() )
3228   {
3229     return property;
3230   }
3231
3232   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3233   {
3234     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3235     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3236
3237     property = animatable->GetSceneGraphProperty();
3238   }
3239   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3240   {
3241     CustomPropertyMetadata* custom = FindCustomProperty( index );
3242     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3243     property = custom->GetSceneGraphProperty();
3244   }
3245   else if( NULL != mNode )
3246   {
3247     switch( index )
3248     {
3249       case Dali::Actor::Property::PARENT_ORIGIN:
3250         property = &mNode->mParentOrigin;
3251         break;
3252
3253       case Dali::Actor::Property::PARENT_ORIGIN_X:
3254         property = &mNode->mParentOrigin;
3255         break;
3256
3257       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3258         property = &mNode->mParentOrigin;
3259         break;
3260
3261       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3262         property = &mNode->mParentOrigin;
3263         break;
3264
3265       case Dali::Actor::Property::ANCHOR_POINT:
3266         property = &mNode->mAnchorPoint;
3267         break;
3268
3269       case Dali::Actor::Property::ANCHOR_POINT_X:
3270         property = &mNode->mAnchorPoint;
3271         break;
3272
3273       case Dali::Actor::Property::ANCHOR_POINT_Y:
3274         property = &mNode->mAnchorPoint;
3275         break;
3276
3277       case Dali::Actor::Property::ANCHOR_POINT_Z:
3278         property = &mNode->mAnchorPoint;
3279         break;
3280
3281       case Dali::Actor::Property::SIZE:
3282         property = &mNode->mSize;
3283         break;
3284
3285       case Dali::Actor::Property::SIZE_WIDTH:
3286         property = &mNode->mSize;
3287         break;
3288
3289       case Dali::Actor::Property::SIZE_HEIGHT:
3290         property = &mNode->mSize;
3291         break;
3292
3293       case Dali::Actor::Property::SIZE_DEPTH:
3294         property = &mNode->mSize;
3295         break;
3296
3297       case Dali::Actor::Property::POSITION:
3298         property = &mNode->mPosition;
3299         break;
3300
3301       case Dali::Actor::Property::POSITION_X:
3302         property = &mNode->mPosition;
3303         break;
3304
3305       case Dali::Actor::Property::POSITION_Y:
3306         property = &mNode->mPosition;
3307         break;
3308
3309       case Dali::Actor::Property::POSITION_Z:
3310         property = &mNode->mPosition;
3311         break;
3312
3313       case Dali::Actor::Property::WORLD_POSITION:
3314         property = &mNode->mWorldPosition;
3315         break;
3316
3317       case Dali::Actor::Property::WORLD_POSITION_X:
3318         property = &mNode->mWorldPosition;
3319         break;
3320
3321       case Dali::Actor::Property::WORLD_POSITION_Y:
3322         property = &mNode->mWorldPosition;
3323         break;
3324
3325       case Dali::Actor::Property::WORLD_POSITION_Z:
3326         property = &mNode->mWorldPosition;
3327         break;
3328
3329       case Dali::Actor::Property::ORIENTATION:
3330         property = &mNode->mOrientation;
3331         break;
3332
3333       case Dali::Actor::Property::WORLD_ORIENTATION:
3334         property = &mNode->mWorldOrientation;
3335         break;
3336
3337       case Dali::Actor::Property::SCALE:
3338         property = &mNode->mScale;
3339         break;
3340
3341       case Dali::Actor::Property::SCALE_X:
3342         property = &mNode->mScale;
3343         break;
3344
3345       case Dali::Actor::Property::SCALE_Y:
3346         property = &mNode->mScale;
3347         break;
3348
3349       case Dali::Actor::Property::SCALE_Z:
3350         property = &mNode->mScale;
3351         break;
3352
3353       case Dali::Actor::Property::WORLD_SCALE:
3354         property = &mNode->mWorldScale;
3355         break;
3356
3357       case Dali::Actor::Property::VISIBLE:
3358         property = &mNode->mVisible;
3359         break;
3360
3361       case Dali::Actor::Property::COLOR:
3362         property = &mNode->mColor;
3363         break;
3364
3365       case Dali::Actor::Property::COLOR_RED:
3366         property = &mNode->mColor;
3367         break;
3368
3369       case Dali::Actor::Property::COLOR_GREEN:
3370         property = &mNode->mColor;
3371         break;
3372
3373       case Dali::Actor::Property::COLOR_BLUE:
3374         property = &mNode->mColor;
3375         break;
3376
3377       case Dali::Actor::Property::COLOR_ALPHA:
3378         property = &mNode->mColor;
3379         break;
3380
3381       case Dali::Actor::Property::WORLD_COLOR:
3382         property = &mNode->mWorldColor;
3383         break;
3384
3385       case Dali::Actor::Property::WORLD_MATRIX:
3386         property = &mNode->mWorldMatrix;
3387         break;
3388
3389       default:
3390         break;
3391     }
3392   }
3393
3394   return property;
3395 }
3396
3397 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3398 {
3399   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3400
3401   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3402   {
3403     // check whether the animatable property is registered already, if not then register one.
3404     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3405     if( animatableProperty )
3406     {
3407       componentIndex = animatableProperty->componentIndex;
3408     }
3409   }
3410   else
3411   {
3412     switch( index )
3413     {
3414       case Dali::Actor::Property::PARENT_ORIGIN_X:
3415       case Dali::Actor::Property::ANCHOR_POINT_X:
3416       case Dali::Actor::Property::SIZE_WIDTH:
3417       case Dali::Actor::Property::POSITION_X:
3418       case Dali::Actor::Property::WORLD_POSITION_X:
3419       case Dali::Actor::Property::SCALE_X:
3420       case Dali::Actor::Property::COLOR_RED:
3421       {
3422         componentIndex = 0;
3423         break;
3424       }
3425
3426       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3427       case Dali::Actor::Property::ANCHOR_POINT_Y:
3428       case Dali::Actor::Property::SIZE_HEIGHT:
3429       case Dali::Actor::Property::POSITION_Y:
3430       case Dali::Actor::Property::WORLD_POSITION_Y:
3431       case Dali::Actor::Property::SCALE_Y:
3432       case Dali::Actor::Property::COLOR_GREEN:
3433       {
3434         componentIndex = 1;
3435         break;
3436       }
3437
3438       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3439       case Dali::Actor::Property::ANCHOR_POINT_Z:
3440       case Dali::Actor::Property::SIZE_DEPTH:
3441       case Dali::Actor::Property::POSITION_Z:
3442       case Dali::Actor::Property::WORLD_POSITION_Z:
3443       case Dali::Actor::Property::SCALE_Z:
3444       case Dali::Actor::Property::COLOR_BLUE:
3445       {
3446         componentIndex = 2;
3447         break;
3448       }
3449
3450       case Dali::Actor::Property::COLOR_ALPHA:
3451       {
3452         componentIndex = 3;
3453         break;
3454       }
3455
3456       default:
3457       {
3458         // Do nothing
3459         break;
3460       }
3461     }
3462   }
3463
3464   return componentIndex;
3465 }
3466
3467 void Actor::SetParent( Actor* parent )
3468 {
3469   if( parent )
3470   {
3471     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3472
3473     mParent = parent;
3474
3475     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3476          parent->OnStage() )
3477     {
3478       // Instruct each actor to create a corresponding node in the scene graph
3479       ConnectToStage( parent->GetHierarchyDepth() );
3480     }
3481   }
3482   else // parent being set to NULL
3483   {
3484     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3485
3486     mParent = NULL;
3487
3488     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3489          OnStage() )
3490     {
3491       DALI_ASSERT_ALWAYS( mNode != NULL );
3492
3493       if( NULL != mNode )
3494       {
3495         // Disconnect the Node & its children from the scene-graph.
3496         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3497       }
3498
3499       // Instruct each actor to discard pointers to the scene-graph
3500       DisconnectFromStage();
3501     }
3502   }
3503 }
3504
3505 SceneGraph::Node* Actor::CreateNode() const
3506 {
3507   return Node::New();
3508 }
3509
3510 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3511 {
3512   bool done = false;
3513   Actor* actor = dynamic_cast< Actor* >( object );
3514
3515   if( actor )
3516   {
3517     if( 0 == actionName.compare( ACTION_SHOW ) )
3518     {
3519       actor->SetVisible( true );
3520       done = true;
3521     }
3522     else if( 0 == actionName.compare( ACTION_HIDE ) )
3523     {
3524       actor->SetVisible( false );
3525       done = true;
3526     }
3527   }
3528
3529   return done;
3530 }
3531
3532 void Actor::EnsureRelayoutData()
3533 {
3534   // Assign relayout data.
3535   if( !mRelayoutData )
3536   {
3537     mRelayoutData = new RelayoutData();
3538   }
3539 }
3540
3541 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3542 {
3543   // Check if actor is dependent on parent
3544   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3545   {
3546     if( ( dimension & ( 1 << i ) ) )
3547     {
3548       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3549       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3550       {
3551         return true;
3552       }
3553     }
3554   }
3555
3556   return false;
3557 }
3558
3559 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3560 {
3561   // Check if actor is dependent on children
3562   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3563   {
3564     if( ( dimension & ( 1 << i ) ) )
3565     {
3566       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3567       switch( resizePolicy )
3568       {
3569         case ResizePolicy::FIT_TO_CHILDREN:
3570         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3571         {
3572           return true;
3573         }
3574
3575         default:
3576         {
3577           break;
3578         }
3579       }
3580     }
3581   }
3582
3583   return false;
3584 }
3585
3586 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3587 {
3588   return Actor::RelayoutDependentOnChildren( dimension );
3589 }
3590
3591 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3592 {
3593   // Check each possible dimension and see if it is dependent on the input one
3594   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3595   {
3596     if( dimension & ( 1 << i ) )
3597     {
3598       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3599     }
3600   }
3601
3602   return false;
3603 }
3604
3605 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3606 {
3607   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3608   {
3609     if( dimension & ( 1 << i ) )
3610     {
3611       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3612     }
3613   }
3614 }
3615
3616 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3617 {
3618   // If more than one dimension is requested, just return the first one found
3619   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3620   {
3621     if( ( dimension & ( 1 << i ) ) )
3622     {
3623       return mRelayoutData->negotiatedDimensions[ i ];
3624     }
3625   }
3626
3627   return 0.0f;   // Default
3628 }
3629
3630 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3631 {
3632   EnsureRelayoutData();
3633
3634   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3635   {
3636     if( dimension & ( 1 << i ) )
3637     {
3638       mRelayoutData->dimensionPadding[ i ] = padding;
3639     }
3640   }
3641 }
3642
3643 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3644 {
3645   if ( mRelayoutData )
3646   {
3647     // If more than one dimension is requested, just return the first one found
3648     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3649     {
3650       if( ( dimension & ( 1 << i ) ) )
3651       {
3652         return mRelayoutData->dimensionPadding[ i ];
3653       }
3654     }
3655   }
3656
3657   return GetDefaultDimensionPadding();
3658 }
3659
3660 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3661 {
3662   EnsureRelayoutData();
3663
3664   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3665   {
3666     if( dimension & ( 1 << i ) )
3667     {
3668       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3669     }
3670   }
3671 }
3672
3673 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3674 {
3675   if ( mRelayoutData )
3676   {
3677     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3678     {
3679       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3680       {
3681         return true;
3682       }
3683     }
3684   }
3685
3686   return false;
3687 }
3688
3689 float Actor::GetHeightForWidthBase( float width )
3690 {
3691   float height = 0.0f;
3692
3693   const Vector3 naturalSize = GetNaturalSize();
3694   if( naturalSize.width > 0.0f )
3695   {
3696     height = naturalSize.height * width / naturalSize.width;
3697   }
3698   else // we treat 0 as 1:1 aspect ratio
3699   {
3700     height = width;
3701   }
3702
3703   return height;
3704 }
3705
3706 float Actor::GetWidthForHeightBase( float height )
3707 {
3708   float width = 0.0f;
3709
3710   const Vector3 naturalSize = GetNaturalSize();
3711   if( naturalSize.height > 0.0f )
3712   {
3713     width = naturalSize.width * height / naturalSize.height;
3714   }
3715   else // we treat 0 as 1:1 aspect ratio
3716   {
3717     width = height;
3718   }
3719
3720   return width;
3721 }
3722
3723 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3724 {
3725   // Fill to parent, taking size mode factor into account
3726   switch( child.GetResizePolicy( dimension ) )
3727   {
3728     case ResizePolicy::FILL_TO_PARENT:
3729     {
3730       return GetLatestSize( dimension );
3731     }
3732
3733     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3734     {
3735       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3736     }
3737
3738     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3739     {
3740       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3741     }
3742
3743     default:
3744     {
3745       return GetLatestSize( dimension );
3746     }
3747   }
3748 }
3749
3750 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3751 {
3752   // Can be overridden in derived class
3753   return CalculateChildSizeBase( child, dimension );
3754 }
3755
3756 float Actor::GetHeightForWidth( float width )
3757 {
3758   // Can be overridden in derived class
3759   return GetHeightForWidthBase( width );
3760 }
3761
3762 float Actor::GetWidthForHeight( float height )
3763 {
3764   // Can be overridden in derived class
3765   return GetWidthForHeightBase( height );
3766 }
3767
3768 float Actor::GetLatestSize( Dimension::Type dimension ) const
3769 {
3770   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3771 }
3772
3773 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3774 {
3775   Vector2 padding = GetPadding( dimension );
3776
3777   return GetLatestSize( dimension ) + padding.x + padding.y;
3778 }
3779
3780 float Actor::NegotiateFromParent( Dimension::Type dimension )
3781 {
3782   Actor* parent = GetParent();
3783   if( parent )
3784   {
3785     Vector2 padding( GetPadding( dimension ) );
3786     Vector2 parentPadding( parent->GetPadding( dimension ) );
3787     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3788   }
3789
3790   return 0.0f;
3791 }
3792
3793 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3794 {
3795   float maxDimensionPoint = 0.0f;
3796
3797   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3798   {
3799     ActorPtr child = GetChildAt( i );
3800
3801     if( !child->RelayoutDependentOnParent( dimension ) )
3802     {
3803       // Calculate the min and max points that the children range across
3804       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3805       float dimensionSize = child->GetRelayoutSize( dimension );
3806       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3807     }
3808   }
3809
3810   return maxDimensionPoint;
3811 }
3812
3813 float Actor::GetSize( Dimension::Type dimension ) const
3814 {
3815   return GetDimensionValue( GetTargetSize(), dimension );
3816 }
3817
3818 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3819 {
3820   return GetDimensionValue( GetNaturalSize(), dimension );
3821 }
3822
3823 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3824 {
3825   switch( GetResizePolicy( dimension ) )
3826   {
3827     case ResizePolicy::USE_NATURAL_SIZE:
3828     {
3829       return GetNaturalSize( dimension );
3830     }
3831
3832     case ResizePolicy::FIXED:
3833     {
3834       return GetDimensionValue( GetPreferredSize(), dimension );
3835     }
3836
3837     case ResizePolicy::USE_ASSIGNED_SIZE:
3838     {
3839       return GetDimensionValue( maximumSize, dimension );
3840     }
3841
3842     case ResizePolicy::FILL_TO_PARENT:
3843     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3844     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3845     {
3846       return NegotiateFromParent( dimension );
3847     }
3848
3849     case ResizePolicy::FIT_TO_CHILDREN:
3850     {
3851       return NegotiateFromChildren( dimension );
3852     }
3853
3854     case ResizePolicy::DIMENSION_DEPENDENCY:
3855     {
3856       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3857
3858       // Custom rules
3859       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3860       {
3861         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3862       }
3863
3864       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3865       {
3866         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3867       }
3868
3869       break;
3870     }
3871
3872     default:
3873     {
3874       break;
3875     }
3876   }
3877
3878   return 0.0f;  // Default
3879 }
3880
3881 float Actor::ClampDimension( float size, Dimension::Type dimension )
3882 {
3883   const float minSize = GetMinimumSize( dimension );
3884   const float maxSize = GetMaximumSize( dimension );
3885
3886   return std::max( minSize, std::min( size, maxSize ) );
3887 }
3888
3889 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3890 {
3891   // Check if it needs to be negotiated
3892   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3893   {
3894     // Check that we havn't gotten into an infinite loop
3895     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3896     bool recursionFound = false;
3897     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3898     {
3899       if( *it == searchActor )
3900       {
3901         recursionFound = true;
3902         break;
3903       }
3904     }
3905
3906     if( !recursionFound )
3907     {
3908       // Record the path that we have taken
3909       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3910
3911       // Dimension dependency check
3912       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3913       {
3914         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3915
3916         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3917         {
3918           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3919         }
3920       }
3921
3922       // Parent dependency check
3923       Actor* parent = GetParent();
3924       if( parent && RelayoutDependentOnParent( dimension ) )
3925       {
3926         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3927       }
3928
3929       // Children dependency check
3930       if( RelayoutDependentOnChildren( dimension ) )
3931       {
3932         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3933         {
3934           ActorPtr child = GetChildAt( i );
3935
3936           // Only relayout child first if it is not dependent on this actor
3937           if( !child->RelayoutDependentOnParent( dimension ) )
3938           {
3939             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3940           }
3941         }
3942       }
3943
3944       // For deriving classes
3945       OnCalculateRelayoutSize( dimension );
3946
3947       // All dependencies checked, calculate the size and set negotiated flag
3948       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3949
3950       SetNegotiatedDimension( newSize, dimension );
3951       SetLayoutNegotiated( true, dimension );
3952
3953       // For deriving classes
3954       OnLayoutNegotiated( newSize, dimension );
3955
3956       // This actor has been successfully processed, pop it off the recursion stack
3957       recursionStack.pop_back();
3958     }
3959     else
3960     {
3961       // TODO: Break infinite loop
3962       SetLayoutNegotiated( true, dimension );
3963     }
3964   }
3965 }
3966
3967 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3968 {
3969   // Negotiate all dimensions that require it
3970   ActorDimensionStack recursionStack;
3971
3972   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3973   {
3974     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3975
3976     // Negotiate
3977     NegotiateDimension( dimension, allocatedSize, recursionStack );
3978   }
3979 }
3980
3981 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3982 {
3983   switch( mRelayoutData->sizeSetPolicy )
3984   {
3985     case SizeScalePolicy::USE_SIZE_SET:
3986     {
3987       return size;
3988     }
3989
3990     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3991     {
3992       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3993       const Vector3 naturalSize = GetNaturalSize();
3994       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3995       {
3996         const float sizeRatio = size.width / size.height;
3997         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3998
3999         if( naturalSizeRatio < sizeRatio )
4000         {
4001           return Vector2( naturalSizeRatio * size.height, size.height );
4002         }
4003         else if( naturalSizeRatio > sizeRatio )
4004         {
4005           return Vector2( size.width, size.width / naturalSizeRatio );
4006         }
4007         else
4008         {
4009           return size;
4010         }
4011       }
4012
4013       break;
4014     }
4015
4016     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4017     {
4018       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4019       const Vector3 naturalSize = GetNaturalSize();
4020       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4021       {
4022         const float sizeRatio = size.width / size.height;
4023         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4024
4025         if( naturalSizeRatio < sizeRatio )
4026         {
4027           return Vector2( size.width, size.width / naturalSizeRatio );
4028         }
4029         else if( naturalSizeRatio > sizeRatio )
4030         {
4031           return Vector2( naturalSizeRatio * size.height, size.height );
4032         }
4033         else
4034         {
4035           return size;
4036         }
4037       }
4038       break;
4039     }
4040
4041     default:
4042     {
4043       break;
4044     }
4045   }
4046
4047   return size;
4048 }
4049
4050 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4051 {
4052   // Do the set actor size
4053   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4054
4055   // Adjust for size set policy
4056   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4057
4058   // Lock the flag to stop recursive relayouts on set size
4059   mRelayoutData->insideRelayout = true;
4060   SetSize( negotiatedSize );
4061   mRelayoutData->insideRelayout = false;
4062
4063   // Clear flags for all dimensions
4064   SetLayoutDirty( false );
4065
4066   // Give deriving classes a chance to respond
4067   OnRelayout( negotiatedSize, container );
4068
4069   if( !mOnRelayoutSignal.Empty() )
4070   {
4071     Dali::Actor handle( this );
4072     mOnRelayoutSignal.Emit( handle );
4073   }
4074 }
4075
4076 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4077 {
4078   // Do the negotiation
4079   NegotiateDimensions( allocatedSize );
4080
4081   // Set the actor size
4082   SetNegotiatedSize( container );
4083
4084   // Negotiate down to children
4085   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4086
4087   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4088   {
4089     ActorPtr child = GetChildAt( i );
4090
4091     // Only relayout if required
4092     if( child->RelayoutRequired() )
4093     {
4094       container.Add( Dali::Actor( child.Get() ), newBounds );
4095     }
4096   }
4097 }
4098
4099 void Actor::RelayoutRequest( Dimension::Type dimension )
4100 {
4101   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4102   if( relayoutController )
4103   {
4104     Dali::Actor self( this );
4105     relayoutController->RequestRelayout( self, dimension );
4106   }
4107 }
4108
4109 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4110 {
4111 }
4112
4113 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4114 {
4115 }
4116
4117 void Actor::SetPreferredSize( const Vector2& size )
4118 {
4119   EnsureRelayoutData();
4120
4121   if( size.width > 0.0f )
4122   {
4123     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4124   }
4125
4126   if( size.height > 0.0f )
4127   {
4128     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4129   }
4130
4131   mRelayoutData->preferredSize = size;
4132
4133   RelayoutRequest();
4134 }
4135
4136 Vector2 Actor::GetPreferredSize() const
4137 {
4138   if ( mRelayoutData )
4139   {
4140     return Vector2( mRelayoutData->preferredSize );
4141   }
4142
4143   return GetDefaultPreferredSize();
4144 }
4145
4146 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4147 {
4148   EnsureRelayoutData();
4149
4150   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4151   {
4152     if( dimension & ( 1 << i ) )
4153     {
4154       mRelayoutData->minimumSize[ i ] = size;
4155     }
4156   }
4157
4158   RelayoutRequest();
4159 }
4160
4161 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4162 {
4163   if ( mRelayoutData )
4164   {
4165     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4166     {
4167       if( dimension & ( 1 << i ) )
4168       {
4169         return mRelayoutData->minimumSize[ i ];
4170       }
4171     }
4172   }
4173
4174   return 0.0f;  // Default
4175 }
4176
4177 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4178 {
4179   EnsureRelayoutData();
4180
4181   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4182   {
4183     if( dimension & ( 1 << i ) )
4184     {
4185       mRelayoutData->maximumSize[ i ] = size;
4186     }
4187   }
4188
4189   RelayoutRequest();
4190 }
4191
4192 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4193 {
4194   if ( mRelayoutData )
4195   {
4196     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4197     {
4198       if( dimension & ( 1 << i ) )
4199       {
4200         return mRelayoutData->maximumSize[ i ];
4201       }
4202     }
4203   }
4204
4205   return FLT_MAX;  // Default
4206 }
4207
4208 } // namespace Internal
4209
4210 } // namespace Dali