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