Remove dali-any from Property::Value - reimplement multivalue using more efficient...
[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   if( OnStage() )
1859   {
1860     const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1861
1862     Vector2 converted( screenX, screenY );
1863
1864     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1865     const int taskCount = taskList.GetTaskCount();
1866     for( int i = taskCount - 1; i >= 0; --i )
1867     {
1868       Dali::RenderTask task = taskList.GetTask( i );
1869       if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1870       {
1871         // found a task where this conversion was ok so return
1872         return true;
1873       }
1874     }
1875   }
1876   return false;
1877 }
1878
1879 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1880 {
1881   bool retval = false;
1882   // only valid when on-stage
1883   if( OnStage() )
1884   {
1885     CameraActor* camera = renderTask.GetCameraActor();
1886     if( camera )
1887     {
1888       Viewport viewport;
1889       renderTask.GetViewport( viewport );
1890
1891       // need to translate coordinates to render tasks coordinate space
1892       Vector2 converted( screenX, screenY );
1893       if( renderTask.TranslateCoordinates( converted ) )
1894       {
1895         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1896       }
1897     }
1898   }
1899   return retval;
1900 }
1901
1902 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1903 {
1904   // Early-out if mNode is NULL
1905   if( !OnStage() )
1906   {
1907     return false;
1908   }
1909
1910   BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1911
1912   // Calculate the ModelView matrix
1913   Matrix modelView( false/*don't init*/);
1914   // need to use the components as world matrix is only updated for actors that need it
1915   modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1916   Matrix::Multiply( modelView, modelView, viewMatrix );
1917
1918   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1919   Matrix invertedMvp( false/*don't init*/);
1920   Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1921   bool success = invertedMvp.Invert();
1922
1923   // Convert to GL coordinates
1924   Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1925
1926   Vector4 nearPos;
1927   if( success )
1928   {
1929     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1930   }
1931
1932   Vector4 farPos;
1933   if( success )
1934   {
1935     screenPos.z = 1.0f;
1936     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1937   }
1938
1939   if( success )
1940   {
1941     Vector4 local;
1942     if( XyPlaneIntersect( nearPos, farPos, local ) )
1943     {
1944       Vector3 size = GetCurrentSize();
1945       localX = local.x + size.x * 0.5f;
1946       localY = local.y + size.y * 0.5f;
1947     }
1948     else
1949     {
1950       success = false;
1951     }
1952   }
1953
1954   return success;
1955 }
1956
1957 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1958 {
1959   /*
1960    http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1961
1962    Mathematical Formulation
1963
1964    Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1965
1966    ( p - c ) dot ( p - c ) = r^2
1967
1968    Given a ray with a point of origin 'o', and a direction vector 'd':
1969
1970    ray(t) = o + td, t >= 0
1971
1972    we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1973
1974    (o + td - c ) dot ( o + td - c ) = r^2
1975
1976    To solve for t we first expand the above into a more recognisable quadratic equation form
1977
1978    ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1979
1980    or
1981
1982    At2 + Bt + C = 0
1983
1984    where
1985
1986    A = d dot d
1987    B = 2( o - c ) dot d
1988    C = ( o - c ) dot ( o - c ) - r^2
1989
1990    which can be solved using a standard quadratic formula.
1991
1992    Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1993
1994    Practical Simplification
1995
1996    In a renderer, we often differentiate between world space and object space. In the object space
1997    of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1998    into object space, the mathematical solution presented above can be simplified significantly.
1999
2000    If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2001
2002    p dot p = r^2
2003
2004    and we can find the t at which the (transformed) ray intersects the sphere by
2005
2006    ( o + td ) dot ( o + td ) = r^2
2007
2008    According to the reasoning above, we expand the above quadratic equation into the general form
2009
2010    At2 + Bt + C = 0
2011
2012    which now has coefficients:
2013
2014    A = d dot d
2015    B = 2( d dot o )
2016    C = o dot o - r^2
2017    */
2018
2019   // Early out if mNode is NULL
2020   if( !mNode )
2021   {
2022     return false;
2023   }
2024
2025   BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2026
2027   // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2028   const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2029   Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2030
2031   // Compute the radius is not needed, square radius it's enough.
2032   const Vector3& size( mNode->GetSize( bufferIndex ) );
2033
2034   // Scale the sphere.
2035   const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2036
2037   const float width = size.width * scale.width;
2038   const float height = size.height * scale.height;
2039
2040   float squareSphereRadius = 0.5f * ( width * width + height * height );
2041
2042   float a = rayDir.Dot( rayDir );                                       // a
2043   float b2 = rayDir.Dot( rayOriginLocal );                              // b/2
2044   float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius;  // c
2045
2046   return ( b2 * b2 - a * c ) >= 0.f;
2047 }
2048
2049 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2050 {
2051   bool hit = false;
2052
2053   if( OnStage() &&
2054   NULL != mNode )
2055   {
2056     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2057
2058     // Transforms the ray to the local reference system.
2059
2060     // Calculate the inverse of Model matrix
2061     Matrix invModelMatrix( false/*don't init*/);
2062     // need to use the components as world matrix is only updated for actors that need it
2063     invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2064
2065     Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2066     Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2067
2068     // Test with the actor's XY plane (Normal = 0 0 1 1).
2069
2070     float a = -rayOriginLocal.z;
2071     float b = rayDirLocal.z;
2072
2073     if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2074     {
2075       // Ray travels distance * rayDirLocal to intersect with plane.
2076       distance = a / b;
2077
2078       const Vector3& size = mNode->GetSize( bufferIndex );
2079
2080       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2081       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2082
2083       // Test with the actor's geometry.
2084       hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2085     }
2086   }
2087
2088   return hit;
2089 }
2090
2091 void Actor::SetLeaveRequired( bool required )
2092 {
2093   mLeaveRequired = required;
2094 }
2095
2096 bool Actor::GetLeaveRequired() const
2097 {
2098   return mLeaveRequired;
2099 }
2100
2101 void Actor::SetKeyboardFocusable( bool focusable )
2102 {
2103   mKeyboardFocusable = focusable;
2104 }
2105
2106 bool Actor::IsKeyboardFocusable() const
2107 {
2108   return mKeyboardFocusable;
2109 }
2110
2111 bool Actor::GetTouchRequired() const
2112 {
2113   return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2114 }
2115
2116 bool Actor::GetHoverRequired() const
2117 {
2118   return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2119 }
2120
2121 bool Actor::GetWheelEventRequired() const
2122 {
2123   return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2124 }
2125
2126 bool Actor::IsHittable() const
2127 {
2128   return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2129 }
2130
2131 ActorGestureData& Actor::GetGestureData()
2132 {
2133   // Likely scenario is that once gesture-data is created for this actor, the actor will require
2134   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2135   if( NULL == mGestureData )
2136   {
2137     mGestureData = new ActorGestureData;
2138   }
2139   return *mGestureData;
2140 }
2141
2142 bool Actor::IsGestureRequred( Gesture::Type type ) const
2143 {
2144   return mGestureData && mGestureData->IsGestureRequred( type );
2145 }
2146
2147 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2148 {
2149   bool consumed = false;
2150
2151   if( !mTouchedSignal.Empty() )
2152   {
2153     Dali::Actor handle( this );
2154     consumed = mTouchedSignal.Emit( handle, event );
2155   }
2156
2157   if( !consumed )
2158   {
2159     // Notification for derived classes
2160     consumed = OnTouchEvent( event );
2161   }
2162
2163   return consumed;
2164 }
2165
2166 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2167 {
2168   bool consumed = false;
2169
2170   if( !mHoveredSignal.Empty() )
2171   {
2172     Dali::Actor handle( this );
2173     consumed = mHoveredSignal.Emit( handle, event );
2174   }
2175
2176   if( !consumed )
2177   {
2178     // Notification for derived classes
2179     consumed = OnHoverEvent( event );
2180   }
2181
2182   return consumed;
2183 }
2184
2185 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2186 {
2187   bool consumed = false;
2188
2189   if( !mWheelEventSignal.Empty() )
2190   {
2191     Dali::Actor handle( this );
2192     consumed = mWheelEventSignal.Emit( handle, event );
2193   }
2194
2195   if( !consumed )
2196   {
2197     // Notification for derived classes
2198     consumed = OnWheelEvent( event );
2199   }
2200
2201   return consumed;
2202 }
2203
2204 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2205 {
2206   return mTouchedSignal;
2207 }
2208
2209 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2210 {
2211   return mHoveredSignal;
2212 }
2213
2214 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2215 {
2216   return mWheelEventSignal;
2217 }
2218
2219 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2220 {
2221   return mOnStageSignal;
2222 }
2223
2224 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2225 {
2226   return mOffStageSignal;
2227 }
2228
2229 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2230 {
2231   return mOnRelayoutSignal;
2232 }
2233
2234 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2235 {
2236   bool connected( true );
2237   Actor* actor = dynamic_cast< Actor* >( object );
2238
2239   if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2240   {
2241     actor->TouchedSignal().Connect( tracker, functor );
2242   }
2243   else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2244   {
2245     actor->HoveredSignal().Connect( tracker, functor );
2246   }
2247   else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2248   {
2249     actor->WheelEventSignal().Connect( tracker, functor );
2250   }
2251   else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2252   {
2253     actor->OnStageSignal().Connect( tracker, functor );
2254   }
2255   else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2256   {
2257     actor->OffStageSignal().Connect( tracker, functor );
2258   }
2259   else
2260   {
2261     // signalName does not match any signal
2262     connected = false;
2263   }
2264
2265   return connected;
2266 }
2267
2268 Actor::Actor( DerivedType derivedType )
2269 : mParent( NULL ),
2270   mChildren( NULL ),
2271   mNode( NULL ),
2272   mParentOrigin( NULL ),
2273   mAnchorPoint( NULL ),
2274   mRelayoutData( NULL ),
2275 #ifdef DALI_DYNAMICS_SUPPORT
2276   mDynamicsData( NULL ),
2277 #endif
2278   mGestureData( NULL ),
2279   mAttachment(),
2280   mTargetSize( 0.0f, 0.0f, 0.0f ),
2281   mName(),
2282   mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2283   mIsRoot( ROOT_LAYER == derivedType ),
2284   mIsRenderable( RENDERABLE == derivedType ),
2285   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2286   mIsOnStage( false ),
2287   mIsDynamicsRoot( false ),
2288   mSensitive( true ),
2289   mLeaveRequired( false ),
2290   mKeyboardFocusable( false ),
2291   mDerivedRequiresTouch( false ),
2292   mDerivedRequiresHover( false ),
2293   mDerivedRequiresWheelEvent( false ),
2294   mOnStageSignalled( false ),
2295   mInsideOnSizeSet( false ),
2296   mInheritOrientation( true ),
2297   mInheritScale( true ),
2298   mDrawMode( DrawMode::NORMAL ),
2299   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2300   mColorMode( Node::DEFAULT_COLOR_MODE )
2301 {
2302 }
2303
2304 void Actor::Initialize()
2305 {
2306   // Node creation
2307   SceneGraph::Node* node = CreateNode();
2308
2309   AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2310   mNode = node; // Keep raw-pointer to Node
2311
2312   OnInitialize();
2313
2314   GetEventThreadServices().RegisterObject( this );
2315 }
2316
2317 Actor::~Actor()
2318 {
2319   // Remove mParent pointers from children even if we're destroying core,
2320   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2321   if( mChildren )
2322   {
2323     ActorConstIter endIter = mChildren->end();
2324     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2325     {
2326       Actor& actor = GetImplementation( *iter );
2327       actor.SetParent( NULL );
2328     }
2329   }
2330   delete mChildren;
2331
2332   // Guard to allow handle destruction after Core has been destroyed
2333   if( EventThreadServices::IsCoreRunning() )
2334   {
2335     if( NULL != mNode )
2336     {
2337       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2338       mNode = NULL; // Node is about to be destroyed
2339     }
2340
2341     GetEventThreadServices().UnregisterObject( this );
2342   }
2343
2344 #ifdef DALI_DYNAMICS_SUPPORT
2345   // Cleanup dynamics
2346   delete mDynamicsData;
2347 #endif
2348
2349   // Cleanup optional gesture data
2350   delete mGestureData;
2351
2352   // Cleanup optional parent origin and anchor
2353   delete mParentOrigin;
2354   delete mAnchorPoint;
2355
2356   // Delete optional relayout data
2357   if( mRelayoutData )
2358   {
2359     delete mRelayoutData;
2360   }
2361 }
2362
2363 void Actor::ConnectToStage( int index )
2364 {
2365   // This container is used instead of walking the Actor hierachy.
2366   // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2367   ActorContainer connectionList;
2368
2369   // This stage is atomic i.e. not interrupted by user callbacks
2370   RecursiveConnectToStage( connectionList, index );
2371
2372   // Notify applications about the newly connected actors.
2373   const ActorIter endIter = connectionList.end();
2374   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2375   {
2376     Actor& actor = GetImplementation( *iter );
2377     actor.NotifyStageConnection();
2378   }
2379
2380   RelayoutRequest();
2381 }
2382
2383 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2384 {
2385   DALI_ASSERT_ALWAYS( !OnStage() );
2386
2387   mIsOnStage = true;
2388
2389   ConnectToSceneGraph( index );
2390
2391   // Notification for internal derived classes
2392   OnStageConnectionInternal();
2393
2394   // This stage is atomic; avoid emitting callbacks until all Actors are connected
2395   connectionList.push_back( Dali::Actor( this ) );
2396
2397   // Recursively connect children
2398   if( mChildren )
2399   {
2400     ActorConstIter endIter = mChildren->end();
2401     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2402     {
2403       Actor& actor = GetImplementation( *iter );
2404       actor.RecursiveConnectToStage( connectionList );
2405     }
2406   }
2407 }
2408
2409 /**
2410  * This method is called when the Actor is connected to the Stage.
2411  * The parent must have added its Node to the scene-graph.
2412  * The child must connect its Node to the parent's Node.
2413  * This is resursive; the child calls ConnectToStage() for its children.
2414  */
2415 void Actor::ConnectToSceneGraph( int index )
2416 {
2417   DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2418
2419   if( NULL != mNode )
2420   {
2421     // Reparent Node in next Update
2422     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2423   }
2424
2425   // Notify attachment
2426   if( mAttachment )
2427   {
2428     mAttachment->Connect();
2429   }
2430
2431 #ifdef DALI_DYNAMICS_SUPPORT
2432   // Notify dynamics
2433   if( NULL != mDynamicsData )
2434   {
2435     ConnectDynamics();
2436   }
2437 #endif
2438
2439   // Request relayout on all actors that are added to the scenegraph
2440   RelayoutRequest();
2441
2442   // Notification for Object::Observers
2443   OnSceneObjectAdd();
2444 }
2445
2446 void Actor::NotifyStageConnection()
2447 {
2448   // Actors can be removed (in a callback), before the on-stage stage is reported.
2449   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2450   if( OnStage() && !mOnStageSignalled )
2451   {
2452     // Notification for external (CustomActor) derived classes
2453     OnStageConnectionExternal();
2454
2455     if( !mOnStageSignal.Empty() )
2456     {
2457       Dali::Actor handle( this );
2458       mOnStageSignal.Emit( handle );
2459     }
2460
2461     // Guard against Remove during callbacks
2462     if( OnStage() )
2463     {
2464       mOnStageSignalled = true; // signal required next time Actor is removed
2465     }
2466   }
2467 }
2468
2469 void Actor::DisconnectFromStage()
2470 {
2471   // This container is used instead of walking the Actor hierachy.
2472   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2473   ActorContainer disconnectionList;
2474
2475   // This stage is atomic i.e. not interrupted by user callbacks
2476   RecursiveDisconnectFromStage( disconnectionList );
2477
2478   // Notify applications about the newly disconnected actors.
2479   const ActorIter endIter = disconnectionList.end();
2480   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2481   {
2482     Actor& actor = GetImplementation( *iter );
2483     actor.NotifyStageDisconnection();
2484   }
2485 }
2486
2487 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2488 {
2489   DALI_ASSERT_ALWAYS( OnStage() );
2490
2491   // Recursively disconnect children
2492   if( mChildren )
2493   {
2494     ActorConstIter endIter = mChildren->end();
2495     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2496     {
2497       Actor& actor = GetImplementation( *iter );
2498       actor.RecursiveDisconnectFromStage( disconnectionList );
2499     }
2500   }
2501
2502   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2503   disconnectionList.push_back( Dali::Actor( this ) );
2504
2505   // Notification for internal derived classes
2506   OnStageDisconnectionInternal();
2507
2508   DisconnectFromSceneGraph();
2509
2510   mIsOnStage = false;
2511 }
2512
2513 /**
2514  * This method is called by an actor or its parent, before a node removal message is sent.
2515  * This is recursive; the child calls DisconnectFromStage() for its children.
2516  */
2517 void Actor::DisconnectFromSceneGraph()
2518 {
2519   // Notification for Object::Observers
2520   OnSceneObjectRemove();
2521
2522   // Notify attachment
2523   if( mAttachment )
2524   {
2525     mAttachment->Disconnect();
2526   }
2527
2528 #ifdef DALI_DYNAMICS_SUPPORT
2529   // Notify dynamics
2530   if( NULL != mDynamicsData )
2531   {
2532     DisconnectDynamics();
2533   }
2534 #endif
2535 }
2536
2537 void Actor::NotifyStageDisconnection()
2538 {
2539   // Actors can be added (in a callback), before the off-stage state is reported.
2540   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2541   // only do this step if there is a stage, i.e. Core is not being shut down
2542   if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2543   {
2544     // Notification for external (CustomeActor) derived classes
2545     OnStageDisconnectionExternal();
2546
2547     if( !mOffStageSignal.Empty() )
2548     {
2549       Dali::Actor handle( this );
2550       mOffStageSignal.Emit( handle );
2551     }
2552
2553     // Guard against Add during callbacks
2554     if( !OnStage() )
2555     {
2556       mOnStageSignalled = false; // signal required next time Actor is added
2557     }
2558   }
2559 }
2560
2561 bool Actor::IsNodeConnected() const
2562 {
2563   bool connected( false );
2564
2565   if( OnStage() &&
2566   NULL != mNode )
2567   {
2568     if( mNode->IsRoot() || mNode->GetParent() )
2569     {
2570       connected = true;
2571     }
2572   }
2573
2574   return connected;
2575 }
2576
2577 unsigned int Actor::GetDefaultPropertyCount() const
2578 {
2579   return DEFAULT_PROPERTY_COUNT;
2580 }
2581
2582 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2583 {
2584   indices.Reserve( DEFAULT_PROPERTY_COUNT );
2585
2586   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2587   {
2588     indices.PushBack( i );
2589   }
2590 }
2591
2592 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2593 {
2594   if( index < DEFAULT_PROPERTY_COUNT )
2595   {
2596     return DEFAULT_PROPERTY_DETAILS[ index ].name;
2597   }
2598
2599   return NULL;
2600 }
2601
2602 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2603 {
2604   Property::Index index = Property::INVALID_INDEX;
2605
2606   // Look for name in default properties
2607   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2608   {
2609     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2610     if( 0 == name.compare( property->name ) )
2611     {
2612       index = i;
2613       break;
2614     }
2615   }
2616
2617   return index;
2618 }
2619
2620 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2621 {
2622   if( index < DEFAULT_PROPERTY_COUNT )
2623   {
2624     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2625   }
2626
2627   return false;
2628 }
2629
2630 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2631 {
2632   if( index < DEFAULT_PROPERTY_COUNT )
2633   {
2634     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2635   }
2636
2637   return false;
2638 }
2639
2640 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2641 {
2642   if( index < DEFAULT_PROPERTY_COUNT )
2643   {
2644     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2645   }
2646
2647   return false;
2648 }
2649
2650 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2651 {
2652   if( index < DEFAULT_PROPERTY_COUNT )
2653   {
2654     return DEFAULT_PROPERTY_DETAILS[ index ].type;
2655   }
2656
2657   // index out of range...return Property::NONE
2658   return Property::NONE;
2659 }
2660
2661 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2662 {
2663   switch( index )
2664   {
2665     case Dali::Actor::Property::PARENT_ORIGIN:
2666     {
2667       SetParentOrigin( property.Get< Vector3 >() );
2668       break;
2669     }
2670
2671     case Dali::Actor::Property::PARENT_ORIGIN_X:
2672     {
2673       SetParentOriginX( property.Get< float >() );
2674       break;
2675     }
2676
2677     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2678     {
2679       SetParentOriginY( property.Get< float >() );
2680       break;
2681     }
2682
2683     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2684     {
2685       SetParentOriginZ( property.Get< float >() );
2686       break;
2687     }
2688
2689     case Dali::Actor::Property::ANCHOR_POINT:
2690     {
2691       SetAnchorPoint( property.Get< Vector3 >() );
2692       break;
2693     }
2694
2695     case Dali::Actor::Property::ANCHOR_POINT_X:
2696     {
2697       SetAnchorPointX( property.Get< float >() );
2698       break;
2699     }
2700
2701     case Dali::Actor::Property::ANCHOR_POINT_Y:
2702     {
2703       SetAnchorPointY( property.Get< float >() );
2704       break;
2705     }
2706
2707     case Dali::Actor::Property::ANCHOR_POINT_Z:
2708     {
2709       SetAnchorPointZ( property.Get< float >() );
2710       break;
2711     }
2712
2713     case Dali::Actor::Property::SIZE:
2714     {
2715       SetSize( property.Get< Vector3 >() );
2716       break;
2717     }
2718
2719     case Dali::Actor::Property::SIZE_WIDTH:
2720     {
2721       SetWidth( property.Get< float >() );
2722       break;
2723     }
2724
2725     case Dali::Actor::Property::SIZE_HEIGHT:
2726     {
2727       SetHeight( property.Get< float >() );
2728       break;
2729     }
2730
2731     case Dali::Actor::Property::SIZE_DEPTH:
2732     {
2733       SetDepth( property.Get< float >() );
2734       break;
2735     }
2736
2737     case Dali::Actor::Property::POSITION:
2738     {
2739       SetPosition( property.Get< Vector3 >() );
2740       break;
2741     }
2742
2743     case Dali::Actor::Property::POSITION_X:
2744     {
2745       SetX( property.Get< float >() );
2746       break;
2747     }
2748
2749     case Dali::Actor::Property::POSITION_Y:
2750     {
2751       SetY( property.Get< float >() );
2752       break;
2753     }
2754
2755     case Dali::Actor::Property::POSITION_Z:
2756     {
2757       SetZ( property.Get< float >() );
2758       break;
2759     }
2760
2761     case Dali::Actor::Property::ORIENTATION:
2762     {
2763       SetOrientation( property.Get< Quaternion >() );
2764       break;
2765     }
2766
2767     case Dali::Actor::Property::SCALE:
2768     {
2769       SetScale( property.Get< Vector3 >() );
2770       break;
2771     }
2772
2773     case Dali::Actor::Property::SCALE_X:
2774     {
2775       SetScaleX( property.Get< float >() );
2776       break;
2777     }
2778
2779     case Dali::Actor::Property::SCALE_Y:
2780     {
2781       SetScaleY( property.Get< float >() );
2782       break;
2783     }
2784
2785     case Dali::Actor::Property::SCALE_Z:
2786     {
2787       SetScaleZ( property.Get< float >() );
2788       break;
2789     }
2790
2791     case Dali::Actor::Property::VISIBLE:
2792     {
2793       SetVisible( property.Get< bool >() );
2794       break;
2795     }
2796
2797     case Dali::Actor::Property::COLOR:
2798     {
2799       SetColor( property.Get< Vector4 >() );
2800       break;
2801     }
2802
2803     case Dali::Actor::Property::COLOR_RED:
2804     {
2805       SetColorRed( property.Get< float >() );
2806       break;
2807     }
2808
2809     case Dali::Actor::Property::COLOR_GREEN:
2810     {
2811       SetColorGreen( property.Get< float >() );
2812       break;
2813     }
2814
2815     case Dali::Actor::Property::COLOR_BLUE:
2816     {
2817       SetColorBlue( property.Get< float >() );
2818       break;
2819     }
2820
2821     case Dali::Actor::Property::COLOR_ALPHA:
2822     {
2823       SetOpacity( property.Get< float >() );
2824       break;
2825     }
2826
2827     case Dali::Actor::Property::NAME:
2828     {
2829       SetName( property.Get< std::string >() );
2830       break;
2831     }
2832
2833     case Dali::Actor::Property::SENSITIVE:
2834     {
2835       SetSensitive( property.Get< bool >() );
2836       break;
2837     }
2838
2839     case Dali::Actor::Property::LEAVE_REQUIRED:
2840     {
2841       SetLeaveRequired( property.Get< bool >() );
2842       break;
2843     }
2844
2845     case Dali::Actor::Property::INHERIT_ORIENTATION:
2846     {
2847       SetInheritOrientation( property.Get< bool >() );
2848       break;
2849     }
2850
2851     case Dali::Actor::Property::INHERIT_SCALE:
2852     {
2853       SetInheritScale( property.Get< bool >() );
2854       break;
2855     }
2856
2857     case Dali::Actor::Property::COLOR_MODE:
2858     {
2859       SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2860       break;
2861     }
2862
2863     case Dali::Actor::Property::POSITION_INHERITANCE:
2864     {
2865       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2866       break;
2867     }
2868
2869     case Dali::Actor::Property::DRAW_MODE:
2870     {
2871       SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2872       break;
2873     }
2874
2875     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2876     {
2877       SetSizeModeFactor( property.Get< Vector3 >() );
2878       break;
2879     }
2880
2881     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2882     {
2883       ResizePolicy::Type type;
2884       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2885       {
2886         SetResizePolicy( type, Dimension::WIDTH );
2887       }
2888       break;
2889     }
2890
2891     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2892     {
2893       ResizePolicy::Type type;
2894       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2895       {
2896         SetResizePolicy( type, Dimension::HEIGHT );
2897       }
2898       break;
2899     }
2900
2901     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2902     {
2903       SizeScalePolicy::Type type;
2904       if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2905       {
2906         SetSizeScalePolicy( type );
2907       }
2908       break;
2909     }
2910
2911     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2912     {
2913       if( property.Get< bool >() )
2914       {
2915         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2916       }
2917       break;
2918     }
2919
2920     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2921     {
2922       if( property.Get< bool >() )
2923       {
2924         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2925       }
2926       break;
2927     }
2928
2929     case Dali::Actor::Property::PADDING:
2930     {
2931       Vector4 padding = property.Get< Vector4 >();
2932       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2933       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2934       break;
2935     }
2936
2937     case Dali::Actor::Property::MINIMUM_SIZE:
2938     {
2939       Vector2 size = property.Get< Vector2 >();
2940       SetMinimumSize( size.x, Dimension::WIDTH );
2941       SetMinimumSize( size.y, Dimension::HEIGHT );
2942       break;
2943     }
2944
2945     case Dali::Actor::Property::MAXIMUM_SIZE:
2946     {
2947       Vector2 size = property.Get< Vector2 >();
2948       SetMaximumSize( size.x, Dimension::WIDTH );
2949       SetMaximumSize( size.y, Dimension::HEIGHT );
2950       break;
2951     }
2952
2953     default:
2954     {
2955       // this can happen in the case of a non-animatable default property so just do nothing
2956       break;
2957     }
2958   }
2959 }
2960
2961 // TODO: This method needs to be removed
2962 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2963 {
2964   switch( entry.type )
2965   {
2966     case Property::BOOLEAN:
2967     {
2968       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2969       DALI_ASSERT_DEBUG( NULL != property );
2970
2971       // property is being used in a separate thread; queue a message to set the property
2972       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2973
2974       break;
2975     }
2976
2977     case Property::INTEGER:
2978     {
2979       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2980       DALI_ASSERT_DEBUG( NULL != property );
2981
2982       // property is being used in a separate thread; queue a message to set the property
2983       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2984
2985       break;
2986     }
2987
2988     case Property::UNSIGNED_INTEGER:
2989     {
2990       const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2991       DALI_ASSERT_DEBUG( NULL != property );
2992
2993       // property is being used in a separate thread; queue a message to set the property
2994       SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2995
2996       break;
2997     }
2998
2999     case Property::FLOAT:
3000     {
3001       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3002       DALI_ASSERT_DEBUG( NULL != property );
3003
3004       // property is being used in a separate thread; queue a message to set the property
3005       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3006
3007       break;
3008     }
3009
3010     case Property::VECTOR2:
3011     {
3012       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3013       DALI_ASSERT_DEBUG( NULL != property );
3014
3015       // property is being used in a separate thread; queue a message to set the property
3016       if(entry.componentIndex == 0)
3017       {
3018         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3019       }
3020       else if(entry.componentIndex == 1)
3021       {
3022         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3023       }
3024       else
3025       {
3026         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3027       }
3028
3029       break;
3030     }
3031
3032     case Property::VECTOR3:
3033     {
3034       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3035       DALI_ASSERT_DEBUG( NULL != property );
3036
3037       // property is being used in a separate thread; queue a message to set the property
3038       if(entry.componentIndex == 0)
3039       {
3040         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3041       }
3042       else if(entry.componentIndex == 1)
3043       {
3044         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3045       }
3046       else if(entry.componentIndex == 2)
3047       {
3048         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3049       }
3050       else
3051       {
3052         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3053       }
3054
3055       break;
3056     }
3057
3058     case Property::VECTOR4:
3059     {
3060       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3061       DALI_ASSERT_DEBUG( NULL != property );
3062
3063       // property is being used in a separate thread; queue a message to set the property
3064       if(entry.componentIndex == 0)
3065       {
3066         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3067       }
3068       else if(entry.componentIndex == 1)
3069       {
3070         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3071       }
3072       else if(entry.componentIndex == 2)
3073       {
3074         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3075       }
3076       else if(entry.componentIndex == 3)
3077       {
3078         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3079       }
3080       else
3081       {
3082         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3083       }
3084
3085       break;
3086     }
3087
3088     case Property::ROTATION:
3089     {
3090       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3091       DALI_ASSERT_DEBUG( NULL != property );
3092
3093       // property is being used in a separate thread; queue a message to set the property
3094       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
3095
3096       break;
3097     }
3098
3099     case Property::MATRIX:
3100     {
3101       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3102       DALI_ASSERT_DEBUG( NULL != property );
3103
3104       // property is being used in a separate thread; queue a message to set the property
3105       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
3106
3107       break;
3108     }
3109
3110     case Property::MATRIX3:
3111     {
3112       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3113       DALI_ASSERT_DEBUG( NULL != property );
3114
3115       // property is being used in a separate thread; queue a message to set the property
3116       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
3117
3118       break;
3119     }
3120
3121     default:
3122     {
3123       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3124       break;
3125     }
3126   }
3127 }
3128
3129 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3130 {
3131   Property::Value value;
3132
3133   switch( index )
3134   {
3135     case Dali::Actor::Property::PARENT_ORIGIN:
3136     {
3137       value = GetCurrentParentOrigin();
3138       break;
3139     }
3140
3141     case Dali::Actor::Property::PARENT_ORIGIN_X:
3142     {
3143       value = GetCurrentParentOrigin().x;
3144       break;
3145     }
3146
3147     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3148     {
3149       value = GetCurrentParentOrigin().y;
3150       break;
3151     }
3152
3153     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3154     {
3155       value = GetCurrentParentOrigin().z;
3156       break;
3157     }
3158
3159     case Dali::Actor::Property::ANCHOR_POINT:
3160     {
3161       value = GetCurrentAnchorPoint();
3162       break;
3163     }
3164
3165     case Dali::Actor::Property::ANCHOR_POINT_X:
3166     {
3167       value = GetCurrentAnchorPoint().x;
3168       break;
3169     }
3170
3171     case Dali::Actor::Property::ANCHOR_POINT_Y:
3172     {
3173       value = GetCurrentAnchorPoint().y;
3174       break;
3175     }
3176
3177     case Dali::Actor::Property::ANCHOR_POINT_Z:
3178     {
3179       value = GetCurrentAnchorPoint().z;
3180       break;
3181     }
3182
3183     case Dali::Actor::Property::SIZE:
3184     {
3185       value = GetCurrentSize();
3186       break;
3187     }
3188
3189     case Dali::Actor::Property::SIZE_WIDTH:
3190     {
3191       value = GetCurrentSize().width;
3192       break;
3193     }
3194
3195     case Dali::Actor::Property::SIZE_HEIGHT:
3196     {
3197       value = GetCurrentSize().height;
3198       break;
3199     }
3200
3201     case Dali::Actor::Property::SIZE_DEPTH:
3202     {
3203       value = GetCurrentSize().depth;
3204       break;
3205     }
3206
3207     case Dali::Actor::Property::POSITION:
3208     {
3209       value = GetCurrentPosition();
3210       break;
3211     }
3212
3213     case Dali::Actor::Property::POSITION_X:
3214     {
3215       value = GetCurrentPosition().x;
3216       break;
3217     }
3218
3219     case Dali::Actor::Property::POSITION_Y:
3220     {
3221       value = GetCurrentPosition().y;
3222       break;
3223     }
3224
3225     case Dali::Actor::Property::POSITION_Z:
3226     {
3227       value = GetCurrentPosition().z;
3228       break;
3229     }
3230
3231     case Dali::Actor::Property::WORLD_POSITION:
3232     {
3233       value = GetCurrentWorldPosition();
3234       break;
3235     }
3236
3237     case Dali::Actor::Property::WORLD_POSITION_X:
3238     {
3239       value = GetCurrentWorldPosition().x;
3240       break;
3241     }
3242
3243     case Dali::Actor::Property::WORLD_POSITION_Y:
3244     {
3245       value = GetCurrentWorldPosition().y;
3246       break;
3247     }
3248
3249     case Dali::Actor::Property::WORLD_POSITION_Z:
3250     {
3251       value = GetCurrentWorldPosition().z;
3252       break;
3253     }
3254
3255     case Dali::Actor::Property::ORIENTATION:
3256     {
3257       value = GetCurrentOrientation();
3258       break;
3259     }
3260
3261     case Dali::Actor::Property::WORLD_ORIENTATION:
3262     {
3263       value = GetCurrentWorldOrientation();
3264       break;
3265     }
3266
3267     case Dali::Actor::Property::SCALE:
3268     {
3269       value = GetCurrentScale();
3270       break;
3271     }
3272
3273     case Dali::Actor::Property::SCALE_X:
3274     {
3275       value = GetCurrentScale().x;
3276       break;
3277     }
3278
3279     case Dali::Actor::Property::SCALE_Y:
3280     {
3281       value = GetCurrentScale().y;
3282       break;
3283     }
3284
3285     case Dali::Actor::Property::SCALE_Z:
3286     {
3287       value = GetCurrentScale().z;
3288       break;
3289     }
3290
3291     case Dali::Actor::Property::WORLD_SCALE:
3292     {
3293       value = GetCurrentWorldScale();
3294       break;
3295     }
3296
3297     case Dali::Actor::Property::VISIBLE:
3298     {
3299       value = IsVisible();
3300       break;
3301     }
3302
3303     case Dali::Actor::Property::COLOR:
3304     {
3305       value = GetCurrentColor();
3306       break;
3307     }
3308
3309     case Dali::Actor::Property::COLOR_RED:
3310     {
3311       value = GetCurrentColor().r;
3312       break;
3313     }
3314
3315     case Dali::Actor::Property::COLOR_GREEN:
3316     {
3317       value = GetCurrentColor().g;
3318       break;
3319     }
3320
3321     case Dali::Actor::Property::COLOR_BLUE:
3322     {
3323       value = GetCurrentColor().b;
3324       break;
3325     }
3326
3327     case Dali::Actor::Property::COLOR_ALPHA:
3328     {
3329       value = GetCurrentColor().a;
3330       break;
3331     }
3332
3333     case Dali::Actor::Property::WORLD_COLOR:
3334     {
3335       value = GetCurrentWorldColor();
3336       break;
3337     }
3338
3339     case Dali::Actor::Property::WORLD_MATRIX:
3340     {
3341       value = GetCurrentWorldMatrix();
3342       break;
3343     }
3344
3345     case Dali::Actor::Property::NAME:
3346     {
3347       value = GetName();
3348       break;
3349     }
3350
3351     case Dali::Actor::Property::SENSITIVE:
3352     {
3353       value = IsSensitive();
3354       break;
3355     }
3356
3357     case Dali::Actor::Property::LEAVE_REQUIRED:
3358     {
3359       value = GetLeaveRequired();
3360       break;
3361     }
3362
3363     case Dali::Actor::Property::INHERIT_ORIENTATION:
3364     {
3365       value = IsOrientationInherited();
3366       break;
3367     }
3368
3369     case Dali::Actor::Property::INHERIT_SCALE:
3370     {
3371       value = IsScaleInherited();
3372       break;
3373     }
3374
3375     case Dali::Actor::Property::COLOR_MODE:
3376     {
3377       value = Scripting::GetColorMode( GetColorMode() );
3378       break;
3379     }
3380
3381     case Dali::Actor::Property::POSITION_INHERITANCE:
3382     {
3383       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3384       break;
3385     }
3386
3387     case Dali::Actor::Property::DRAW_MODE:
3388     {
3389       value = Scripting::GetDrawMode( GetDrawMode() );
3390       break;
3391     }
3392
3393     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3394     {
3395       value = GetSizeModeFactor();
3396       break;
3397     }
3398
3399     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3400     {
3401       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3402       break;
3403     }
3404
3405     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3406     {
3407       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3408       break;
3409     }
3410
3411     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3412     {
3413       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3414       break;
3415     }
3416
3417     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3418     {
3419       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3420       break;
3421     }
3422
3423     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3424     {
3425       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3426       break;
3427     }
3428
3429     case Dali::Actor::Property::PADDING:
3430     {
3431       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3432       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3433       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3434       break;
3435     }
3436
3437     case Dali::Actor::Property::MINIMUM_SIZE:
3438     {
3439       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3440       break;
3441     }
3442
3443     case Dali::Actor::Property::MAXIMUM_SIZE:
3444     {
3445       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3446       break;
3447     }
3448
3449     default:
3450     {
3451       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3452       break;
3453     }
3454   }
3455
3456   return value;
3457 }
3458
3459 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3460 {
3461   return mNode;
3462 }
3463
3464 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3465 {
3466   // This method should only return an object connected to the scene-graph
3467   return OnStage() ? mNode : NULL;
3468 }
3469
3470 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3471 {
3472   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3473
3474   const PropertyBase* property( NULL );
3475
3476   // This method should only return a property of an object connected to the scene-graph
3477   if( !OnStage() )
3478   {
3479     return property;
3480   }
3481
3482   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3483   {
3484     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3485     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3486
3487     property = animatable->GetSceneGraphProperty();
3488   }
3489   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3490   {
3491     CustomPropertyMetadata* custom = FindCustomProperty( index );
3492     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3493
3494     property = custom->GetSceneGraphProperty();
3495   }
3496   else if( NULL != mNode )
3497   {
3498     switch( index )
3499     {
3500       case Dali::Actor::Property::SIZE:
3501         property = &mNode->mSize;
3502         break;
3503
3504       case Dali::Actor::Property::SIZE_WIDTH:
3505         property = &mNode->mSize;
3506         break;
3507
3508       case Dali::Actor::Property::SIZE_HEIGHT:
3509         property = &mNode->mSize;
3510         break;
3511
3512       case Dali::Actor::Property::SIZE_DEPTH:
3513         property = &mNode->mSize;
3514         break;
3515
3516       case Dali::Actor::Property::POSITION:
3517         property = &mNode->mPosition;
3518         break;
3519
3520       case Dali::Actor::Property::POSITION_X:
3521         property = &mNode->mPosition;
3522         break;
3523
3524       case Dali::Actor::Property::POSITION_Y:
3525         property = &mNode->mPosition;
3526         break;
3527
3528       case Dali::Actor::Property::POSITION_Z:
3529         property = &mNode->mPosition;
3530         break;
3531
3532       case Dali::Actor::Property::ORIENTATION:
3533         property = &mNode->mOrientation;
3534         break;
3535
3536       case Dali::Actor::Property::SCALE:
3537         property = &mNode->mScale;
3538         break;
3539
3540       case Dali::Actor::Property::SCALE_X:
3541         property = &mNode->mScale;
3542         break;
3543
3544       case Dali::Actor::Property::SCALE_Y:
3545         property = &mNode->mScale;
3546         break;
3547
3548       case Dali::Actor::Property::SCALE_Z:
3549         property = &mNode->mScale;
3550         break;
3551
3552       case Dali::Actor::Property::VISIBLE:
3553         property = &mNode->mVisible;
3554         break;
3555
3556       case Dali::Actor::Property::COLOR:
3557         property = &mNode->mColor;
3558         break;
3559
3560       case Dali::Actor::Property::COLOR_RED:
3561         property = &mNode->mColor;
3562         break;
3563
3564       case Dali::Actor::Property::COLOR_GREEN:
3565         property = &mNode->mColor;
3566         break;
3567
3568       case Dali::Actor::Property::COLOR_BLUE:
3569         property = &mNode->mColor;
3570         break;
3571
3572       case Dali::Actor::Property::COLOR_ALPHA:
3573         property = &mNode->mColor;
3574         break;
3575
3576       default:
3577         break;
3578     }
3579   }
3580
3581   return property;
3582 }
3583
3584 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3585 {
3586   const PropertyInputImpl* property( NULL );
3587
3588   // This method should only return a property of an object connected to the scene-graph
3589   if( !OnStage() )
3590   {
3591     return property;
3592   }
3593
3594   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3595   {
3596     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3597     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3598
3599     property = animatable->GetSceneGraphProperty();
3600   }
3601   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3602   {
3603     CustomPropertyMetadata* custom = FindCustomProperty( index );
3604     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3605     property = custom->GetSceneGraphProperty();
3606   }
3607   else if( NULL != mNode )
3608   {
3609     switch( index )
3610     {
3611       case Dali::Actor::Property::PARENT_ORIGIN:
3612         property = &mNode->mParentOrigin;
3613         break;
3614
3615       case Dali::Actor::Property::PARENT_ORIGIN_X:
3616         property = &mNode->mParentOrigin;
3617         break;
3618
3619       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3620         property = &mNode->mParentOrigin;
3621         break;
3622
3623       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3624         property = &mNode->mParentOrigin;
3625         break;
3626
3627       case Dali::Actor::Property::ANCHOR_POINT:
3628         property = &mNode->mAnchorPoint;
3629         break;
3630
3631       case Dali::Actor::Property::ANCHOR_POINT_X:
3632         property = &mNode->mAnchorPoint;
3633         break;
3634
3635       case Dali::Actor::Property::ANCHOR_POINT_Y:
3636         property = &mNode->mAnchorPoint;
3637         break;
3638
3639       case Dali::Actor::Property::ANCHOR_POINT_Z:
3640         property = &mNode->mAnchorPoint;
3641         break;
3642
3643       case Dali::Actor::Property::SIZE:
3644         property = &mNode->mSize;
3645         break;
3646
3647       case Dali::Actor::Property::SIZE_WIDTH:
3648         property = &mNode->mSize;
3649         break;
3650
3651       case Dali::Actor::Property::SIZE_HEIGHT:
3652         property = &mNode->mSize;
3653         break;
3654
3655       case Dali::Actor::Property::SIZE_DEPTH:
3656         property = &mNode->mSize;
3657         break;
3658
3659       case Dali::Actor::Property::POSITION:
3660         property = &mNode->mPosition;
3661         break;
3662
3663       case Dali::Actor::Property::POSITION_X:
3664         property = &mNode->mPosition;
3665         break;
3666
3667       case Dali::Actor::Property::POSITION_Y:
3668         property = &mNode->mPosition;
3669         break;
3670
3671       case Dali::Actor::Property::POSITION_Z:
3672         property = &mNode->mPosition;
3673         break;
3674
3675       case Dali::Actor::Property::WORLD_POSITION:
3676         property = &mNode->mWorldPosition;
3677         break;
3678
3679       case Dali::Actor::Property::WORLD_POSITION_X:
3680         property = &mNode->mWorldPosition;
3681         break;
3682
3683       case Dali::Actor::Property::WORLD_POSITION_Y:
3684         property = &mNode->mWorldPosition;
3685         break;
3686
3687       case Dali::Actor::Property::WORLD_POSITION_Z:
3688         property = &mNode->mWorldPosition;
3689         break;
3690
3691       case Dali::Actor::Property::ORIENTATION:
3692         property = &mNode->mOrientation;
3693         break;
3694
3695       case Dali::Actor::Property::WORLD_ORIENTATION:
3696         property = &mNode->mWorldOrientation;
3697         break;
3698
3699       case Dali::Actor::Property::SCALE:
3700         property = &mNode->mScale;
3701         break;
3702
3703       case Dali::Actor::Property::SCALE_X:
3704         property = &mNode->mScale;
3705         break;
3706
3707       case Dali::Actor::Property::SCALE_Y:
3708         property = &mNode->mScale;
3709         break;
3710
3711       case Dali::Actor::Property::SCALE_Z:
3712         property = &mNode->mScale;
3713         break;
3714
3715       case Dali::Actor::Property::WORLD_SCALE:
3716         property = &mNode->mWorldScale;
3717         break;
3718
3719       case Dali::Actor::Property::VISIBLE:
3720         property = &mNode->mVisible;
3721         break;
3722
3723       case Dali::Actor::Property::COLOR:
3724         property = &mNode->mColor;
3725         break;
3726
3727       case Dali::Actor::Property::COLOR_RED:
3728         property = &mNode->mColor;
3729         break;
3730
3731       case Dali::Actor::Property::COLOR_GREEN:
3732         property = &mNode->mColor;
3733         break;
3734
3735       case Dali::Actor::Property::COLOR_BLUE:
3736         property = &mNode->mColor;
3737         break;
3738
3739       case Dali::Actor::Property::COLOR_ALPHA:
3740         property = &mNode->mColor;
3741         break;
3742
3743       case Dali::Actor::Property::WORLD_COLOR:
3744         property = &mNode->mWorldColor;
3745         break;
3746
3747       case Dali::Actor::Property::WORLD_MATRIX:
3748         property = &mNode->mWorldMatrix;
3749         break;
3750
3751       default:
3752         break;
3753     }
3754   }
3755
3756   return property;
3757 }
3758
3759 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3760 {
3761   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3762
3763   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3764   {
3765     // check whether the animatable property is registered already, if not then register one.
3766     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3767     if( animatableProperty )
3768     {
3769       componentIndex = animatableProperty->componentIndex;
3770     }
3771   }
3772   else
3773   {
3774     switch( index )
3775     {
3776       case Dali::Actor::Property::PARENT_ORIGIN_X:
3777       case Dali::Actor::Property::ANCHOR_POINT_X:
3778       case Dali::Actor::Property::SIZE_WIDTH:
3779       case Dali::Actor::Property::POSITION_X:
3780       case Dali::Actor::Property::WORLD_POSITION_X:
3781       case Dali::Actor::Property::SCALE_X:
3782       case Dali::Actor::Property::COLOR_RED:
3783       {
3784         componentIndex = 0;
3785         break;
3786       }
3787
3788       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3789       case Dali::Actor::Property::ANCHOR_POINT_Y:
3790       case Dali::Actor::Property::SIZE_HEIGHT:
3791       case Dali::Actor::Property::POSITION_Y:
3792       case Dali::Actor::Property::WORLD_POSITION_Y:
3793       case Dali::Actor::Property::SCALE_Y:
3794       case Dali::Actor::Property::COLOR_GREEN:
3795       {
3796         componentIndex = 1;
3797         break;
3798       }
3799
3800       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3801       case Dali::Actor::Property::ANCHOR_POINT_Z:
3802       case Dali::Actor::Property::SIZE_DEPTH:
3803       case Dali::Actor::Property::POSITION_Z:
3804       case Dali::Actor::Property::WORLD_POSITION_Z:
3805       case Dali::Actor::Property::SCALE_Z:
3806       case Dali::Actor::Property::COLOR_BLUE:
3807       {
3808         componentIndex = 2;
3809         break;
3810       }
3811
3812       case Dali::Actor::Property::COLOR_ALPHA:
3813       {
3814         componentIndex = 3;
3815         break;
3816       }
3817
3818       default:
3819       {
3820         // Do nothing
3821         break;
3822       }
3823     }
3824   }
3825
3826   return componentIndex;
3827 }
3828
3829 void Actor::SetParent( Actor* parent, int index )
3830 {
3831   if( parent )
3832   {
3833     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3834
3835     mParent = parent;
3836
3837     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3838          parent->OnStage() )
3839     {
3840       // Instruct each actor to create a corresponding node in the scene graph
3841       ConnectToStage( index );
3842     }
3843   }
3844   else // parent being set to NULL
3845   {
3846     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3847
3848     mParent = NULL;
3849
3850     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3851          OnStage() )
3852     {
3853       DALI_ASSERT_ALWAYS( mNode != NULL );
3854
3855       if( NULL != mNode )
3856       {
3857         // Disconnect the Node & its children from the scene-graph.
3858         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3859       }
3860
3861       // Instruct each actor to discard pointers to the scene-graph
3862       DisconnectFromStage();
3863     }
3864   }
3865 }
3866
3867 SceneGraph::Node* Actor::CreateNode() const
3868 {
3869   return Node::New();
3870 }
3871
3872 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3873 {
3874   bool done = false;
3875   Actor* actor = dynamic_cast< Actor* >( object );
3876
3877   if( actor )
3878   {
3879     if( 0 == actionName.compare( ACTION_SHOW ) )
3880     {
3881       actor->SetVisible( true );
3882       done = true;
3883     }
3884     else if( 0 == actionName.compare( ACTION_HIDE ) )
3885     {
3886       actor->SetVisible( false );
3887       done = true;
3888     }
3889   }
3890
3891   return done;
3892 }
3893
3894 void Actor::EnsureRelayoutData() const
3895 {
3896   // Assign relayout data.
3897   if( !mRelayoutData )
3898   {
3899     mRelayoutData = new RelayoutData();
3900   }
3901 }
3902
3903 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3904 {
3905   // Check if actor is dependent on parent
3906   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3907   {
3908     if( ( dimension & ( 1 << i ) ) )
3909     {
3910       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3911       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3912       {
3913         return true;
3914       }
3915     }
3916   }
3917
3918   return false;
3919 }
3920
3921 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3922 {
3923   // Check if actor is dependent on children
3924   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3925   {
3926     if( ( dimension & ( 1 << i ) ) )
3927     {
3928       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3929       switch( resizePolicy )
3930       {
3931         case ResizePolicy::FIT_TO_CHILDREN:
3932         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3933         {
3934           return true;
3935         }
3936
3937         default:
3938         {
3939           break;
3940         }
3941       }
3942     }
3943   }
3944
3945   return false;
3946 }
3947
3948 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3949 {
3950   return Actor::RelayoutDependentOnChildren( dimension );
3951 }
3952
3953 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3954 {
3955   // Check each possible dimension and see if it is dependent on the input one
3956   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3957   {
3958     if( dimension & ( 1 << i ) )
3959     {
3960       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3961     }
3962   }
3963
3964   return false;
3965 }
3966
3967 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3968 {
3969   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3970   {
3971     if( dimension & ( 1 << i ) )
3972     {
3973       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3974     }
3975   }
3976 }
3977
3978 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3979 {
3980   // If more than one dimension is requested, just return the first one found
3981   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3982   {
3983     if( ( dimension & ( 1 << i ) ) )
3984     {
3985       return mRelayoutData->negotiatedDimensions[ i ];
3986     }
3987   }
3988
3989   return 0.0f;   // Default
3990 }
3991
3992 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3993 {
3994   EnsureRelayoutData();
3995
3996   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3997   {
3998     if( dimension & ( 1 << i ) )
3999     {
4000       mRelayoutData->dimensionPadding[ i ] = padding;
4001     }
4002   }
4003 }
4004
4005 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4006 {
4007   EnsureRelayoutData();
4008
4009   // If more than one dimension is requested, just return the first one found
4010   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4011   {
4012     if( ( dimension & ( 1 << i ) ) )
4013     {
4014       return mRelayoutData->dimensionPadding[ i ];
4015     }
4016   }
4017
4018   return Vector2( 0.0f, 0.0f );   // Default
4019 }
4020
4021 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4022 {
4023   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4024   {
4025     if( dimension & ( 1 << i ) )
4026     {
4027       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4028     }
4029   }
4030 }
4031
4032 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4033 {
4034   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4035   {
4036     if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4037     {
4038       return true;
4039     }
4040   }
4041
4042   return false;
4043 }
4044
4045 float Actor::GetHeightForWidthBase( float width )
4046 {
4047   float height = 0.0f;
4048
4049   const Vector3 naturalSize = GetNaturalSize();
4050   if( naturalSize.width > 0.0f )
4051   {
4052     height = naturalSize.height * width / naturalSize.width;
4053   }
4054   else // we treat 0 as 1:1 aspect ratio
4055   {
4056     height = width;
4057   }
4058
4059   return height;
4060 }
4061
4062 float Actor::GetWidthForHeightBase( float height )
4063 {
4064   float width = 0.0f;
4065
4066   const Vector3 naturalSize = GetNaturalSize();
4067   if( naturalSize.height > 0.0f )
4068   {
4069     width = naturalSize.width * height / naturalSize.height;
4070   }
4071   else // we treat 0 as 1:1 aspect ratio
4072   {
4073     width = height;
4074   }
4075
4076   return width;
4077 }
4078
4079 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4080 {
4081   // Fill to parent, taking size mode factor into account
4082   switch( child.GetResizePolicy( dimension ) )
4083   {
4084     case ResizePolicy::FILL_TO_PARENT:
4085     {
4086       return GetLatestSize( dimension );
4087     }
4088
4089     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4090     {
4091       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4092     }
4093
4094     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4095     {
4096       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4097     }
4098
4099     default:
4100     {
4101       return GetLatestSize( dimension );
4102     }
4103   }
4104 }
4105
4106 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4107 {
4108   // Can be overridden in derived class
4109   return CalculateChildSizeBase( child, dimension );
4110 }
4111
4112 float Actor::GetHeightForWidth( float width )
4113 {
4114   // Can be overridden in derived class
4115   return GetHeightForWidthBase( width );
4116 }
4117
4118 float Actor::GetWidthForHeight( float height )
4119 {
4120   // Can be overridden in derived class
4121   return GetWidthForHeightBase( height );
4122 }
4123
4124 float Actor::GetLatestSize( Dimension::Type dimension ) const
4125 {
4126   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4127 }
4128
4129 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4130 {
4131   Vector2 padding = GetPadding( dimension );
4132
4133   return GetLatestSize( dimension ) + padding.x + padding.y;
4134 }
4135
4136 float Actor::NegotiateFromParent( Dimension::Type dimension )
4137 {
4138   Actor* parent = GetParent();
4139   if( parent )
4140   {
4141     Vector2 padding( GetPadding( dimension ) );
4142     Vector2 parentPadding( parent->GetPadding( dimension ) );
4143     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4144   }
4145
4146   return 0.0f;
4147 }
4148
4149 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4150 {
4151   float maxDimensionPoint = 0.0f;
4152
4153   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4154   {
4155     Dali::Actor child = GetChildAt( i );
4156     Actor& childImpl = GetImplementation( child );
4157
4158     if( !childImpl.RelayoutDependentOnParent( dimension ) )
4159     {
4160       // Calculate the min and max points that the children range across
4161       float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4162       float dimensionSize = childImpl.GetRelayoutSize( dimension );
4163       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4164     }
4165   }
4166
4167   return maxDimensionPoint;
4168 }
4169
4170 float Actor::GetSize( Dimension::Type dimension ) const
4171 {
4172   return GetDimensionValue( GetTargetSize(), dimension );
4173 }
4174
4175 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4176 {
4177   return GetDimensionValue( GetNaturalSize(), dimension );
4178 }
4179
4180 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4181 {
4182   switch( GetResizePolicy( dimension ) )
4183   {
4184     case ResizePolicy::USE_NATURAL_SIZE:
4185     {
4186       return GetNaturalSize( dimension );
4187     }
4188
4189     case ResizePolicy::FIXED:
4190     {
4191       return GetDimensionValue( GetPreferredSize(), dimension );
4192     }
4193
4194     case ResizePolicy::USE_ASSIGNED_SIZE:
4195     {
4196       return GetDimensionValue( maximumSize, dimension );
4197     }
4198
4199     case ResizePolicy::FILL_TO_PARENT:
4200     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4201     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4202     {
4203       return NegotiateFromParent( dimension );
4204     }
4205
4206     case ResizePolicy::FIT_TO_CHILDREN:
4207     {
4208       return NegotiateFromChildren( dimension );
4209     }
4210
4211     case ResizePolicy::DIMENSION_DEPENDENCY:
4212     {
4213       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4214
4215       // Custom rules
4216       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4217       {
4218         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4219       }
4220
4221       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4222       {
4223         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4224       }
4225
4226       break;
4227     }
4228
4229     default:
4230     {
4231       break;
4232     }
4233   }
4234
4235   return 0.0f;  // Default
4236 }
4237
4238 float Actor::ClampDimension( float size, Dimension::Type dimension )
4239 {
4240   const float minSize = GetMinimumSize( dimension );
4241   const float maxSize = GetMaximumSize( dimension );
4242
4243   return std::max( minSize, std::min( size, maxSize ) );
4244 }
4245
4246 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4247 {
4248   // Check if it needs to be negotiated
4249   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4250   {
4251     // Check that we havn't gotten into an infinite loop
4252     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4253     bool recursionFound = false;
4254     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4255     {
4256       if( *it == searchActor )
4257       {
4258         recursionFound = true;
4259         break;
4260       }
4261     }
4262
4263     if( !recursionFound )
4264     {
4265       // Record the path that we have taken
4266       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4267
4268       // Dimension dependency check
4269       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4270       {
4271         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4272
4273         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4274         {
4275           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4276         }
4277       }
4278
4279       // Parent dependency check
4280       Actor* parent = GetParent();
4281       if( parent && RelayoutDependentOnParent( dimension ) )
4282       {
4283         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4284       }
4285
4286       // Children dependency check
4287       if( RelayoutDependentOnChildren( dimension ) )
4288       {
4289         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4290         {
4291           Dali::Actor child = GetChildAt( i );
4292           Actor& childImpl = GetImplementation( child );
4293
4294           // Only relayout child first if it is not dependent on this actor
4295           if( !childImpl.RelayoutDependentOnParent( dimension ) )
4296           {
4297             childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4298           }
4299         }
4300       }
4301
4302       // For deriving classes
4303       OnCalculateRelayoutSize( dimension );
4304
4305       // All dependencies checked, calculate the size and set negotiated flag
4306       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4307
4308       SetNegotiatedDimension( newSize, dimension );
4309       SetLayoutNegotiated( true, dimension );
4310
4311       // For deriving classes
4312       OnLayoutNegotiated( newSize, dimension );
4313
4314       // This actor has been successfully processed, pop it off the recursion stack
4315       recursionStack.pop_back();
4316     }
4317     else
4318     {
4319       // TODO: Break infinite loop
4320       SetLayoutNegotiated( true, dimension );
4321     }
4322   }
4323 }
4324
4325 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4326 {
4327   // Negotiate all dimensions that require it
4328   ActorDimensionStack recursionStack;
4329
4330   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4331   {
4332     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4333
4334     // Negotiate
4335     NegotiateDimension( dimension, allocatedSize, recursionStack );
4336   }
4337 }
4338
4339 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4340 {
4341   switch( mRelayoutData->sizeSetPolicy )
4342   {
4343     case SizeScalePolicy::USE_SIZE_SET:
4344     {
4345       return size;
4346     }
4347
4348     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4349     {
4350       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4351       const Vector3 naturalSize = GetNaturalSize();
4352       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4353       {
4354         const float sizeRatio = size.width / size.height;
4355         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4356
4357         if( naturalSizeRatio < sizeRatio )
4358         {
4359           return Vector2( naturalSizeRatio * size.height, size.height );
4360         }
4361         else if( naturalSizeRatio > sizeRatio )
4362         {
4363           return Vector2( size.width, size.width / naturalSizeRatio );
4364         }
4365         else
4366         {
4367           return size;
4368         }
4369       }
4370
4371       break;
4372     }
4373
4374     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4375     {
4376       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4377       const Vector3 naturalSize = GetNaturalSize();
4378       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4379       {
4380         const float sizeRatio = size.width / size.height;
4381         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4382
4383         if( naturalSizeRatio < sizeRatio )
4384         {
4385           return Vector2( size.width, size.width / naturalSizeRatio );
4386         }
4387         else if( naturalSizeRatio > sizeRatio )
4388         {
4389           return Vector2( naturalSizeRatio * size.height, size.height );
4390         }
4391         else
4392         {
4393           return size;
4394         }
4395       }
4396     }
4397
4398     default:
4399     {
4400       break;
4401     }
4402   }
4403
4404   return size;
4405 }
4406
4407 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4408 {
4409   // Do the set actor size
4410   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4411
4412   // Adjust for size set policy
4413   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4414
4415   // Lock the flag to stop recursive relayouts on set size
4416   mRelayoutData->insideRelayout = true;
4417   SetSize( negotiatedSize );
4418   mRelayoutData->insideRelayout = false;
4419
4420   // Clear flags for all dimensions
4421   SetLayoutDirty( false );
4422
4423   // Give deriving classes a chance to respond
4424   OnRelayout( negotiatedSize, container );
4425
4426   if( !mOnRelayoutSignal.Empty() )
4427   {
4428     Dali::Actor handle( this );
4429     mOnRelayoutSignal.Emit( handle );
4430   }
4431 }
4432
4433 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4434 {
4435   // Do the negotiation
4436   NegotiateDimensions( allocatedSize );
4437
4438   // Set the actor size
4439   SetNegotiatedSize( container );
4440
4441   // Negotiate down to children
4442   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4443
4444   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4445   {
4446     Dali::Actor child = GetChildAt( i );
4447
4448     // Only relayout if required
4449     if( GetImplementation( child ).RelayoutRequired() )
4450     {
4451       container.Add( child, newBounds );
4452     }
4453   }
4454 }
4455
4456 void Actor::RelayoutRequest( Dimension::Type dimension )
4457 {
4458   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4459   if( relayoutController )
4460   {
4461     Dali::Actor self( this );
4462     relayoutController->RequestRelayout( self, dimension );
4463   }
4464 }
4465
4466 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4467 {
4468 }
4469
4470 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4471 {
4472 }
4473
4474 void Actor::SetPreferredSize( const Vector2& size )
4475 {
4476   EnsureRelayoutData();
4477
4478   if( size.width > 0.0f )
4479   {
4480     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4481   }
4482
4483   if( size.height > 0.0f )
4484   {
4485     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4486   }
4487
4488   mRelayoutData->preferredSize = size;
4489
4490   RelayoutRequest();
4491 }
4492
4493 Vector2 Actor::GetPreferredSize() const
4494 {
4495   EnsureRelayoutData();
4496
4497   return mRelayoutData->preferredSize;
4498 }
4499
4500 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4501 {
4502   EnsureRelayoutData();
4503
4504   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4505   {
4506     if( dimension & ( 1 << i ) )
4507     {
4508       mRelayoutData->minimumSize[ i ] = size;
4509     }
4510   }
4511
4512   RelayoutRequest();
4513 }
4514
4515 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4516 {
4517   EnsureRelayoutData();
4518
4519   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4520   {
4521     if( dimension & ( 1 << i ) )
4522     {
4523       return mRelayoutData->minimumSize[ i ];
4524     }
4525   }
4526
4527   return 0.0f;  // Default
4528 }
4529
4530 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4531 {
4532   EnsureRelayoutData();
4533
4534   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4535   {
4536     if( dimension & ( 1 << i ) )
4537     {
4538       mRelayoutData->maximumSize[ i ] = size;
4539     }
4540   }
4541
4542   RelayoutRequest();
4543 }
4544
4545 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4546 {
4547   EnsureRelayoutData();
4548
4549   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4550   {
4551     if( dimension & ( 1 << i ) )
4552     {
4553       return mRelayoutData->maximumSize[ i ];
4554     }
4555   }
4556
4557   return 0.0f;  // Default
4558 }
4559
4560 } // namespace Internal
4561
4562 } // namespace Dali