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