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