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