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