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