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