Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25
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( 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   // This stage is atomic i.e. not interrupted by user callbacks
2387   RecursiveConnectToStage( connectionList, index );
2388
2389   // Notify applications about the newly connected actors.
2390   const ActorIter endIter = connectionList.end();
2391   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2392   {
2393     Actor& actor = GetImplementation( *iter );
2394     actor.NotifyStageConnection();
2395   }
2396
2397   RelayoutRequest();
2398 }
2399
2400 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2401 {
2402   DALI_ASSERT_ALWAYS( !OnStage() );
2403
2404   mIsOnStage = true;
2405
2406   ConnectToSceneGraph( index );
2407
2408   // Notification for internal derived classes
2409   OnStageConnectionInternal();
2410
2411   // This stage is atomic; avoid emitting callbacks until all Actors are connected
2412   connectionList.push_back( Dali::Actor( this ) );
2413
2414   // Recursively connect children
2415   if( mChildren )
2416   {
2417     ActorConstIter endIter = mChildren->end();
2418     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2419     {
2420       Actor& actor = GetImplementation( *iter );
2421       actor.RecursiveConnectToStage( connectionList );
2422     }
2423   }
2424 }
2425
2426 /**
2427  * This method is called when the Actor is connected to the Stage.
2428  * The parent must have added its Node to the scene-graph.
2429  * The child must connect its Node to the parent's Node.
2430  * This is resursive; the child calls ConnectToStage() for its children.
2431  */
2432 void Actor::ConnectToSceneGraph( int index )
2433 {
2434   DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2435
2436   if( NULL != mNode )
2437   {
2438     // Reparent Node in next Update
2439     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2440   }
2441
2442   // Notify attachment
2443   if( mAttachment )
2444   {
2445     mAttachment->Connect();
2446   }
2447
2448 #ifdef DYNAMICS_SUPPORT
2449   // Notify dynamics
2450   if( NULL != mDynamicsData )
2451   {
2452     ConnectDynamics();
2453   }
2454 #endif
2455
2456   // Request relayout on all actors that are added to the scenegraph
2457   RelayoutRequest();
2458
2459   // Notification for Object::Observers
2460   OnSceneObjectAdd();
2461 }
2462
2463 void Actor::NotifyStageConnection()
2464 {
2465   // Actors can be removed (in a callback), before the on-stage stage is reported.
2466   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2467   if( OnStage() && !mOnStageSignalled )
2468   {
2469     // Notification for external (CustomActor) derived classes
2470     OnStageConnectionExternal();
2471
2472     if( !mOnStageSignal.Empty() )
2473     {
2474       Dali::Actor handle( this );
2475       mOnStageSignal.Emit( handle );
2476     }
2477
2478     // Guard against Remove during callbacks
2479     if( OnStage() )
2480     {
2481       mOnStageSignalled = true; // signal required next time Actor is removed
2482     }
2483   }
2484 }
2485
2486 void Actor::DisconnectFromStage()
2487 {
2488   // This container is used instead of walking the Actor hierachy.
2489   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2490   ActorContainer disconnectionList;
2491
2492   // This stage is atomic i.e. not interrupted by user callbacks
2493   RecursiveDisconnectFromStage( disconnectionList );
2494
2495   // Notify applications about the newly disconnected actors.
2496   const ActorIter endIter = disconnectionList.end();
2497   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2498   {
2499     Actor& actor = GetImplementation( *iter );
2500     actor.NotifyStageDisconnection();
2501   }
2502 }
2503
2504 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2505 {
2506   DALI_ASSERT_ALWAYS( OnStage() );
2507
2508   // Recursively disconnect children
2509   if( mChildren )
2510   {
2511     ActorConstIter endIter = mChildren->end();
2512     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2513     {
2514       Actor& actor = GetImplementation( *iter );
2515       actor.RecursiveDisconnectFromStage( disconnectionList );
2516     }
2517   }
2518
2519   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2520   disconnectionList.push_back( Dali::Actor( this ) );
2521
2522   // Notification for internal derived classes
2523   OnStageDisconnectionInternal();
2524
2525   DisconnectFromSceneGraph();
2526
2527   mIsOnStage = false;
2528 }
2529
2530 /**
2531  * This method is called by an actor or its parent, before a node removal message is sent.
2532  * This is recursive; the child calls DisconnectFromStage() for its children.
2533  */
2534 void Actor::DisconnectFromSceneGraph()
2535 {
2536   // Notification for Object::Observers
2537   OnSceneObjectRemove();
2538
2539   // Notify attachment
2540   if( mAttachment )
2541   {
2542     mAttachment->Disconnect();
2543   }
2544
2545 #ifdef DYNAMICS_SUPPORT
2546   // Notify dynamics
2547   if( NULL != mDynamicsData )
2548   {
2549     DisconnectDynamics();
2550   }
2551 #endif
2552 }
2553
2554 void Actor::NotifyStageDisconnection()
2555 {
2556   // Actors can be added (in a callback), before the off-stage state is reported.
2557   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2558   // only do this step if there is a stage, i.e. Core is not being shut down
2559   if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2560   {
2561     // Notification for external (CustomeActor) derived classes
2562     OnStageDisconnectionExternal();
2563
2564     if( !mOffStageSignal.Empty() )
2565     {
2566       Dali::Actor handle( this );
2567       mOffStageSignal.Emit( handle );
2568     }
2569
2570     // Guard against Add during callbacks
2571     if( !OnStage() )
2572     {
2573       mOnStageSignalled = false; // signal required next time Actor is added
2574     }
2575   }
2576 }
2577
2578 bool Actor::IsNodeConnected() const
2579 {
2580   bool connected( false );
2581
2582   if( OnStage() &&
2583   NULL != mNode )
2584   {
2585     if( mNode->IsRoot() || mNode->GetParent() )
2586     {
2587       connected = true;
2588     }
2589   }
2590
2591   return connected;
2592 }
2593
2594 unsigned int Actor::GetDefaultPropertyCount() const
2595 {
2596   return DEFAULT_PROPERTY_COUNT;
2597 }
2598
2599 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2600 {
2601   indices.Reserve( DEFAULT_PROPERTY_COUNT );
2602
2603   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2604   {
2605     indices.PushBack( i );
2606   }
2607 }
2608
2609 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2610 {
2611   if( index < DEFAULT_PROPERTY_COUNT )
2612   {
2613     return DEFAULT_PROPERTY_DETAILS[ index ].name;
2614   }
2615
2616   return NULL;
2617 }
2618
2619 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2620 {
2621   Property::Index index = Property::INVALID_INDEX;
2622
2623   // Look for name in default properties
2624   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2625   {
2626     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2627     if( 0 == name.compare( property->name ) )
2628     {
2629       index = i;
2630       break;
2631     }
2632   }
2633
2634   return index;
2635 }
2636
2637 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2638 {
2639   if( index < DEFAULT_PROPERTY_COUNT )
2640   {
2641     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2642   }
2643
2644   return false;
2645 }
2646
2647 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2648 {
2649   if( index < DEFAULT_PROPERTY_COUNT )
2650   {
2651     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2652   }
2653
2654   return false;
2655 }
2656
2657 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2658 {
2659   if( index < DEFAULT_PROPERTY_COUNT )
2660   {
2661     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2662   }
2663
2664   return false;
2665 }
2666
2667 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2668 {
2669   if( index < DEFAULT_PROPERTY_COUNT )
2670   {
2671     return DEFAULT_PROPERTY_DETAILS[ index ].type;
2672   }
2673
2674   // index out of range...return Property::NONE
2675   return Property::NONE;
2676 }
2677
2678 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2679 {
2680   switch( index )
2681   {
2682     case Dali::Actor::Property::PARENT_ORIGIN:
2683     {
2684       SetParentOrigin( property.Get< Vector3 >() );
2685       break;
2686     }
2687
2688     case Dali::Actor::Property::PARENT_ORIGIN_X:
2689     {
2690       SetParentOriginX( property.Get< float >() );
2691       break;
2692     }
2693
2694     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2695     {
2696       SetParentOriginY( property.Get< float >() );
2697       break;
2698     }
2699
2700     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2701     {
2702       SetParentOriginZ( property.Get< float >() );
2703       break;
2704     }
2705
2706     case Dali::Actor::Property::ANCHOR_POINT:
2707     {
2708       SetAnchorPoint( property.Get< Vector3 >() );
2709       break;
2710     }
2711
2712     case Dali::Actor::Property::ANCHOR_POINT_X:
2713     {
2714       SetAnchorPointX( property.Get< float >() );
2715       break;
2716     }
2717
2718     case Dali::Actor::Property::ANCHOR_POINT_Y:
2719     {
2720       SetAnchorPointY( property.Get< float >() );
2721       break;
2722     }
2723
2724     case Dali::Actor::Property::ANCHOR_POINT_Z:
2725     {
2726       SetAnchorPointZ( property.Get< float >() );
2727       break;
2728     }
2729
2730     case Dali::Actor::Property::SIZE:
2731     {
2732       SetSize( property.Get< Vector3 >() );
2733       break;
2734     }
2735
2736     case Dali::Actor::Property::SIZE_WIDTH:
2737     {
2738       SetWidth( property.Get< float >() );
2739       break;
2740     }
2741
2742     case Dali::Actor::Property::SIZE_HEIGHT:
2743     {
2744       SetHeight( property.Get< float >() );
2745       break;
2746     }
2747
2748     case Dali::Actor::Property::SIZE_DEPTH:
2749     {
2750       SetDepth( property.Get< float >() );
2751       break;
2752     }
2753
2754     case Dali::Actor::Property::POSITION:
2755     {
2756       SetPosition( property.Get< Vector3 >() );
2757       break;
2758     }
2759
2760     case Dali::Actor::Property::POSITION_X:
2761     {
2762       SetX( property.Get< float >() );
2763       break;
2764     }
2765
2766     case Dali::Actor::Property::POSITION_Y:
2767     {
2768       SetY( property.Get< float >() );
2769       break;
2770     }
2771
2772     case Dali::Actor::Property::POSITION_Z:
2773     {
2774       SetZ( property.Get< float >() );
2775       break;
2776     }
2777
2778     case Dali::Actor::Property::ORIENTATION:
2779     {
2780       SetOrientation( property.Get< Quaternion >() );
2781       break;
2782     }
2783
2784     case Dali::Actor::Property::SCALE:
2785     {
2786       SetScale( property.Get< Vector3 >() );
2787       break;
2788     }
2789
2790     case Dali::Actor::Property::SCALE_X:
2791     {
2792       SetScaleX( property.Get< float >() );
2793       break;
2794     }
2795
2796     case Dali::Actor::Property::SCALE_Y:
2797     {
2798       SetScaleY( property.Get< float >() );
2799       break;
2800     }
2801
2802     case Dali::Actor::Property::SCALE_Z:
2803     {
2804       SetScaleZ( property.Get< float >() );
2805       break;
2806     }
2807
2808     case Dali::Actor::Property::VISIBLE:
2809     {
2810       SetVisible( property.Get< bool >() );
2811       break;
2812     }
2813
2814     case Dali::Actor::Property::COLOR:
2815     {
2816       SetColor( property.Get< Vector4 >() );
2817       break;
2818     }
2819
2820     case Dali::Actor::Property::COLOR_RED:
2821     {
2822       SetColorRed( property.Get< float >() );
2823       break;
2824     }
2825
2826     case Dali::Actor::Property::COLOR_GREEN:
2827     {
2828       SetColorGreen( property.Get< float >() );
2829       break;
2830     }
2831
2832     case Dali::Actor::Property::COLOR_BLUE:
2833     {
2834       SetColorBlue( property.Get< float >() );
2835       break;
2836     }
2837
2838     case Dali::Actor::Property::COLOR_ALPHA:
2839     {
2840       SetOpacity( property.Get< float >() );
2841       break;
2842     }
2843
2844     case Dali::Actor::Property::NAME:
2845     {
2846       SetName( property.Get< std::string >() );
2847       break;
2848     }
2849
2850     case Dali::Actor::Property::SENSITIVE:
2851     {
2852       SetSensitive( property.Get< bool >() );
2853       break;
2854     }
2855
2856     case Dali::Actor::Property::LEAVE_REQUIRED:
2857     {
2858       SetLeaveRequired( property.Get< bool >() );
2859       break;
2860     }
2861
2862     case Dali::Actor::Property::INHERIT_ORIENTATION:
2863     {
2864       SetInheritOrientation( property.Get< bool >() );
2865       break;
2866     }
2867
2868     case Dali::Actor::Property::INHERIT_SCALE:
2869     {
2870       SetInheritScale( property.Get< bool >() );
2871       break;
2872     }
2873
2874     case Dali::Actor::Property::COLOR_MODE:
2875     {
2876       SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2877       break;
2878     }
2879
2880     case Dali::Actor::Property::POSITION_INHERITANCE:
2881     {
2882       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2883       break;
2884     }
2885
2886     case Dali::Actor::Property::DRAW_MODE:
2887     {
2888       SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2889       break;
2890     }
2891
2892     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2893     {
2894       SetSizeModeFactor( property.Get< Vector3 >() );
2895       break;
2896     }
2897
2898     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2899     {
2900       SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2901       break;
2902     }
2903
2904     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2905     {
2906       SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2907       break;
2908     }
2909
2910     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2911     {
2912       SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2913       break;
2914     }
2915
2916     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2917     {
2918       if( property.Get< bool >() )
2919       {
2920         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2921       }
2922       break;
2923     }
2924
2925     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2926     {
2927       if( property.Get< bool >() )
2928       {
2929         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2930       }
2931       break;
2932     }
2933
2934     case Dali::Actor::Property::PADDING:
2935     {
2936       Vector4 padding = property.Get< Vector4 >();
2937       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2938       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2939       break;
2940     }
2941
2942     case Dali::Actor::Property::MINIMUM_SIZE:
2943     {
2944       Vector2 size = property.Get< Vector2 >();
2945       SetMinimumSize( size.x, Dimension::WIDTH );
2946       SetMinimumSize( size.y, Dimension::HEIGHT );
2947       break;
2948     }
2949
2950     case Dali::Actor::Property::MAXIMUM_SIZE:
2951     {
2952       Vector2 size = property.Get< Vector2 >();
2953       SetMaximumSize( size.x, Dimension::WIDTH );
2954       SetMaximumSize( size.y, Dimension::HEIGHT );
2955       break;
2956     }
2957
2958     default:
2959     {
2960       // this can happen in the case of a non-animatable default property so just do nothing
2961       break;
2962     }
2963   }
2964 }
2965
2966 // TODO: This method needs to be removed
2967 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2968 {
2969   switch( entry.type )
2970   {
2971     case Property::BOOLEAN:
2972     {
2973       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2974       DALI_ASSERT_DEBUG( NULL != property );
2975
2976       // property is being used in a separate thread; queue a message to set the property
2977       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2978
2979       break;
2980     }
2981
2982     case Property::INTEGER:
2983     {
2984       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2985       DALI_ASSERT_DEBUG( NULL != property );
2986
2987       // property is being used in a separate thread; queue a message to set the property
2988       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2989
2990       break;
2991     }
2992
2993     case Property::UNSIGNED_INTEGER:
2994     {
2995       const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2996       DALI_ASSERT_DEBUG( NULL != property );
2997
2998       // property is being used in a separate thread; queue a message to set the property
2999       SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3000
3001       break;
3002     }
3003
3004     case Property::FLOAT:
3005     {
3006       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3007       DALI_ASSERT_DEBUG( NULL != property );
3008
3009       // property is being used in a separate thread; queue a message to set the property
3010       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3011
3012       break;
3013     }
3014
3015     case Property::VECTOR2:
3016     {
3017       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3018       DALI_ASSERT_DEBUG( NULL != property );
3019
3020       // property is being used in a separate thread; queue a message to set the property
3021       if(entry.componentIndex == 0)
3022       {
3023         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3024       }
3025       else if(entry.componentIndex == 1)
3026       {
3027         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3028       }
3029       else
3030       {
3031         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3032       }
3033
3034       break;
3035     }
3036
3037     case Property::VECTOR3:
3038     {
3039       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3040       DALI_ASSERT_DEBUG( NULL != property );
3041
3042       // property is being used in a separate thread; queue a message to set the property
3043       if(entry.componentIndex == 0)
3044       {
3045         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3046       }
3047       else if(entry.componentIndex == 1)
3048       {
3049         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3050       }
3051       else if(entry.componentIndex == 2)
3052       {
3053         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3054       }
3055       else
3056       {
3057         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3058       }
3059
3060       break;
3061     }
3062
3063     case Property::VECTOR4:
3064     {
3065       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3066       DALI_ASSERT_DEBUG( NULL != property );
3067
3068       // property is being used in a separate thread; queue a message to set the property
3069       if(entry.componentIndex == 0)
3070       {
3071         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3072       }
3073       else if(entry.componentIndex == 1)
3074       {
3075         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3076       }
3077       else if(entry.componentIndex == 2)
3078       {
3079         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3080       }
3081       else if(entry.componentIndex == 3)
3082       {
3083         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3084       }
3085       else
3086       {
3087         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3088       }
3089
3090       break;
3091     }
3092
3093     case Property::ROTATION:
3094     {
3095       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3096       DALI_ASSERT_DEBUG( NULL != property );
3097
3098       // property is being used in a separate thread; queue a message to set the property
3099       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
3100
3101       break;
3102     }
3103
3104     case Property::MATRIX:
3105     {
3106       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3107       DALI_ASSERT_DEBUG( NULL != property );
3108
3109       // property is being used in a separate thread; queue a message to set the property
3110       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
3111
3112       break;
3113     }
3114
3115     case Property::MATRIX3:
3116     {
3117       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3118       DALI_ASSERT_DEBUG( NULL != property );
3119
3120       // property is being used in a separate thread; queue a message to set the property
3121       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
3122
3123       break;
3124     }
3125
3126     default:
3127     {
3128       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3129       break;
3130     }
3131   }
3132 }
3133
3134 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3135 {
3136   Property::Value value;
3137
3138   switch( index )
3139   {
3140     case Dali::Actor::Property::PARENT_ORIGIN:
3141     {
3142       value = GetCurrentParentOrigin();
3143       break;
3144     }
3145
3146     case Dali::Actor::Property::PARENT_ORIGIN_X:
3147     {
3148       value = GetCurrentParentOrigin().x;
3149       break;
3150     }
3151
3152     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3153     {
3154       value = GetCurrentParentOrigin().y;
3155       break;
3156     }
3157
3158     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3159     {
3160       value = GetCurrentParentOrigin().z;
3161       break;
3162     }
3163
3164     case Dali::Actor::Property::ANCHOR_POINT:
3165     {
3166       value = GetCurrentAnchorPoint();
3167       break;
3168     }
3169
3170     case Dali::Actor::Property::ANCHOR_POINT_X:
3171     {
3172       value = GetCurrentAnchorPoint().x;
3173       break;
3174     }
3175
3176     case Dali::Actor::Property::ANCHOR_POINT_Y:
3177     {
3178       value = GetCurrentAnchorPoint().y;
3179       break;
3180     }
3181
3182     case Dali::Actor::Property::ANCHOR_POINT_Z:
3183     {
3184       value = GetCurrentAnchorPoint().z;
3185       break;
3186     }
3187
3188     case Dali::Actor::Property::SIZE:
3189     {
3190       value = GetCurrentSize();
3191       break;
3192     }
3193
3194     case Dali::Actor::Property::SIZE_WIDTH:
3195     {
3196       value = GetCurrentSize().width;
3197       break;
3198     }
3199
3200     case Dali::Actor::Property::SIZE_HEIGHT:
3201     {
3202       value = GetCurrentSize().height;
3203       break;
3204     }
3205
3206     case Dali::Actor::Property::SIZE_DEPTH:
3207     {
3208       value = GetCurrentSize().depth;
3209       break;
3210     }
3211
3212     case Dali::Actor::Property::POSITION:
3213     {
3214       value = GetCurrentPosition();
3215       break;
3216     }
3217
3218     case Dali::Actor::Property::POSITION_X:
3219     {
3220       value = GetCurrentPosition().x;
3221       break;
3222     }
3223
3224     case Dali::Actor::Property::POSITION_Y:
3225     {
3226       value = GetCurrentPosition().y;
3227       break;
3228     }
3229
3230     case Dali::Actor::Property::POSITION_Z:
3231     {
3232       value = GetCurrentPosition().z;
3233       break;
3234     }
3235
3236     case Dali::Actor::Property::WORLD_POSITION:
3237     {
3238       value = GetCurrentWorldPosition();
3239       break;
3240     }
3241
3242     case Dali::Actor::Property::WORLD_POSITION_X:
3243     {
3244       value = GetCurrentWorldPosition().x;
3245       break;
3246     }
3247
3248     case Dali::Actor::Property::WORLD_POSITION_Y:
3249     {
3250       value = GetCurrentWorldPosition().y;
3251       break;
3252     }
3253
3254     case Dali::Actor::Property::WORLD_POSITION_Z:
3255     {
3256       value = GetCurrentWorldPosition().z;
3257       break;
3258     }
3259
3260     case Dali::Actor::Property::ORIENTATION:
3261     {
3262       value = GetCurrentOrientation();
3263       break;
3264     }
3265
3266     case Dali::Actor::Property::WORLD_ORIENTATION:
3267     {
3268       value = GetCurrentWorldOrientation();
3269       break;
3270     }
3271
3272     case Dali::Actor::Property::SCALE:
3273     {
3274       value = GetCurrentScale();
3275       break;
3276     }
3277
3278     case Dali::Actor::Property::SCALE_X:
3279     {
3280       value = GetCurrentScale().x;
3281       break;
3282     }
3283
3284     case Dali::Actor::Property::SCALE_Y:
3285     {
3286       value = GetCurrentScale().y;
3287       break;
3288     }
3289
3290     case Dali::Actor::Property::SCALE_Z:
3291     {
3292       value = GetCurrentScale().z;
3293       break;
3294     }
3295
3296     case Dali::Actor::Property::WORLD_SCALE:
3297     {
3298       value = GetCurrentWorldScale();
3299       break;
3300     }
3301
3302     case Dali::Actor::Property::VISIBLE:
3303     {
3304       value = IsVisible();
3305       break;
3306     }
3307
3308     case Dali::Actor::Property::COLOR:
3309     {
3310       value = GetCurrentColor();
3311       break;
3312     }
3313
3314     case Dali::Actor::Property::COLOR_RED:
3315     {
3316       value = GetCurrentColor().r;
3317       break;
3318     }
3319
3320     case Dali::Actor::Property::COLOR_GREEN:
3321     {
3322       value = GetCurrentColor().g;
3323       break;
3324     }
3325
3326     case Dali::Actor::Property::COLOR_BLUE:
3327     {
3328       value = GetCurrentColor().b;
3329       break;
3330     }
3331
3332     case Dali::Actor::Property::COLOR_ALPHA:
3333     {
3334       value = GetCurrentColor().a;
3335       break;
3336     }
3337
3338     case Dali::Actor::Property::WORLD_COLOR:
3339     {
3340       value = GetCurrentWorldColor();
3341       break;
3342     }
3343
3344     case Dali::Actor::Property::WORLD_MATRIX:
3345     {
3346       value = GetCurrentWorldMatrix();
3347       break;
3348     }
3349
3350     case Dali::Actor::Property::NAME:
3351     {
3352       value = GetName();
3353       break;
3354     }
3355
3356     case Dali::Actor::Property::SENSITIVE:
3357     {
3358       value = IsSensitive();
3359       break;
3360     }
3361
3362     case Dali::Actor::Property::LEAVE_REQUIRED:
3363     {
3364       value = GetLeaveRequired();
3365       break;
3366     }
3367
3368     case Dali::Actor::Property::INHERIT_ORIENTATION:
3369     {
3370       value = IsOrientationInherited();
3371       break;
3372     }
3373
3374     case Dali::Actor::Property::INHERIT_SCALE:
3375     {
3376       value = IsScaleInherited();
3377       break;
3378     }
3379
3380     case Dali::Actor::Property::COLOR_MODE:
3381     {
3382       value = Scripting::GetColorMode( GetColorMode() );
3383       break;
3384     }
3385
3386     case Dali::Actor::Property::POSITION_INHERITANCE:
3387     {
3388       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3389       break;
3390     }
3391
3392     case Dali::Actor::Property::DRAW_MODE:
3393     {
3394       value = Scripting::GetDrawMode( GetDrawMode() );
3395       break;
3396     }
3397
3398     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3399     {
3400       value = GetSizeModeFactor();
3401       break;
3402     }
3403
3404     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3405     {
3406       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3407       break;
3408     }
3409
3410     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3411     {
3412       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3413       break;
3414     }
3415
3416     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3417     {
3418       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3419       break;
3420     }
3421
3422     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3423     {
3424       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3425       break;
3426     }
3427
3428     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3429     {
3430       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3431       break;
3432     }
3433
3434     case Dali::Actor::Property::PADDING:
3435     {
3436       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3437       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3438       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3439       break;
3440     }
3441
3442     case Dali::Actor::Property::MINIMUM_SIZE:
3443     {
3444       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3445       break;
3446     }
3447
3448     case Dali::Actor::Property::MAXIMUM_SIZE:
3449     {
3450       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3451       break;
3452     }
3453
3454     default:
3455     {
3456       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3457       break;
3458     }
3459   }
3460
3461   return value;
3462 }
3463
3464 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3465 {
3466   return mNode;
3467 }
3468
3469 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3470 {
3471   // This method should only return an object connected to the scene-graph
3472   return OnStage() ? mNode : NULL;
3473 }
3474
3475 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3476 {
3477   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3478
3479   const PropertyBase* property( NULL );
3480
3481   // This method should only return a property of an object connected to the scene-graph
3482   if( !OnStage() )
3483   {
3484     return property;
3485   }
3486
3487   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3488   {
3489     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3490     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3491
3492     property = animatable->GetSceneGraphProperty();
3493   }
3494   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3495   {
3496     CustomPropertyMetadata* custom = FindCustomProperty( index );
3497     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3498
3499     property = custom->GetSceneGraphProperty();
3500   }
3501   else if( NULL != mNode )
3502   {
3503     switch( index )
3504     {
3505       case Dali::Actor::Property::SIZE:
3506         property = &mNode->mSize;
3507         break;
3508
3509       case Dali::Actor::Property::SIZE_WIDTH:
3510         property = &mNode->mSize;
3511         break;
3512
3513       case Dali::Actor::Property::SIZE_HEIGHT:
3514         property = &mNode->mSize;
3515         break;
3516
3517       case Dali::Actor::Property::SIZE_DEPTH:
3518         property = &mNode->mSize;
3519         break;
3520
3521       case Dali::Actor::Property::POSITION:
3522         property = &mNode->mPosition;
3523         break;
3524
3525       case Dali::Actor::Property::POSITION_X:
3526         property = &mNode->mPosition;
3527         break;
3528
3529       case Dali::Actor::Property::POSITION_Y:
3530         property = &mNode->mPosition;
3531         break;
3532
3533       case Dali::Actor::Property::POSITION_Z:
3534         property = &mNode->mPosition;
3535         break;
3536
3537       case Dali::Actor::Property::ORIENTATION:
3538         property = &mNode->mOrientation;
3539         break;
3540
3541       case Dali::Actor::Property::SCALE:
3542         property = &mNode->mScale;
3543         break;
3544
3545       case Dali::Actor::Property::SCALE_X:
3546         property = &mNode->mScale;
3547         break;
3548
3549       case Dali::Actor::Property::SCALE_Y:
3550         property = &mNode->mScale;
3551         break;
3552
3553       case Dali::Actor::Property::SCALE_Z:
3554         property = &mNode->mScale;
3555         break;
3556
3557       case Dali::Actor::Property::VISIBLE:
3558         property = &mNode->mVisible;
3559         break;
3560
3561       case Dali::Actor::Property::COLOR:
3562         property = &mNode->mColor;
3563         break;
3564
3565       case Dali::Actor::Property::COLOR_RED:
3566         property = &mNode->mColor;
3567         break;
3568
3569       case Dali::Actor::Property::COLOR_GREEN:
3570         property = &mNode->mColor;
3571         break;
3572
3573       case Dali::Actor::Property::COLOR_BLUE:
3574         property = &mNode->mColor;
3575         break;
3576
3577       case Dali::Actor::Property::COLOR_ALPHA:
3578         property = &mNode->mColor;
3579         break;
3580
3581       default:
3582         break;
3583     }
3584   }
3585
3586   return property;
3587 }
3588
3589 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3590 {
3591   const PropertyInputImpl* property( NULL );
3592
3593   // This method should only return a property of an object connected to the scene-graph
3594   if( !OnStage() )
3595   {
3596     return property;
3597   }
3598
3599   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3600   {
3601     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3602     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3603
3604     property = animatable->GetSceneGraphProperty();
3605   }
3606   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3607   {
3608     CustomPropertyMetadata* custom = FindCustomProperty( index );
3609     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3610     property = custom->GetSceneGraphProperty();
3611   }
3612   else if( NULL != mNode )
3613   {
3614     switch( index )
3615     {
3616       case Dali::Actor::Property::PARENT_ORIGIN:
3617         property = &mNode->mParentOrigin;
3618         break;
3619
3620       case Dali::Actor::Property::PARENT_ORIGIN_X:
3621         property = &mNode->mParentOrigin;
3622         break;
3623
3624       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3625         property = &mNode->mParentOrigin;
3626         break;
3627
3628       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3629         property = &mNode->mParentOrigin;
3630         break;
3631
3632       case Dali::Actor::Property::ANCHOR_POINT:
3633         property = &mNode->mAnchorPoint;
3634         break;
3635
3636       case Dali::Actor::Property::ANCHOR_POINT_X:
3637         property = &mNode->mAnchorPoint;
3638         break;
3639
3640       case Dali::Actor::Property::ANCHOR_POINT_Y:
3641         property = &mNode->mAnchorPoint;
3642         break;
3643
3644       case Dali::Actor::Property::ANCHOR_POINT_Z:
3645         property = &mNode->mAnchorPoint;
3646         break;
3647
3648       case Dali::Actor::Property::SIZE:
3649         property = &mNode->mSize;
3650         break;
3651
3652       case Dali::Actor::Property::SIZE_WIDTH:
3653         property = &mNode->mSize;
3654         break;
3655
3656       case Dali::Actor::Property::SIZE_HEIGHT:
3657         property = &mNode->mSize;
3658         break;
3659
3660       case Dali::Actor::Property::SIZE_DEPTH:
3661         property = &mNode->mSize;
3662         break;
3663
3664       case Dali::Actor::Property::POSITION:
3665         property = &mNode->mPosition;
3666         break;
3667
3668       case Dali::Actor::Property::POSITION_X:
3669         property = &mNode->mPosition;
3670         break;
3671
3672       case Dali::Actor::Property::POSITION_Y:
3673         property = &mNode->mPosition;
3674         break;
3675
3676       case Dali::Actor::Property::POSITION_Z:
3677         property = &mNode->mPosition;
3678         break;
3679
3680       case Dali::Actor::Property::WORLD_POSITION:
3681         property = &mNode->mWorldPosition;
3682         break;
3683
3684       case Dali::Actor::Property::WORLD_POSITION_X:
3685         property = &mNode->mWorldPosition;
3686         break;
3687
3688       case Dali::Actor::Property::WORLD_POSITION_Y:
3689         property = &mNode->mWorldPosition;
3690         break;
3691
3692       case Dali::Actor::Property::WORLD_POSITION_Z:
3693         property = &mNode->mWorldPosition;
3694         break;
3695
3696       case Dali::Actor::Property::ORIENTATION:
3697         property = &mNode->mOrientation;
3698         break;
3699
3700       case Dali::Actor::Property::WORLD_ORIENTATION:
3701         property = &mNode->mWorldOrientation;
3702         break;
3703
3704       case Dali::Actor::Property::SCALE:
3705         property = &mNode->mScale;
3706         break;
3707
3708       case Dali::Actor::Property::SCALE_X:
3709         property = &mNode->mScale;
3710         break;
3711
3712       case Dali::Actor::Property::SCALE_Y:
3713         property = &mNode->mScale;
3714         break;
3715
3716       case Dali::Actor::Property::SCALE_Z:
3717         property = &mNode->mScale;
3718         break;
3719
3720       case Dali::Actor::Property::WORLD_SCALE:
3721         property = &mNode->mWorldScale;
3722         break;
3723
3724       case Dali::Actor::Property::VISIBLE:
3725         property = &mNode->mVisible;
3726         break;
3727
3728       case Dali::Actor::Property::COLOR:
3729         property = &mNode->mColor;
3730         break;
3731
3732       case Dali::Actor::Property::COLOR_RED:
3733         property = &mNode->mColor;
3734         break;
3735
3736       case Dali::Actor::Property::COLOR_GREEN:
3737         property = &mNode->mColor;
3738         break;
3739
3740       case Dali::Actor::Property::COLOR_BLUE:
3741         property = &mNode->mColor;
3742         break;
3743
3744       case Dali::Actor::Property::COLOR_ALPHA:
3745         property = &mNode->mColor;
3746         break;
3747
3748       case Dali::Actor::Property::WORLD_COLOR:
3749         property = &mNode->mWorldColor;
3750         break;
3751
3752       case Dali::Actor::Property::WORLD_MATRIX:
3753         property = &mNode->mWorldMatrix;
3754         break;
3755
3756       default:
3757         break;
3758     }
3759   }
3760
3761   return property;
3762 }
3763
3764 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3765 {
3766   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3767
3768   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3769   {
3770     // check whether the animatable property is registered already, if not then register one.
3771     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3772     if( animatableProperty )
3773     {
3774       componentIndex = animatableProperty->componentIndex;
3775     }
3776   }
3777   else
3778   {
3779     switch( index )
3780     {
3781       case Dali::Actor::Property::PARENT_ORIGIN_X:
3782       case Dali::Actor::Property::ANCHOR_POINT_X:
3783       case Dali::Actor::Property::SIZE_WIDTH:
3784       case Dali::Actor::Property::POSITION_X:
3785       case Dali::Actor::Property::WORLD_POSITION_X:
3786       case Dali::Actor::Property::SCALE_X:
3787       case Dali::Actor::Property::COLOR_RED:
3788       {
3789         componentIndex = 0;
3790         break;
3791       }
3792
3793       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3794       case Dali::Actor::Property::ANCHOR_POINT_Y:
3795       case Dali::Actor::Property::SIZE_HEIGHT:
3796       case Dali::Actor::Property::POSITION_Y:
3797       case Dali::Actor::Property::WORLD_POSITION_Y:
3798       case Dali::Actor::Property::SCALE_Y:
3799       case Dali::Actor::Property::COLOR_GREEN:
3800       {
3801         componentIndex = 1;
3802         break;
3803       }
3804
3805       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3806       case Dali::Actor::Property::ANCHOR_POINT_Z:
3807       case Dali::Actor::Property::SIZE_DEPTH:
3808       case Dali::Actor::Property::POSITION_Z:
3809       case Dali::Actor::Property::WORLD_POSITION_Z:
3810       case Dali::Actor::Property::SCALE_Z:
3811       case Dali::Actor::Property::COLOR_BLUE:
3812       {
3813         componentIndex = 2;
3814         break;
3815       }
3816
3817       case Dali::Actor::Property::COLOR_ALPHA:
3818       {
3819         componentIndex = 3;
3820         break;
3821       }
3822
3823       default:
3824       {
3825         // Do nothing
3826         break;
3827       }
3828     }
3829   }
3830
3831   return componentIndex;
3832 }
3833
3834 void Actor::SetParent( Actor* parent, int index )
3835 {
3836   if( parent )
3837   {
3838     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3839
3840     mParent = parent;
3841
3842     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3843          parent->OnStage() )
3844     {
3845       // Instruct each actor to create a corresponding node in the scene graph
3846       ConnectToStage( index );
3847     }
3848   }
3849   else // parent being set to NULL
3850   {
3851     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3852
3853     mParent = NULL;
3854
3855     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3856          OnStage() )
3857     {
3858       DALI_ASSERT_ALWAYS( mNode != NULL );
3859
3860       if( NULL != mNode )
3861       {
3862         // Disconnect the Node & its children from the scene-graph.
3863         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3864       }
3865
3866       // Instruct each actor to discard pointers to the scene-graph
3867       DisconnectFromStage();
3868     }
3869   }
3870 }
3871
3872 SceneGraph::Node* Actor::CreateNode() const
3873 {
3874   return Node::New();
3875 }
3876
3877 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3878 {
3879   bool done = false;
3880   Actor* actor = dynamic_cast< Actor* >( object );
3881
3882   if( actor )
3883   {
3884     if( 0 == actionName.compare( ACTION_SHOW ) )
3885     {
3886       actor->SetVisible( true );
3887       done = true;
3888     }
3889     else if( 0 == actionName.compare( ACTION_HIDE ) )
3890     {
3891       actor->SetVisible( false );
3892       done = true;
3893     }
3894   }
3895
3896   return done;
3897 }
3898
3899 void Actor::EnsureRelayoutData() const
3900 {
3901   // Assign relayout data.
3902   if( !mRelayoutData )
3903   {
3904     mRelayoutData = new RelayoutData();
3905   }
3906 }
3907
3908 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3909 {
3910   // Check if actor is dependent on parent
3911   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3912   {
3913     if( ( dimension & ( 1 << i ) ) )
3914     {
3915       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3916       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3917       {
3918         return true;
3919       }
3920     }
3921   }
3922
3923   return false;
3924 }
3925
3926 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3927 {
3928   // Check if actor is dependent on children
3929   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3930   {
3931     if( ( dimension & ( 1 << i ) ) )
3932     {
3933       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3934       switch( resizePolicy )
3935       {
3936         case ResizePolicy::FIT_TO_CHILDREN:
3937         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3938         {
3939           return true;
3940         }
3941
3942         default:
3943         {
3944           break;
3945         }
3946       }
3947     }
3948   }
3949
3950   return false;
3951 }
3952
3953 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3954 {
3955   return Actor::RelayoutDependentOnChildren( dimension );
3956 }
3957
3958 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3959 {
3960   // Check each possible dimension and see if it is dependent on the input one
3961   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3962   {
3963     if( dimension & ( 1 << i ) )
3964     {
3965       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3966     }
3967   }
3968
3969   return false;
3970 }
3971
3972 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3973 {
3974   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3975   {
3976     if( dimension & ( 1 << i ) )
3977     {
3978       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3979     }
3980   }
3981 }
3982
3983 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3984 {
3985   // If more than one dimension is requested, just return the first one found
3986   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3987   {
3988     if( ( dimension & ( 1 << i ) ) )
3989     {
3990       return mRelayoutData->negotiatedDimensions[ i ];
3991     }
3992   }
3993
3994   return 0.0f;   // Default
3995 }
3996
3997 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3998 {
3999   EnsureRelayoutData();
4000
4001   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4002   {
4003     if( dimension & ( 1 << i ) )
4004     {
4005       mRelayoutData->dimensionPadding[ i ] = padding;
4006     }
4007   }
4008 }
4009
4010 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4011 {
4012   EnsureRelayoutData();
4013
4014   // If more than one dimension is requested, just return the first one found
4015   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4016   {
4017     if( ( dimension & ( 1 << i ) ) )
4018     {
4019       return mRelayoutData->dimensionPadding[ i ];
4020     }
4021   }
4022
4023   return Vector2( 0.0f, 0.0f );   // Default
4024 }
4025
4026 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4027 {
4028   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4029   {
4030     if( dimension & ( 1 << i ) )
4031     {
4032       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4033     }
4034   }
4035 }
4036
4037 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4038 {
4039   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4040   {
4041     if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4042     {
4043       return true;
4044     }
4045   }
4046
4047   return false;
4048 }
4049
4050 float Actor::GetHeightForWidthBase( float width )
4051 {
4052   float height = 0.0f;
4053
4054   const Vector3 naturalSize = GetNaturalSize();
4055   if( naturalSize.width > 0.0f )
4056   {
4057     height = naturalSize.height * width / naturalSize.width;
4058   }
4059   else // we treat 0 as 1:1 aspect ratio
4060   {
4061     height = width;
4062   }
4063
4064   return height;
4065 }
4066
4067 float Actor::GetWidthForHeightBase( float height )
4068 {
4069   float width = 0.0f;
4070
4071   const Vector3 naturalSize = GetNaturalSize();
4072   if( naturalSize.height > 0.0f )
4073   {
4074     width = naturalSize.width * height / naturalSize.height;
4075   }
4076   else // we treat 0 as 1:1 aspect ratio
4077   {
4078     width = height;
4079   }
4080
4081   return width;
4082 }
4083
4084 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4085 {
4086   // Fill to parent, taking size mode factor into account
4087   switch( child.GetResizePolicy( dimension ) )
4088   {
4089     case ResizePolicy::FILL_TO_PARENT:
4090     {
4091       return GetLatestSize( dimension );
4092     }
4093
4094     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4095     {
4096       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4097     }
4098
4099     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4100     {
4101       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4102     }
4103
4104     default:
4105     {
4106       return GetLatestSize( dimension );
4107     }
4108   }
4109 }
4110
4111 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4112 {
4113   // Can be overridden in derived class
4114   return CalculateChildSizeBase( child, dimension );
4115 }
4116
4117 float Actor::GetHeightForWidth( float width )
4118 {
4119   // Can be overridden in derived class
4120   return GetHeightForWidthBase( width );
4121 }
4122
4123 float Actor::GetWidthForHeight( float height )
4124 {
4125   // Can be overridden in derived class
4126   return GetWidthForHeightBase( height );
4127 }
4128
4129 float Actor::GetLatestSize( Dimension::Type dimension ) const
4130 {
4131   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4132 }
4133
4134 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4135 {
4136   Vector2 padding = GetPadding( dimension );
4137
4138   return GetLatestSize( dimension ) + padding.x + padding.y;
4139 }
4140
4141 float Actor::NegotiateFromParent( Dimension::Type dimension )
4142 {
4143   Actor* parent = GetParent();
4144   if( parent )
4145   {
4146     Vector2 padding( GetPadding( dimension ) );
4147     Vector2 parentPadding( parent->GetPadding( dimension ) );
4148     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4149   }
4150
4151   return 0.0f;
4152 }
4153
4154 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4155 {
4156   float maxDimensionPoint = 0.0f;
4157
4158   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4159   {
4160     Dali::Actor child = GetChildAt( i );
4161     Actor& childImpl = GetImplementation( child );
4162
4163     if( !childImpl.RelayoutDependentOnParent( dimension ) )
4164     {
4165       // Calculate the min and max points that the children range across
4166       float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4167       float dimensionSize = childImpl.GetRelayoutSize( dimension );
4168       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4169     }
4170   }
4171
4172   return maxDimensionPoint;
4173 }
4174
4175 float Actor::GetSize( Dimension::Type dimension ) const
4176 {
4177   return GetDimensionValue( GetTargetSize(), dimension );
4178 }
4179
4180 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4181 {
4182   return GetDimensionValue( GetNaturalSize(), dimension );
4183 }
4184
4185 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4186 {
4187   switch( GetResizePolicy( dimension ) )
4188   {
4189     case ResizePolicy::USE_NATURAL_SIZE:
4190     {
4191       return GetNaturalSize( dimension );
4192     }
4193
4194     case ResizePolicy::FIXED:
4195     {
4196       return GetDimensionValue( GetPreferredSize(), dimension );
4197     }
4198
4199     case ResizePolicy::USE_ASSIGNED_SIZE:
4200     {
4201       return GetDimensionValue( maximumSize, dimension );
4202     }
4203
4204     case ResizePolicy::FILL_TO_PARENT:
4205     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4206     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4207     {
4208       return NegotiateFromParent( dimension );
4209     }
4210
4211     case ResizePolicy::FIT_TO_CHILDREN:
4212     {
4213       return NegotiateFromChildren( dimension );
4214     }
4215
4216     case ResizePolicy::DIMENSION_DEPENDENCY:
4217     {
4218       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4219
4220       // Custom rules
4221       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4222       {
4223         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4224       }
4225
4226       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4227       {
4228         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4229       }
4230
4231       break;
4232     }
4233
4234     default:
4235     {
4236       break;
4237     }
4238   }
4239
4240   return 0.0f;  // Default
4241 }
4242
4243 float Actor::ClampDimension( float size, Dimension::Type dimension )
4244 {
4245   const float minSize = GetMinimumSize( dimension );
4246   const float maxSize = GetMaximumSize( dimension );
4247
4248   return std::max( minSize, std::min( size, maxSize ) );
4249 }
4250
4251 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4252 {
4253   // Check if it needs to be negotiated
4254   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4255   {
4256     // Check that we havn't gotten into an infinite loop
4257     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4258     bool recursionFound = false;
4259     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4260     {
4261       if( *it == searchActor )
4262       {
4263         recursionFound = true;
4264         break;
4265       }
4266     }
4267
4268     if( !recursionFound )
4269     {
4270       // Record the path that we have taken
4271       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4272
4273       // Dimension dependency check
4274       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4275       {
4276         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4277
4278         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4279         {
4280           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4281         }
4282       }
4283
4284       // Parent dependency check
4285       Actor* parent = GetParent();
4286       if( parent && RelayoutDependentOnParent( dimension ) )
4287       {
4288         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4289       }
4290
4291       // Children dependency check
4292       if( RelayoutDependentOnChildren( dimension ) )
4293       {
4294         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4295         {
4296           Dali::Actor child = GetChildAt( i );
4297           Actor& childImpl = GetImplementation( child );
4298
4299           // Only relayout child first if it is not dependent on this actor
4300           if( !childImpl.RelayoutDependentOnParent( dimension ) )
4301           {
4302             childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4303           }
4304         }
4305       }
4306
4307       // For deriving classes
4308       OnCalculateRelayoutSize( dimension );
4309
4310       // All dependencies checked, calculate the size and set negotiated flag
4311       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4312
4313       SetNegotiatedDimension( newSize, dimension );
4314       SetLayoutNegotiated( true, dimension );
4315
4316       // For deriving classes
4317       OnLayoutNegotiated( newSize, dimension );
4318
4319       // This actor has been successfully processed, pop it off the recursion stack
4320       recursionStack.pop_back();
4321     }
4322     else
4323     {
4324       // TODO: Break infinite loop
4325       SetLayoutNegotiated( true, dimension );
4326     }
4327   }
4328 }
4329
4330 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4331 {
4332   // Negotiate all dimensions that require it
4333   ActorDimensionStack recursionStack;
4334
4335   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4336   {
4337     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4338
4339     // Negotiate
4340     NegotiateDimension( dimension, allocatedSize, recursionStack );
4341   }
4342 }
4343
4344 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4345 {
4346   switch( mRelayoutData->sizeSetPolicy )
4347   {
4348     case SizeScalePolicy::USE_SIZE_SET:
4349     {
4350       return size;
4351     }
4352
4353     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4354     {
4355       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4356       const Vector3 naturalSize = GetNaturalSize();
4357       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4358       {
4359         const float sizeRatio = size.width / size.height;
4360         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4361
4362         if( naturalSizeRatio < sizeRatio )
4363         {
4364           return Vector2( naturalSizeRatio * size.height, size.height );
4365         }
4366         else if( naturalSizeRatio > sizeRatio )
4367         {
4368           return Vector2( size.width, size.width / naturalSizeRatio );
4369         }
4370         else
4371         {
4372           return size;
4373         }
4374       }
4375
4376       break;
4377     }
4378
4379     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4380     {
4381       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4382       const Vector3 naturalSize = GetNaturalSize();
4383       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4384       {
4385         const float sizeRatio = size.width / size.height;
4386         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4387
4388         if( naturalSizeRatio < sizeRatio )
4389         {
4390           return Vector2( size.width, size.width / naturalSizeRatio );
4391         }
4392         else if( naturalSizeRatio > sizeRatio )
4393         {
4394           return Vector2( naturalSizeRatio * size.height, size.height );
4395         }
4396         else
4397         {
4398           return size;
4399         }
4400       }
4401     }
4402
4403     default:
4404     {
4405       break;
4406     }
4407   }
4408
4409   return size;
4410 }
4411
4412 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4413 {
4414   // Do the set actor size
4415   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4416
4417   // Adjust for size set policy
4418   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4419
4420   // Lock the flag to stop recursive relayouts on set size
4421   mRelayoutData->insideRelayout = true;
4422   SetSize( negotiatedSize );
4423   mRelayoutData->insideRelayout = false;
4424
4425   // Clear flags for all dimensions
4426   SetLayoutDirty( false );
4427
4428   // Give deriving classes a chance to respond
4429   OnRelayout( negotiatedSize, container );
4430
4431   if( !mOnRelayoutSignal.Empty() )
4432   {
4433     Dali::Actor handle( this );
4434     mOnRelayoutSignal.Emit( handle );
4435   }
4436 }
4437
4438 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4439 {
4440   // Do the negotiation
4441   NegotiateDimensions( allocatedSize );
4442
4443   // Set the actor size
4444   SetNegotiatedSize( container );
4445
4446   // Negotiate down to children
4447   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4448
4449   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4450   {
4451     Dali::Actor child = GetChildAt( i );
4452
4453     // Only relayout if required
4454     if( GetImplementation( child ).RelayoutRequired() )
4455     {
4456       container.Add( child, newBounds );
4457     }
4458   }
4459 }
4460
4461 void Actor::RelayoutRequest( Dimension::Type dimension )
4462 {
4463   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4464   if( relayoutController )
4465   {
4466     Dali::Actor self( this );
4467     relayoutController->RequestRelayout( self, dimension );
4468   }
4469 }
4470
4471 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4472 {
4473 }
4474
4475 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4476 {
4477 }
4478
4479 void Actor::SetPreferredSize( const Vector2& size )
4480 {
4481   EnsureRelayoutData();
4482
4483   if( size.width > 0.0f )
4484   {
4485     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4486   }
4487
4488   if( size.height > 0.0f )
4489   {
4490     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4491   }
4492
4493   mRelayoutData->preferredSize = size;
4494
4495   RelayoutRequest();
4496 }
4497
4498 Vector2 Actor::GetPreferredSize() const
4499 {
4500   EnsureRelayoutData();
4501
4502   return mRelayoutData->preferredSize;
4503 }
4504
4505 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4506 {
4507   EnsureRelayoutData();
4508
4509   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4510   {
4511     if( dimension & ( 1 << i ) )
4512     {
4513       mRelayoutData->minimumSize[ i ] = size;
4514     }
4515   }
4516
4517   RelayoutRequest();
4518 }
4519
4520 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4521 {
4522   EnsureRelayoutData();
4523
4524   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4525   {
4526     if( dimension & ( 1 << i ) )
4527     {
4528       return mRelayoutData->minimumSize[ i ];
4529     }
4530   }
4531
4532   return 0.0f;  // Default
4533 }
4534
4535 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4536 {
4537   EnsureRelayoutData();
4538
4539   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4540   {
4541     if( dimension & ( 1 << i ) )
4542     {
4543       mRelayoutData->maximumSize[ i ] = size;
4544     }
4545   }
4546
4547   RelayoutRequest();
4548 }
4549
4550 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4551 {
4552   EnsureRelayoutData();
4553
4554   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4555   {
4556     if( dimension & ( 1 << i ) )
4557     {
4558       return mRelayoutData->maximumSize[ i ];
4559     }
4560   }
4561
4562   return 0.0f;  // Default
4563 }
4564
4565 } // namespace Internal
4566
4567 } // namespace Dali