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