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