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