(Properties) OnPropertySet is called when any property is set
[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   switch( entry.type )
2934   {
2935     case Property::BOOLEAN:
2936     {
2937       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2938       DALI_ASSERT_DEBUG( NULL != property );
2939
2940       // property is being used in a separate thread; queue a message to set the property
2941       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2942
2943       break;
2944     }
2945
2946     case Property::INTEGER:
2947     {
2948       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2949       DALI_ASSERT_DEBUG( NULL != property );
2950
2951       // property is being used in a separate thread; queue a message to set the property
2952       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2953
2954       break;
2955     }
2956
2957     case Property::UNSIGNED_INTEGER:
2958     {
2959       const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2960       DALI_ASSERT_DEBUG( NULL != property );
2961
2962       // property is being used in a separate thread; queue a message to set the property
2963       SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2964
2965       break;
2966     }
2967
2968     case Property::FLOAT:
2969     {
2970       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2971       DALI_ASSERT_DEBUG( NULL != property );
2972
2973       // property is being used in a separate thread; queue a message to set the property
2974       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2975
2976       break;
2977     }
2978
2979     case Property::VECTOR2:
2980     {
2981       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2982       DALI_ASSERT_DEBUG( NULL != property );
2983
2984       // property is being used in a separate thread; queue a message to set the property
2985       SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2986
2987       break;
2988     }
2989
2990     case Property::VECTOR3:
2991     {
2992       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2993       DALI_ASSERT_DEBUG( NULL != property );
2994
2995       // property is being used in a separate thread; queue a message to set the property
2996       SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2997
2998       break;
2999     }
3000
3001     case Property::VECTOR4:
3002     {
3003       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3004       DALI_ASSERT_DEBUG( NULL != property );
3005
3006       // property is being used in a separate thread; queue a message to set the property
3007       SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3008
3009       break;
3010     }
3011
3012     case Property::ROTATION:
3013     {
3014       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3015       DALI_ASSERT_DEBUG( NULL != property );
3016
3017       // property is being used in a separate thread; queue a message to set the property
3018       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
3019
3020       break;
3021     }
3022
3023     case Property::MATRIX:
3024     {
3025       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3026       DALI_ASSERT_DEBUG( NULL != property );
3027
3028       // property is being used in a separate thread; queue a message to set the property
3029       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
3030
3031       break;
3032     }
3033
3034     case Property::MATRIX3:
3035     {
3036       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3037       DALI_ASSERT_DEBUG( NULL != property );
3038
3039       // property is being used in a separate thread; queue a message to set the property
3040       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
3041
3042       break;
3043     }
3044
3045     default:
3046     {
3047       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3048       break;
3049     }
3050   }
3051 }
3052
3053 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3054 {
3055   Property::Value value;
3056
3057   switch( index )
3058   {
3059     case Dali::Actor::Property::PARENT_ORIGIN:
3060     {
3061       value = GetCurrentParentOrigin();
3062       break;
3063     }
3064
3065     case Dali::Actor::Property::PARENT_ORIGIN_X:
3066     {
3067       value = GetCurrentParentOrigin().x;
3068       break;
3069     }
3070
3071     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3072     {
3073       value = GetCurrentParentOrigin().y;
3074       break;
3075     }
3076
3077     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3078     {
3079       value = GetCurrentParentOrigin().z;
3080       break;
3081     }
3082
3083     case Dali::Actor::Property::ANCHOR_POINT:
3084     {
3085       value = GetCurrentAnchorPoint();
3086       break;
3087     }
3088
3089     case Dali::Actor::Property::ANCHOR_POINT_X:
3090     {
3091       value = GetCurrentAnchorPoint().x;
3092       break;
3093     }
3094
3095     case Dali::Actor::Property::ANCHOR_POINT_Y:
3096     {
3097       value = GetCurrentAnchorPoint().y;
3098       break;
3099     }
3100
3101     case Dali::Actor::Property::ANCHOR_POINT_Z:
3102     {
3103       value = GetCurrentAnchorPoint().z;
3104       break;
3105     }
3106
3107     case Dali::Actor::Property::SIZE:
3108     {
3109       value = GetCurrentSize();
3110       break;
3111     }
3112
3113     case Dali::Actor::Property::SIZE_WIDTH:
3114     {
3115       value = GetCurrentSize().width;
3116       break;
3117     }
3118
3119     case Dali::Actor::Property::SIZE_HEIGHT:
3120     {
3121       value = GetCurrentSize().height;
3122       break;
3123     }
3124
3125     case Dali::Actor::Property::SIZE_DEPTH:
3126     {
3127       value = GetCurrentSize().depth;
3128       break;
3129     }
3130
3131     case Dali::Actor::Property::POSITION:
3132     {
3133       value = GetCurrentPosition();
3134       break;
3135     }
3136
3137     case Dali::Actor::Property::POSITION_X:
3138     {
3139       value = GetCurrentPosition().x;
3140       break;
3141     }
3142
3143     case Dali::Actor::Property::POSITION_Y:
3144     {
3145       value = GetCurrentPosition().y;
3146       break;
3147     }
3148
3149     case Dali::Actor::Property::POSITION_Z:
3150     {
3151       value = GetCurrentPosition().z;
3152       break;
3153     }
3154
3155     case Dali::Actor::Property::WORLD_POSITION:
3156     {
3157       value = GetCurrentWorldPosition();
3158       break;
3159     }
3160
3161     case Dali::Actor::Property::WORLD_POSITION_X:
3162     {
3163       value = GetCurrentWorldPosition().x;
3164       break;
3165     }
3166
3167     case Dali::Actor::Property::WORLD_POSITION_Y:
3168     {
3169       value = GetCurrentWorldPosition().y;
3170       break;
3171     }
3172
3173     case Dali::Actor::Property::WORLD_POSITION_Z:
3174     {
3175       value = GetCurrentWorldPosition().z;
3176       break;
3177     }
3178
3179     case Dali::Actor::Property::ORIENTATION:
3180     {
3181       value = GetCurrentOrientation();
3182       break;
3183     }
3184
3185     case Dali::Actor::Property::WORLD_ORIENTATION:
3186     {
3187       value = GetCurrentWorldOrientation();
3188       break;
3189     }
3190
3191     case Dali::Actor::Property::SCALE:
3192     {
3193       value = GetCurrentScale();
3194       break;
3195     }
3196
3197     case Dali::Actor::Property::SCALE_X:
3198     {
3199       value = GetCurrentScale().x;
3200       break;
3201     }
3202
3203     case Dali::Actor::Property::SCALE_Y:
3204     {
3205       value = GetCurrentScale().y;
3206       break;
3207     }
3208
3209     case Dali::Actor::Property::SCALE_Z:
3210     {
3211       value = GetCurrentScale().z;
3212       break;
3213     }
3214
3215     case Dali::Actor::Property::WORLD_SCALE:
3216     {
3217       value = GetCurrentWorldScale();
3218       break;
3219     }
3220
3221     case Dali::Actor::Property::VISIBLE:
3222     {
3223       value = IsVisible();
3224       break;
3225     }
3226
3227     case Dali::Actor::Property::COLOR:
3228     {
3229       value = GetCurrentColor();
3230       break;
3231     }
3232
3233     case Dali::Actor::Property::COLOR_RED:
3234     {
3235       value = GetCurrentColor().r;
3236       break;
3237     }
3238
3239     case Dali::Actor::Property::COLOR_GREEN:
3240     {
3241       value = GetCurrentColor().g;
3242       break;
3243     }
3244
3245     case Dali::Actor::Property::COLOR_BLUE:
3246     {
3247       value = GetCurrentColor().b;
3248       break;
3249     }
3250
3251     case Dali::Actor::Property::COLOR_ALPHA:
3252     {
3253       value = GetCurrentColor().a;
3254       break;
3255     }
3256
3257     case Dali::Actor::Property::WORLD_COLOR:
3258     {
3259       value = GetCurrentWorldColor();
3260       break;
3261     }
3262
3263     case Dali::Actor::Property::WORLD_MATRIX:
3264     {
3265       value = GetCurrentWorldMatrix();
3266       break;
3267     }
3268
3269     case Dali::Actor::Property::NAME:
3270     {
3271       value = GetName();
3272       break;
3273     }
3274
3275     case Dali::Actor::Property::SENSITIVE:
3276     {
3277       value = IsSensitive();
3278       break;
3279     }
3280
3281     case Dali::Actor::Property::LEAVE_REQUIRED:
3282     {
3283       value = GetLeaveRequired();
3284       break;
3285     }
3286
3287     case Dali::Actor::Property::INHERIT_ORIENTATION:
3288     {
3289       value = IsOrientationInherited();
3290       break;
3291     }
3292
3293     case Dali::Actor::Property::INHERIT_SCALE:
3294     {
3295       value = IsScaleInherited();
3296       break;
3297     }
3298
3299     case Dali::Actor::Property::COLOR_MODE:
3300     {
3301       value = Scripting::GetColorMode( GetColorMode() );
3302       break;
3303     }
3304
3305     case Dali::Actor::Property::POSITION_INHERITANCE:
3306     {
3307       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3308       break;
3309     }
3310
3311     case Dali::Actor::Property::DRAW_MODE:
3312     {
3313       value = Scripting::GetDrawMode( GetDrawMode() );
3314       break;
3315     }
3316
3317     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3318     {
3319       value = GetSizeModeFactor();
3320       break;
3321     }
3322
3323     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3324     {
3325       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3326       break;
3327     }
3328
3329     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3330     {
3331       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3332       break;
3333     }
3334
3335     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3336     {
3337       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3338       break;
3339     }
3340
3341     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3342     {
3343       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3344       break;
3345     }
3346
3347     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3348     {
3349       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3350       break;
3351     }
3352
3353     case Dali::Actor::Property::PADDING:
3354     {
3355       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3356       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3357       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3358       break;
3359     }
3360
3361     case Dali::Actor::Property::MINIMUM_SIZE:
3362     {
3363       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3364       break;
3365     }
3366
3367     case Dali::Actor::Property::MAXIMUM_SIZE:
3368     {
3369       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3370       break;
3371     }
3372
3373     default:
3374     {
3375       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3376       break;
3377     }
3378   }
3379
3380   return value;
3381 }
3382
3383 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3384 {
3385   return mNode;
3386 }
3387
3388 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3389 {
3390   // This method should only return an object connected to the scene-graph
3391   return OnStage() ? mNode : NULL;
3392 }
3393
3394 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3395 {
3396   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3397
3398   const PropertyBase* property( NULL );
3399
3400   // This method should only return a property of an object connected to the scene-graph
3401   if( !OnStage() )
3402   {
3403     return property;
3404   }
3405
3406   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3407   {
3408     AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3409     if( !animatable )
3410     {
3411       const TypeInfo* typeInfo( GetTypeInfo() );
3412       if ( typeInfo )
3413       {
3414         if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3415         {
3416           animatable = FindAnimatableProperty( index );
3417         }
3418       }
3419     }
3420     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3421
3422     property = animatable->GetSceneGraphProperty();
3423   }
3424   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3425   {
3426     CustomPropertyMetadata* custom = FindCustomProperty( index );
3427     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3428
3429     property = custom->GetSceneGraphProperty();
3430   }
3431   else if( NULL != mNode )
3432   {
3433     switch( index )
3434     {
3435       case Dali::Actor::Property::SIZE:
3436         property = &mNode->mSize;
3437         break;
3438
3439       case Dali::Actor::Property::SIZE_WIDTH:
3440         property = &mNode->mSize;
3441         break;
3442
3443       case Dali::Actor::Property::SIZE_HEIGHT:
3444         property = &mNode->mSize;
3445         break;
3446
3447       case Dali::Actor::Property::SIZE_DEPTH:
3448         property = &mNode->mSize;
3449         break;
3450
3451       case Dali::Actor::Property::POSITION:
3452         property = &mNode->mPosition;
3453         break;
3454
3455       case Dali::Actor::Property::POSITION_X:
3456         property = &mNode->mPosition;
3457         break;
3458
3459       case Dali::Actor::Property::POSITION_Y:
3460         property = &mNode->mPosition;
3461         break;
3462
3463       case Dali::Actor::Property::POSITION_Z:
3464         property = &mNode->mPosition;
3465         break;
3466
3467       case Dali::Actor::Property::ORIENTATION:
3468         property = &mNode->mOrientation;
3469         break;
3470
3471       case Dali::Actor::Property::SCALE:
3472         property = &mNode->mScale;
3473         break;
3474
3475       case Dali::Actor::Property::SCALE_X:
3476         property = &mNode->mScale;
3477         break;
3478
3479       case Dali::Actor::Property::SCALE_Y:
3480         property = &mNode->mScale;
3481         break;
3482
3483       case Dali::Actor::Property::SCALE_Z:
3484         property = &mNode->mScale;
3485         break;
3486
3487       case Dali::Actor::Property::VISIBLE:
3488         property = &mNode->mVisible;
3489         break;
3490
3491       case Dali::Actor::Property::COLOR:
3492         property = &mNode->mColor;
3493         break;
3494
3495       case Dali::Actor::Property::COLOR_RED:
3496         property = &mNode->mColor;
3497         break;
3498
3499       case Dali::Actor::Property::COLOR_GREEN:
3500         property = &mNode->mColor;
3501         break;
3502
3503       case Dali::Actor::Property::COLOR_BLUE:
3504         property = &mNode->mColor;
3505         break;
3506
3507       case Dali::Actor::Property::COLOR_ALPHA:
3508         property = &mNode->mColor;
3509         break;
3510
3511       default:
3512         break;
3513     }
3514   }
3515
3516   return property;
3517 }
3518
3519 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3520 {
3521   const PropertyInputImpl* property( NULL );
3522
3523   // This method should only return a property of an object connected to the scene-graph
3524   if( !OnStage() )
3525   {
3526     return property;
3527   }
3528
3529   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3530   {
3531     AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3532     if( !animatable )
3533     {
3534       const TypeInfo* typeInfo( GetTypeInfo() );
3535       if ( typeInfo )
3536       {
3537         if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3538         {
3539           animatable = FindAnimatableProperty( index );
3540         }
3541       }
3542     }
3543     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3544
3545     property = animatable->GetSceneGraphProperty();
3546   }
3547   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3548   {
3549     CustomPropertyMetadata* custom = FindCustomProperty( index );
3550     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3551     property = custom->GetSceneGraphProperty();
3552   }
3553   else if( NULL != mNode )
3554   {
3555     switch( index )
3556     {
3557       case Dali::Actor::Property::PARENT_ORIGIN:
3558         property = &mNode->mParentOrigin;
3559         break;
3560
3561       case Dali::Actor::Property::PARENT_ORIGIN_X:
3562         property = &mNode->mParentOrigin;
3563         break;
3564
3565       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3566         property = &mNode->mParentOrigin;
3567         break;
3568
3569       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3570         property = &mNode->mParentOrigin;
3571         break;
3572
3573       case Dali::Actor::Property::ANCHOR_POINT:
3574         property = &mNode->mAnchorPoint;
3575         break;
3576
3577       case Dali::Actor::Property::ANCHOR_POINT_X:
3578         property = &mNode->mAnchorPoint;
3579         break;
3580
3581       case Dali::Actor::Property::ANCHOR_POINT_Y:
3582         property = &mNode->mAnchorPoint;
3583         break;
3584
3585       case Dali::Actor::Property::ANCHOR_POINT_Z:
3586         property = &mNode->mAnchorPoint;
3587         break;
3588
3589       case Dali::Actor::Property::SIZE:
3590         property = &mNode->mSize;
3591         break;
3592
3593       case Dali::Actor::Property::SIZE_WIDTH:
3594         property = &mNode->mSize;
3595         break;
3596
3597       case Dali::Actor::Property::SIZE_HEIGHT:
3598         property = &mNode->mSize;
3599         break;
3600
3601       case Dali::Actor::Property::SIZE_DEPTH:
3602         property = &mNode->mSize;
3603         break;
3604
3605       case Dali::Actor::Property::POSITION:
3606         property = &mNode->mPosition;
3607         break;
3608
3609       case Dali::Actor::Property::POSITION_X:
3610         property = &mNode->mPosition;
3611         break;
3612
3613       case Dali::Actor::Property::POSITION_Y:
3614         property = &mNode->mPosition;
3615         break;
3616
3617       case Dali::Actor::Property::POSITION_Z:
3618         property = &mNode->mPosition;
3619         break;
3620
3621       case Dali::Actor::Property::WORLD_POSITION:
3622         property = &mNode->mWorldPosition;
3623         break;
3624
3625       case Dali::Actor::Property::WORLD_POSITION_X:
3626         property = &mNode->mWorldPosition;
3627         break;
3628
3629       case Dali::Actor::Property::WORLD_POSITION_Y:
3630         property = &mNode->mWorldPosition;
3631         break;
3632
3633       case Dali::Actor::Property::WORLD_POSITION_Z:
3634         property = &mNode->mWorldPosition;
3635         break;
3636
3637       case Dali::Actor::Property::ORIENTATION:
3638         property = &mNode->mOrientation;
3639         break;
3640
3641       case Dali::Actor::Property::WORLD_ORIENTATION:
3642         property = &mNode->mWorldOrientation;
3643         break;
3644
3645       case Dali::Actor::Property::SCALE:
3646         property = &mNode->mScale;
3647         break;
3648
3649       case Dali::Actor::Property::SCALE_X:
3650         property = &mNode->mScale;
3651         break;
3652
3653       case Dali::Actor::Property::SCALE_Y:
3654         property = &mNode->mScale;
3655         break;
3656
3657       case Dali::Actor::Property::SCALE_Z:
3658         property = &mNode->mScale;
3659         break;
3660
3661       case Dali::Actor::Property::WORLD_SCALE:
3662         property = &mNode->mWorldScale;
3663         break;
3664
3665       case Dali::Actor::Property::VISIBLE:
3666         property = &mNode->mVisible;
3667         break;
3668
3669       case Dali::Actor::Property::COLOR:
3670         property = &mNode->mColor;
3671         break;
3672
3673       case Dali::Actor::Property::COLOR_RED:
3674         property = &mNode->mColor;
3675         break;
3676
3677       case Dali::Actor::Property::COLOR_GREEN:
3678         property = &mNode->mColor;
3679         break;
3680
3681       case Dali::Actor::Property::COLOR_BLUE:
3682         property = &mNode->mColor;
3683         break;
3684
3685       case Dali::Actor::Property::COLOR_ALPHA:
3686         property = &mNode->mColor;
3687         break;
3688
3689       case Dali::Actor::Property::WORLD_COLOR:
3690         property = &mNode->mWorldColor;
3691         break;
3692
3693       case Dali::Actor::Property::WORLD_MATRIX:
3694         property = &mNode->mWorldMatrix;
3695         break;
3696
3697       default:
3698         break;
3699     }
3700   }
3701
3702   return property;
3703 }
3704
3705 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3706 {
3707   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3708
3709   switch( index )
3710   {
3711     case Dali::Actor::Property::PARENT_ORIGIN_X:
3712     case Dali::Actor::Property::ANCHOR_POINT_X:
3713     case Dali::Actor::Property::SIZE_WIDTH:
3714     case Dali::Actor::Property::POSITION_X:
3715     case Dali::Actor::Property::WORLD_POSITION_X:
3716     case Dali::Actor::Property::SCALE_X:
3717     case Dali::Actor::Property::COLOR_RED:
3718     {
3719       componentIndex = 0;
3720       break;
3721     }
3722
3723     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3724     case Dali::Actor::Property::ANCHOR_POINT_Y:
3725     case Dali::Actor::Property::SIZE_HEIGHT:
3726     case Dali::Actor::Property::POSITION_Y:
3727     case Dali::Actor::Property::WORLD_POSITION_Y:
3728     case Dali::Actor::Property::SCALE_Y:
3729     case Dali::Actor::Property::COLOR_GREEN:
3730     {
3731       componentIndex = 1;
3732       break;
3733     }
3734
3735     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3736     case Dali::Actor::Property::ANCHOR_POINT_Z:
3737     case Dali::Actor::Property::SIZE_DEPTH:
3738     case Dali::Actor::Property::POSITION_Z:
3739     case Dali::Actor::Property::WORLD_POSITION_Z:
3740     case Dali::Actor::Property::SCALE_Z:
3741     case Dali::Actor::Property::COLOR_BLUE:
3742     {
3743       componentIndex = 2;
3744       break;
3745     }
3746
3747     case Dali::Actor::Property::COLOR_ALPHA:
3748     {
3749       componentIndex = 3;
3750       break;
3751     }
3752
3753     default:
3754     {
3755       // Do nothing
3756       break;
3757     }
3758   }
3759
3760   return componentIndex;
3761 }
3762
3763 void Actor::SetParent( Actor* parent, int index )
3764 {
3765   if( parent )
3766   {
3767     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3768
3769     mParent = parent;
3770
3771     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3772          parent->OnStage() )
3773     {
3774       // Instruct each actor to create a corresponding node in the scene graph
3775       ConnectToStage( index );
3776     }
3777   }
3778   else // parent being set to NULL
3779   {
3780     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3781
3782     mParent = NULL;
3783
3784     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3785          OnStage() )
3786     {
3787       DALI_ASSERT_ALWAYS( mNode != NULL );
3788
3789       if( NULL != mNode )
3790       {
3791         // Disconnect the Node & its children from the scene-graph.
3792         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3793       }
3794
3795       // Instruct each actor to discard pointers to the scene-graph
3796       DisconnectFromStage();
3797     }
3798   }
3799 }
3800
3801 SceneGraph::Node* Actor::CreateNode() const
3802 {
3803   return Node::New();
3804 }
3805
3806 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3807 {
3808   bool done = false;
3809   Actor* actor = dynamic_cast< Actor* >( object );
3810
3811   if( actor )
3812   {
3813     if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3814     {
3815       actor->SetVisible( true );
3816       done = true;
3817     }
3818     else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3819     {
3820       actor->SetVisible( false );
3821       done = true;
3822     }
3823   }
3824
3825   return done;
3826 }
3827
3828 void Actor::EnsureRelayoutData() const
3829 {
3830   // Assign relayout data.
3831   if( !mRelayoutData )
3832   {
3833     mRelayoutData = new RelayoutData();
3834   }
3835 }
3836
3837 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3838 {
3839   // Check if actor is dependent on parent
3840   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3841   {
3842     if( ( dimension & ( 1 << i ) ) )
3843     {
3844       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3845       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3846       {
3847         return true;
3848       }
3849     }
3850   }
3851
3852   return false;
3853 }
3854
3855 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3856 {
3857   // Check if actor is dependent on children
3858   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3859   {
3860     if( ( dimension & ( 1 << i ) ) )
3861     {
3862       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3863       switch( resizePolicy )
3864       {
3865         case ResizePolicy::FIT_TO_CHILDREN:
3866         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3867         {
3868           return true;
3869         }
3870
3871         default:
3872         {
3873           break;
3874         }
3875       }
3876     }
3877   }
3878
3879   return false;
3880 }
3881
3882 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3883 {
3884   return Actor::RelayoutDependentOnChildren( dimension );
3885 }
3886
3887 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3888 {
3889   // Check each possible dimension and see if it is dependent on the input one
3890   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3891   {
3892     if( dimension & ( 1 << i ) )
3893     {
3894       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3895     }
3896   }
3897
3898   return false;
3899 }
3900
3901 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3902 {
3903   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3904   {
3905     if( dimension & ( 1 << i ) )
3906     {
3907       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3908     }
3909   }
3910 }
3911
3912 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3913 {
3914   // If more than one dimension is requested, just return the first one found
3915   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3916   {
3917     if( ( dimension & ( 1 << i ) ) )
3918     {
3919       return mRelayoutData->negotiatedDimensions[ i ];
3920     }
3921   }
3922
3923   return 0.0f;   // Default
3924 }
3925
3926 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3927 {
3928   EnsureRelayoutData();
3929
3930   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3931   {
3932     if( dimension & ( 1 << i ) )
3933     {
3934       mRelayoutData->dimensionPadding[ i ] = padding;
3935     }
3936   }
3937 }
3938
3939 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3940 {
3941   EnsureRelayoutData();
3942
3943   // If more than one dimension is requested, just return the first one found
3944   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3945   {
3946     if( ( dimension & ( 1 << i ) ) )
3947     {
3948       return mRelayoutData->dimensionPadding[ i ];
3949     }
3950   }
3951
3952   return Vector2( 0.0f, 0.0f );   // Default
3953 }
3954
3955 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3956 {
3957   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3958   {
3959     if( dimension & ( 1 << i ) )
3960     {
3961       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3962     }
3963   }
3964 }
3965
3966 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3967 {
3968   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3969   {
3970     if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3971     {
3972       return true;
3973     }
3974   }
3975
3976   return false;
3977 }
3978
3979 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3980 {
3981   // Could be overridden in derived classes.
3982   return CalculateChildSizeBase( child, dimension );
3983 }
3984
3985 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3986 {
3987   // Fill to parent, taking size mode factor into account
3988   switch( child.GetResizePolicy( dimension ) )
3989   {
3990     case ResizePolicy::FILL_TO_PARENT:
3991     {
3992       return GetLatestSize( dimension );
3993     }
3994
3995     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3996     {
3997       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3998     }
3999
4000     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4001     {
4002       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4003     }
4004
4005     default:
4006     {
4007       return GetLatestSize( dimension );
4008     }
4009   }
4010 }
4011
4012 float Actor::GetHeightForWidth( float width )
4013 {
4014   // Could be overridden in derived classes.
4015   float height = 0.0f;
4016
4017   const Vector3 naturalSize = GetNaturalSize();
4018   if( naturalSize.width > 0.0f )
4019   {
4020     height = naturalSize.height * width / naturalSize.width;
4021   }
4022
4023   return height;
4024 }
4025
4026 float Actor::GetWidthForHeight( float height )
4027 {
4028   // Could be overridden in derived classes.
4029   float width = 0.0f;
4030
4031   const Vector3 naturalSize = GetNaturalSize();
4032   if( naturalSize.height > 0.0f )
4033   {
4034     width = naturalSize.width * height / naturalSize.height;
4035   }
4036
4037   return width;
4038 }
4039
4040 float Actor::GetLatestSize( Dimension::Type dimension ) const
4041 {
4042   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4043 }
4044
4045 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4046 {
4047   Vector2 padding = GetPadding( dimension );
4048
4049   return GetLatestSize( dimension ) + padding.x + padding.y;
4050 }
4051
4052 float Actor::NegotiateFromParent( Dimension::Type dimension )
4053 {
4054   Actor* parent = GetParent();
4055   if( parent )
4056   {
4057     Vector2 padding( GetPadding( dimension ) );
4058     Vector2 parentPadding( parent->GetPadding( dimension ) );
4059     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4060   }
4061
4062   return 0.0f;
4063 }
4064
4065 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4066 {
4067   float maxDimensionPoint = 0.0f;
4068
4069   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4070   {
4071     Dali::Actor child = GetChildAt( i );
4072     Actor& childImpl = GetImplementation( child );
4073
4074     if( !childImpl.RelayoutDependentOnParent( dimension ) )
4075     {
4076       // Calculate the min and max points that the children range across
4077       float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4078       float dimensionSize = childImpl.GetRelayoutSize( dimension );
4079       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4080     }
4081   }
4082
4083   return maxDimensionPoint;
4084 }
4085
4086 float Actor::GetSize( Dimension::Type dimension ) const
4087 {
4088   return GetDimensionValue( GetTargetSize(), dimension );
4089 }
4090
4091 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4092 {
4093   return GetDimensionValue( GetNaturalSize(), dimension );
4094 }
4095
4096 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4097 {
4098   switch( GetResizePolicy( dimension ) )
4099   {
4100     case ResizePolicy::USE_NATURAL_SIZE:
4101     {
4102       return GetNaturalSize( dimension );
4103     }
4104
4105     case ResizePolicy::FIXED:
4106     {
4107       return GetDimensionValue( GetPreferredSize(), dimension );
4108     }
4109
4110     case ResizePolicy::USE_ASSIGNED_SIZE:
4111     {
4112       return GetDimensionValue( maximumSize, dimension );
4113     }
4114
4115     case ResizePolicy::FILL_TO_PARENT:
4116     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4117     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4118     {
4119       return NegotiateFromParent( dimension );
4120     }
4121
4122     case ResizePolicy::FIT_TO_CHILDREN:
4123     {
4124       return NegotiateFromChildren( dimension );
4125     }
4126
4127     case ResizePolicy::DIMENSION_DEPENDENCY:
4128     {
4129       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4130
4131       // Custom rules
4132       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4133       {
4134         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4135       }
4136
4137       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4138       {
4139         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4140       }
4141
4142       break;
4143     }
4144
4145     default:
4146     {
4147       break;
4148     }
4149   }
4150
4151   return 0.0f;  // Default
4152 }
4153
4154 float Actor::ClampDimension( float size, Dimension::Type dimension )
4155 {
4156   const float minSize = GetMinimumSize( dimension );
4157   const float maxSize = GetMaximumSize( dimension );
4158
4159   return std::max( minSize, std::min( size, maxSize ) );
4160 }
4161
4162 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4163 {
4164   // Check if it needs to be negotiated
4165   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4166   {
4167     // Check that we havn't gotten into an infinite loop
4168     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4169     bool recursionFound = false;
4170     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4171     {
4172       if( *it == searchActor )
4173       {
4174         recursionFound = true;
4175         break;
4176       }
4177     }
4178
4179     if( !recursionFound )
4180     {
4181       // Record the path that we have taken
4182       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4183
4184       // Dimension dependency check
4185       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4186       {
4187         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4188
4189         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4190         {
4191           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4192         }
4193       }
4194
4195       // Parent dependency check
4196       Actor* parent = GetParent();
4197       if( parent && RelayoutDependentOnParent( dimension ) )
4198       {
4199         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4200       }
4201
4202       // Children dependency check
4203       if( RelayoutDependentOnChildren( dimension ) )
4204       {
4205         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4206         {
4207           Dali::Actor child = GetChildAt( i );
4208           Actor& childImpl = GetImplementation( child );
4209
4210           // Only relayout child first if it is not dependent on this actor
4211           if( !childImpl.RelayoutDependentOnParent( dimension ) )
4212           {
4213             childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4214           }
4215         }
4216       }
4217
4218       // For deriving classes
4219       OnCalculateRelayoutSize( dimension );
4220
4221       // All dependencies checked, calculate the size and set negotiated flag
4222       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4223
4224       SetNegotiatedDimension( newSize, dimension );
4225       SetLayoutNegotiated( true, dimension );
4226
4227       // For deriving classes
4228       OnLayoutNegotiated( newSize, dimension );
4229
4230       // This actor has been successfully processed, pop it off the recursion stack
4231       recursionStack.pop_back();
4232     }
4233     else
4234     {
4235       // TODO: Break infinite loop
4236       SetLayoutNegotiated( true, dimension );
4237     }
4238   }
4239 }
4240
4241 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4242 {
4243   // Negotiate all dimensions that require it
4244   ActorDimensionStack recursionStack;
4245
4246   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4247   {
4248     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4249
4250     // Negotiate
4251     NegotiateDimension( dimension, allocatedSize, recursionStack );
4252   }
4253 }
4254
4255 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4256 {
4257   switch( mRelayoutData->sizeSetPolicy )
4258   {
4259     case SizeScalePolicy::USE_SIZE_SET:
4260     {
4261       return size;
4262     }
4263
4264     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4265     {
4266       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4267       const Vector3 naturalSize = GetNaturalSize();
4268       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4269       {
4270         const float sizeRatio = size.width / size.height;
4271         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4272
4273         if( naturalSizeRatio < sizeRatio )
4274         {
4275           return Vector2( naturalSizeRatio * size.height, size.height );
4276         }
4277         else if( naturalSizeRatio > sizeRatio )
4278         {
4279           return Vector2( size.width, size.width / naturalSizeRatio );
4280         }
4281         else
4282         {
4283           return size;
4284         }
4285       }
4286
4287       break;
4288     }
4289
4290     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4291     {
4292       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4293       const Vector3 naturalSize = GetNaturalSize();
4294       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4295       {
4296         const float sizeRatio = size.width / size.height;
4297         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4298
4299         if( naturalSizeRatio < sizeRatio )
4300         {
4301           return Vector2( size.width, size.width / naturalSizeRatio );
4302         }
4303         else if( naturalSizeRatio > sizeRatio )
4304         {
4305           return Vector2( naturalSizeRatio * size.height, size.height );
4306         }
4307         else
4308         {
4309           return size;
4310         }
4311       }
4312     }
4313
4314     default:
4315     {
4316       break;
4317     }
4318   }
4319
4320   return size;
4321 }
4322
4323 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4324 {
4325   // Do the set actor size
4326   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4327
4328   // Adjust for size set policy
4329   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4330
4331   // Lock the flag to stop recursive relayouts on set size
4332   mRelayoutData->insideRelayout = true;
4333   SetSize( negotiatedSize );
4334   mRelayoutData->insideRelayout = false;
4335
4336   // Clear flags for all dimensions
4337   SetLayoutDirty( false );
4338
4339   // Give deriving classes a chance to respond
4340   OnRelayout( negotiatedSize, container );
4341
4342   if( !mOnRelayoutSignal.Empty() )
4343   {
4344     Dali::Actor handle( this );
4345     mOnRelayoutSignal.Emit( handle );
4346   }
4347 }
4348
4349 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4350 {
4351   // Do the negotiation
4352   NegotiateDimensions( allocatedSize );
4353
4354   // Set the actor size
4355   SetNegotiatedSize( container );
4356
4357   // Negotiate down to children
4358   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4359
4360   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4361   {
4362     Dali::Actor child = GetChildAt( i );
4363
4364     // Only relayout if required
4365     if( GetImplementation( child ).RelayoutRequired() )
4366     {
4367       container.Add( child, newBounds );
4368     }
4369   }
4370 }
4371
4372 void Actor::RelayoutRequest( Dimension::Type dimension )
4373 {
4374   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4375   if( relayoutController )
4376   {
4377     Dali::Actor self( this );
4378     relayoutController->RequestRelayout( self, dimension );
4379   }
4380 }
4381
4382 void Actor::PropagateRelayoutFlags()
4383 {
4384   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4385   if( relayoutController )
4386   {
4387     Dali::Actor self( this );
4388     relayoutController->PropagateFlags( self );
4389   }
4390 }
4391
4392 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4393 {
4394 }
4395
4396 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4397 {
4398 }
4399
4400 void Actor::SetPreferredSize( const Vector2& size )
4401 {
4402   EnsureRelayoutData();
4403
4404   if( size.width > 0.0f )
4405   {
4406     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4407   }
4408
4409   if( size.height > 0.0f )
4410   {
4411     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4412   }
4413
4414   mRelayoutData->preferredSize = size;
4415
4416   RelayoutRequest();
4417 }
4418
4419 Vector2 Actor::GetPreferredSize() const
4420 {
4421   EnsureRelayoutData();
4422
4423   return mRelayoutData->preferredSize;
4424 }
4425
4426 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4427 {
4428   EnsureRelayoutData();
4429
4430   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4431   {
4432     if( dimension & ( 1 << i ) )
4433     {
4434       mRelayoutData->minimumSize[ i ] = size;
4435     }
4436   }
4437
4438   RelayoutRequest();
4439 }
4440
4441 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4442 {
4443   EnsureRelayoutData();
4444
4445   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4446   {
4447     if( dimension & ( 1 << i ) )
4448     {
4449       return mRelayoutData->minimumSize[ i ];
4450     }
4451   }
4452
4453   return 0.0f;  // Default
4454 }
4455
4456 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4457 {
4458   EnsureRelayoutData();
4459
4460   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4461   {
4462     if( dimension & ( 1 << i ) )
4463     {
4464       mRelayoutData->maximumSize[ i ] = size;
4465     }
4466   }
4467
4468   RelayoutRequest();
4469 }
4470
4471 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4472 {
4473   EnsureRelayoutData();
4474
4475   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4476   {
4477     if( dimension & ( 1 << i ) )
4478     {
4479       return mRelayoutData->maximumSize[ i ];
4480     }
4481   }
4482
4483   return 0.0f;  // Default
4484 }
4485
4486 } // namespace Internal
4487
4488 } // namespace Dali