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