Merge "Remove std::vector from public api" into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25
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 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 )DALI_ENUM_TO_STRING( FIXED )
75 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
76 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
77 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
79 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
80 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
81 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
82 DALI_ENUM_TO_STRING_TABLE_END( Type )
83
84 } // unnamed namespace
85 } // ResizePolicy
86
87 namespace SizeScalePolicy
88 {
89 namespace
90 {
91 // Enumeration to / from string conversion tables
92 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
93 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
94 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
95 DALI_ENUM_TO_STRING_TABLE_END( Type )
96 } // unnamed namespace
97 } // SizeScalePolicy
98
99 namespace Internal
100 {
101
102 unsigned int Actor::mActorCounter = 0;
103
104 /**
105  * Struct to collect relayout variables
106  */
107 struct Actor::RelayoutData
108 {
109   RelayoutData()
110     : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
111   {
112     // Set size negotiation defaults
113     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
114     {
115       resizePolicies[ i ] = ResizePolicy::FIXED;
116       negotiatedDimensions[ i ] = 0.0f;
117       dimensionNegotiated[ i ] = false;
118       dimensionDirty[ i ] = false;
119       dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
120       dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
121       minimumSize[ i ] = 0.0f;
122       maximumSize[ i ] = FLT_MAX;
123     }
124   }
125
126   ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ];      ///< Resize policies
127
128   Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ];  ///< A list of dimension dependencies
129
130   Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ];         ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
131
132   float negotiatedDimensions[ Dimension::DIMENSION_COUNT ];       ///< Storage for when a dimension is negotiated but before set on actor
133
134   float minimumSize[ Dimension::DIMENSION_COUNT ];                ///< The minimum size an actor can be
135   float maximumSize[ Dimension::DIMENSION_COUNT ];                ///< The maximum size an actor can be
136
137   bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ];         ///< Has the dimension been negotiated
138   bool dimensionDirty[ Dimension::DIMENSION_COUNT ];              ///< Flags indicating whether the layout dimension is dirty or not
139
140   Vector3 sizeModeFactor;                              ///< Factor of size used for certain SizeModes
141
142   Vector2 preferredSize;                               ///< The preferred size of the actor
143
144   SizeScalePolicy::Type sizeSetPolicy :3;            ///< Policy to apply when setting size. Enough room for the enum
145
146   bool relayoutEnabled :1;                   ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
147   bool insideRelayout :1;                    ///< Locking flag to prevent recursive relayouts on size set
148 };
149
150 #ifdef DYNAMICS_SUPPORT
151
152 // Encapsulate actor related dynamics data
153 struct DynamicsData
154 {
155   DynamicsData( Actor* slotOwner )
156   : slotDelegate( slotOwner )
157   {
158   }
159
160   typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
161   typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
162
163   DynamicsBodyPtr body;
164   JointContainer joints;
165   ReferencedJointContainer referencedJoints;
166
167   SlotDelegate< Actor > slotDelegate;
168 };
169
170 #endif // DYNAMICS_SUPPORT
171
172 namespace // unnamed namespace
173 {
174
175 // Properties
176
177 /**
178  * We want to discourage the use of property strings (minimize string comparisons),
179  * particularly for the default properties.
180  *              Name                Type   writable animatable constraint-input  enum for index-checking
181  */
182 DALI_PROPERTY_TABLE_BEGIN
183 DALI_PROPERTY( "parent-origin",     VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
184 DALI_PROPERTY( "parent-origin-x",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
185 DALI_PROPERTY( "parent-origin-y",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
186 DALI_PROPERTY( "parent-origin-z",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
187 DALI_PROPERTY( "anchor-point",      VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
188 DALI_PROPERTY( "anchor-point-x",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
189 DALI_PROPERTY( "anchor-point-y",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
190 DALI_PROPERTY( "anchor-point-z",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
191 DALI_PROPERTY( "size",              VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
192 DALI_PROPERTY( "size-width",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
193 DALI_PROPERTY( "size-height",       FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
194 DALI_PROPERTY( "size-depth",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
195 DALI_PROPERTY( "position",          VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
196 DALI_PROPERTY( "position-x",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
197 DALI_PROPERTY( "position-y",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
198 DALI_PROPERTY( "position-z",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
199 DALI_PROPERTY( "world-position",    VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
200 DALI_PROPERTY( "world-position-x",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
201 DALI_PROPERTY( "world-position-y",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
202 DALI_PROPERTY( "world-position-z",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
203 DALI_PROPERTY( "orientation",       ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
204 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
205 DALI_PROPERTY( "scale",             VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
206 DALI_PROPERTY( "scale-x",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
207 DALI_PROPERTY( "scale-y",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
208 DALI_PROPERTY( "scale-z",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
209 DALI_PROPERTY( "world-scale",       VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
210 DALI_PROPERTY( "visible",           BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
211 DALI_PROPERTY( "color",             VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
212 DALI_PROPERTY( "color-red",         FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
213 DALI_PROPERTY( "color-green",       FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
214 DALI_PROPERTY( "color-blue",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
215 DALI_PROPERTY( "color-alpha",       FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
216 DALI_PROPERTY( "world-color",       VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
217 DALI_PROPERTY( "world-matrix",      MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
218 DALI_PROPERTY( "name",              STRING,   true,  false, false, Dali::Actor::Property::NAME )
219 DALI_PROPERTY( "sensitive",         BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
220 DALI_PROPERTY( "leave-required",    BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
221 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
222 DALI_PROPERTY( "inherit-scale",     BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
223 DALI_PROPERTY( "color-mode",        STRING,   true,  false, false, Dali::Actor::Property::COLOR_MODE )
224 DALI_PROPERTY( "position-inheritance",STRING, true,  false, false, Dali::Actor::Property::POSITION_INHERITANCE )
225 DALI_PROPERTY( "draw-mode",         STRING,   true,  false, false, Dali::Actor::Property::DRAW_MODE )
226 DALI_PROPERTY( "size-mode-factor",  VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
227 DALI_PROPERTY( "width-resize-policy",STRING,  true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
228 DALI_PROPERTY( "height-resize-policy",STRING, true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
229 DALI_PROPERTY( "size-scale-policy", STRING,   true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
230 DALI_PROPERTY( "width-for-height",  BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
231 DALI_PROPERTY( "height-for-width",  BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
232 DALI_PROPERTY( "padding",           VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
233 DALI_PROPERTY( "minimum-size",      VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
234 DALI_PROPERTY( "maximum-size",      VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
235 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
236
237 // Signals
238
239 const char* const SIGNAL_TOUCHED = "touched";
240 const char* const SIGNAL_HOVERED = "hovered";
241 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
242 const char* const SIGNAL_ON_STAGE = "on-stage";
243 const char* const SIGNAL_OFF_STAGE = "off-stage";
244
245 // Actions
246
247 const char* const ACTION_SHOW = "show";
248 const char* const ACTION_HIDE = "hide";
249
250 BaseHandle CreateActor()
251 {
252   return Dali::Actor::New();
253 }
254
255 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
256
257 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264
265 /**
266  * @brief Extract a given dimension from a Vector2
267  *
268  * @param[in] values The values to extract from
269  * @param[in] dimension The dimension to extract
270  * @return Return the value for the dimension
271  */
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
273 {
274   switch( dimension )
275   {
276     case Dimension::WIDTH:
277     {
278       return values.width;
279     }
280
281     case Dimension::HEIGHT:
282     {
283       return values.height;
284     }
285
286     default:
287     {
288       break;
289     }
290   }
291
292   return 0.0f;
293 }
294
295 /**
296  * @brief Extract a given dimension from a Vector3
297  *
298  * @param[in] values The values to extract from
299  * @param[in] dimension The dimension to extract
300  * @return Return the value for the dimension
301  */
302 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
303 {
304   return GetDimensionValue( values.GetVectorXY(), dimension );
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::FIXED;   // 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 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 // 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 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 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 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 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       SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2884       break;
2885     }
2886
2887     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2888     {
2889       SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2890       break;
2891     }
2892
2893     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2894     {
2895       SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2896       break;
2897     }
2898
2899     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2900     {
2901       if( property.Get< bool >() )
2902       {
2903         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2904       }
2905       break;
2906     }
2907
2908     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2909     {
2910       if( property.Get< bool >() )
2911       {
2912         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2913       }
2914       break;
2915     }
2916
2917     case Dali::Actor::Property::PADDING:
2918     {
2919       Vector4 padding = property.Get< Vector4 >();
2920       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2921       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2922       break;
2923     }
2924
2925     case Dali::Actor::Property::MINIMUM_SIZE:
2926     {
2927       Vector2 size = property.Get< Vector2 >();
2928       SetMinimumSize( size.x, Dimension::WIDTH );
2929       SetMinimumSize( size.y, Dimension::HEIGHT );
2930       break;
2931     }
2932
2933     case Dali::Actor::Property::MAXIMUM_SIZE:
2934     {
2935       Vector2 size = property.Get< Vector2 >();
2936       SetMaximumSize( size.x, Dimension::WIDTH );
2937       SetMaximumSize( size.y, Dimension::HEIGHT );
2938       break;
2939     }
2940
2941     default:
2942     {
2943       // this can happen in the case of a non-animatable default property so just do nothing
2944       break;
2945     }
2946   }
2947 }
2948
2949 // TODO: This method needs to be removed
2950 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2951 {
2952   switch( entry.type )
2953   {
2954     case Property::BOOLEAN:
2955     {
2956       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2957       DALI_ASSERT_DEBUG( NULL != property );
2958
2959       // property is being used in a separate thread; queue a message to set the property
2960       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2961
2962       break;
2963     }
2964
2965     case Property::INTEGER:
2966     {
2967       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2968       DALI_ASSERT_DEBUG( NULL != property );
2969
2970       // property is being used in a separate thread; queue a message to set the property
2971       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2972
2973       break;
2974     }
2975
2976     case Property::UNSIGNED_INTEGER:
2977     {
2978       const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2979       DALI_ASSERT_DEBUG( NULL != property );
2980
2981       // property is being used in a separate thread; queue a message to set the property
2982       SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2983
2984       break;
2985     }
2986
2987     case Property::FLOAT:
2988     {
2989       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2990       DALI_ASSERT_DEBUG( NULL != property );
2991
2992       // property is being used in a separate thread; queue a message to set the property
2993       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2994
2995       break;
2996     }
2997
2998     case Property::VECTOR2:
2999     {
3000       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3001       DALI_ASSERT_DEBUG( NULL != property );
3002
3003       // property is being used in a separate thread; queue a message to set the property
3004       if(entry.componentIndex == 0)
3005       {
3006         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3007       }
3008       else if(entry.componentIndex == 1)
3009       {
3010         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3011       }
3012       else
3013       {
3014         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3015       }
3016
3017       break;
3018     }
3019
3020     case Property::VECTOR3:
3021     {
3022       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3023       DALI_ASSERT_DEBUG( NULL != property );
3024
3025       // property is being used in a separate thread; queue a message to set the property
3026       if(entry.componentIndex == 0)
3027       {
3028         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3029       }
3030       else if(entry.componentIndex == 1)
3031       {
3032         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3033       }
3034       else if(entry.componentIndex == 2)
3035       {
3036         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3037       }
3038       else
3039       {
3040         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3041       }
3042
3043       break;
3044     }
3045
3046     case Property::VECTOR4:
3047     {
3048       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3049       DALI_ASSERT_DEBUG( NULL != property );
3050
3051       // property is being used in a separate thread; queue a message to set the property
3052       if(entry.componentIndex == 0)
3053       {
3054         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3055       }
3056       else if(entry.componentIndex == 1)
3057       {
3058         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3059       }
3060       else if(entry.componentIndex == 2)
3061       {
3062         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3063       }
3064       else if(entry.componentIndex == 3)
3065       {
3066         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3067       }
3068       else
3069       {
3070         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3071       }
3072
3073       break;
3074     }
3075
3076     case Property::ROTATION:
3077     {
3078       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3079       DALI_ASSERT_DEBUG( NULL != property );
3080
3081       // property is being used in a separate thread; queue a message to set the property
3082       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
3083
3084       break;
3085     }
3086
3087     case Property::MATRIX:
3088     {
3089       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3090       DALI_ASSERT_DEBUG( NULL != property );
3091
3092       // property is being used in a separate thread; queue a message to set the property
3093       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
3094
3095       break;
3096     }
3097
3098     case Property::MATRIX3:
3099     {
3100       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3101       DALI_ASSERT_DEBUG( NULL != property );
3102
3103       // property is being used in a separate thread; queue a message to set the property
3104       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
3105
3106       break;
3107     }
3108
3109     default:
3110     {
3111       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3112       break;
3113     }
3114   }
3115 }
3116
3117 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3118 {
3119   Property::Value value;
3120
3121   switch( index )
3122   {
3123     case Dali::Actor::Property::PARENT_ORIGIN:
3124     {
3125       value = GetCurrentParentOrigin();
3126       break;
3127     }
3128
3129     case Dali::Actor::Property::PARENT_ORIGIN_X:
3130     {
3131       value = GetCurrentParentOrigin().x;
3132       break;
3133     }
3134
3135     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3136     {
3137       value = GetCurrentParentOrigin().y;
3138       break;
3139     }
3140
3141     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3142     {
3143       value = GetCurrentParentOrigin().z;
3144       break;
3145     }
3146
3147     case Dali::Actor::Property::ANCHOR_POINT:
3148     {
3149       value = GetCurrentAnchorPoint();
3150       break;
3151     }
3152
3153     case Dali::Actor::Property::ANCHOR_POINT_X:
3154     {
3155       value = GetCurrentAnchorPoint().x;
3156       break;
3157     }
3158
3159     case Dali::Actor::Property::ANCHOR_POINT_Y:
3160     {
3161       value = GetCurrentAnchorPoint().y;
3162       break;
3163     }
3164
3165     case Dali::Actor::Property::ANCHOR_POINT_Z:
3166     {
3167       value = GetCurrentAnchorPoint().z;
3168       break;
3169     }
3170
3171     case Dali::Actor::Property::SIZE:
3172     {
3173       value = GetCurrentSize();
3174       break;
3175     }
3176
3177     case Dali::Actor::Property::SIZE_WIDTH:
3178     {
3179       value = GetCurrentSize().width;
3180       break;
3181     }
3182
3183     case Dali::Actor::Property::SIZE_HEIGHT:
3184     {
3185       value = GetCurrentSize().height;
3186       break;
3187     }
3188
3189     case Dali::Actor::Property::SIZE_DEPTH:
3190     {
3191       value = GetCurrentSize().depth;
3192       break;
3193     }
3194
3195     case Dali::Actor::Property::POSITION:
3196     {
3197       value = GetCurrentPosition();
3198       break;
3199     }
3200
3201     case Dali::Actor::Property::POSITION_X:
3202     {
3203       value = GetCurrentPosition().x;
3204       break;
3205     }
3206
3207     case Dali::Actor::Property::POSITION_Y:
3208     {
3209       value = GetCurrentPosition().y;
3210       break;
3211     }
3212
3213     case Dali::Actor::Property::POSITION_Z:
3214     {
3215       value = GetCurrentPosition().z;
3216       break;
3217     }
3218
3219     case Dali::Actor::Property::WORLD_POSITION:
3220     {
3221       value = GetCurrentWorldPosition();
3222       break;
3223     }
3224
3225     case Dali::Actor::Property::WORLD_POSITION_X:
3226     {
3227       value = GetCurrentWorldPosition().x;
3228       break;
3229     }
3230
3231     case Dali::Actor::Property::WORLD_POSITION_Y:
3232     {
3233       value = GetCurrentWorldPosition().y;
3234       break;
3235     }
3236
3237     case Dali::Actor::Property::WORLD_POSITION_Z:
3238     {
3239       value = GetCurrentWorldPosition().z;
3240       break;
3241     }
3242
3243     case Dali::Actor::Property::ORIENTATION:
3244     {
3245       value = GetCurrentOrientation();
3246       break;
3247     }
3248
3249     case Dali::Actor::Property::WORLD_ORIENTATION:
3250     {
3251       value = GetCurrentWorldOrientation();
3252       break;
3253     }
3254
3255     case Dali::Actor::Property::SCALE:
3256     {
3257       value = GetCurrentScale();
3258       break;
3259     }
3260
3261     case Dali::Actor::Property::SCALE_X:
3262     {
3263       value = GetCurrentScale().x;
3264       break;
3265     }
3266
3267     case Dali::Actor::Property::SCALE_Y:
3268     {
3269       value = GetCurrentScale().y;
3270       break;
3271     }
3272
3273     case Dali::Actor::Property::SCALE_Z:
3274     {
3275       value = GetCurrentScale().z;
3276       break;
3277     }
3278
3279     case Dali::Actor::Property::WORLD_SCALE:
3280     {
3281       value = GetCurrentWorldScale();
3282       break;
3283     }
3284
3285     case Dali::Actor::Property::VISIBLE:
3286     {
3287       value = IsVisible();
3288       break;
3289     }
3290
3291     case Dali::Actor::Property::COLOR:
3292     {
3293       value = GetCurrentColor();
3294       break;
3295     }
3296
3297     case Dali::Actor::Property::COLOR_RED:
3298     {
3299       value = GetCurrentColor().r;
3300       break;
3301     }
3302
3303     case Dali::Actor::Property::COLOR_GREEN:
3304     {
3305       value = GetCurrentColor().g;
3306       break;
3307     }
3308
3309     case Dali::Actor::Property::COLOR_BLUE:
3310     {
3311       value = GetCurrentColor().b;
3312       break;
3313     }
3314
3315     case Dali::Actor::Property::COLOR_ALPHA:
3316     {
3317       value = GetCurrentColor().a;
3318       break;
3319     }
3320
3321     case Dali::Actor::Property::WORLD_COLOR:
3322     {
3323       value = GetCurrentWorldColor();
3324       break;
3325     }
3326
3327     case Dali::Actor::Property::WORLD_MATRIX:
3328     {
3329       value = GetCurrentWorldMatrix();
3330       break;
3331     }
3332
3333     case Dali::Actor::Property::NAME:
3334     {
3335       value = GetName();
3336       break;
3337     }
3338
3339     case Dali::Actor::Property::SENSITIVE:
3340     {
3341       value = IsSensitive();
3342       break;
3343     }
3344
3345     case Dali::Actor::Property::LEAVE_REQUIRED:
3346     {
3347       value = GetLeaveRequired();
3348       break;
3349     }
3350
3351     case Dali::Actor::Property::INHERIT_ORIENTATION:
3352     {
3353       value = IsOrientationInherited();
3354       break;
3355     }
3356
3357     case Dali::Actor::Property::INHERIT_SCALE:
3358     {
3359       value = IsScaleInherited();
3360       break;
3361     }
3362
3363     case Dali::Actor::Property::COLOR_MODE:
3364     {
3365       value = Scripting::GetColorMode( GetColorMode() );
3366       break;
3367     }
3368
3369     case Dali::Actor::Property::POSITION_INHERITANCE:
3370     {
3371       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3372       break;
3373     }
3374
3375     case Dali::Actor::Property::DRAW_MODE:
3376     {
3377       value = Scripting::GetDrawMode( GetDrawMode() );
3378       break;
3379     }
3380
3381     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3382     {
3383       value = GetSizeModeFactor();
3384       break;
3385     }
3386
3387     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3388     {
3389       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3390       break;
3391     }
3392
3393     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3394     {
3395       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3396       break;
3397     }
3398
3399     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3400     {
3401       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3402       break;
3403     }
3404
3405     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3406     {
3407       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3408       break;
3409     }
3410
3411     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3412     {
3413       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3414       break;
3415     }
3416
3417     case Dali::Actor::Property::PADDING:
3418     {
3419       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3420       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3421       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3422       break;
3423     }
3424
3425     case Dali::Actor::Property::MINIMUM_SIZE:
3426     {
3427       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3428       break;
3429     }
3430
3431     case Dali::Actor::Property::MAXIMUM_SIZE:
3432     {
3433       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3434       break;
3435     }
3436
3437     default:
3438     {
3439       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3440       break;
3441     }
3442   }
3443
3444   return value;
3445 }
3446
3447 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3448 {
3449   return mNode;
3450 }
3451
3452 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3453 {
3454   // This method should only return an object connected to the scene-graph
3455   return OnStage() ? mNode : NULL;
3456 }
3457
3458 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3459 {
3460   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3461
3462   const PropertyBase* property( NULL );
3463
3464   // This method should only return a property of an object connected to the scene-graph
3465   if( !OnStage() )
3466   {
3467     return property;
3468   }
3469
3470   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3471   {
3472     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3473     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3474
3475     property = animatable->GetSceneGraphProperty();
3476   }
3477   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3478   {
3479     CustomPropertyMetadata* custom = FindCustomProperty( index );
3480     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3481
3482     property = custom->GetSceneGraphProperty();
3483   }
3484   else if( NULL != mNode )
3485   {
3486     switch( index )
3487     {
3488       case Dali::Actor::Property::SIZE:
3489         property = &mNode->mSize;
3490         break;
3491
3492       case Dali::Actor::Property::SIZE_WIDTH:
3493         property = &mNode->mSize;
3494         break;
3495
3496       case Dali::Actor::Property::SIZE_HEIGHT:
3497         property = &mNode->mSize;
3498         break;
3499
3500       case Dali::Actor::Property::SIZE_DEPTH:
3501         property = &mNode->mSize;
3502         break;
3503
3504       case Dali::Actor::Property::POSITION:
3505         property = &mNode->mPosition;
3506         break;
3507
3508       case Dali::Actor::Property::POSITION_X:
3509         property = &mNode->mPosition;
3510         break;
3511
3512       case Dali::Actor::Property::POSITION_Y:
3513         property = &mNode->mPosition;
3514         break;
3515
3516       case Dali::Actor::Property::POSITION_Z:
3517         property = &mNode->mPosition;
3518         break;
3519
3520       case Dali::Actor::Property::ORIENTATION:
3521         property = &mNode->mOrientation;
3522         break;
3523
3524       case Dali::Actor::Property::SCALE:
3525         property = &mNode->mScale;
3526         break;
3527
3528       case Dali::Actor::Property::SCALE_X:
3529         property = &mNode->mScale;
3530         break;
3531
3532       case Dali::Actor::Property::SCALE_Y:
3533         property = &mNode->mScale;
3534         break;
3535
3536       case Dali::Actor::Property::SCALE_Z:
3537         property = &mNode->mScale;
3538         break;
3539
3540       case Dali::Actor::Property::VISIBLE:
3541         property = &mNode->mVisible;
3542         break;
3543
3544       case Dali::Actor::Property::COLOR:
3545         property = &mNode->mColor;
3546         break;
3547
3548       case Dali::Actor::Property::COLOR_RED:
3549         property = &mNode->mColor;
3550         break;
3551
3552       case Dali::Actor::Property::COLOR_GREEN:
3553         property = &mNode->mColor;
3554         break;
3555
3556       case Dali::Actor::Property::COLOR_BLUE:
3557         property = &mNode->mColor;
3558         break;
3559
3560       case Dali::Actor::Property::COLOR_ALPHA:
3561         property = &mNode->mColor;
3562         break;
3563
3564       default:
3565         break;
3566     }
3567   }
3568
3569   return property;
3570 }
3571
3572 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3573 {
3574   const PropertyInputImpl* property( NULL );
3575
3576   // This method should only return a property of an object connected to the scene-graph
3577   if( !OnStage() )
3578   {
3579     return property;
3580   }
3581
3582   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3583   {
3584     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3585     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3586
3587     property = animatable->GetSceneGraphProperty();
3588   }
3589   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3590   {
3591     CustomPropertyMetadata* custom = FindCustomProperty( index );
3592     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3593     property = custom->GetSceneGraphProperty();
3594   }
3595   else if( NULL != mNode )
3596   {
3597     switch( index )
3598     {
3599       case Dali::Actor::Property::PARENT_ORIGIN:
3600         property = &mNode->mParentOrigin;
3601         break;
3602
3603       case Dali::Actor::Property::PARENT_ORIGIN_X:
3604         property = &mNode->mParentOrigin;
3605         break;
3606
3607       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3608         property = &mNode->mParentOrigin;
3609         break;
3610
3611       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3612         property = &mNode->mParentOrigin;
3613         break;
3614
3615       case Dali::Actor::Property::ANCHOR_POINT:
3616         property = &mNode->mAnchorPoint;
3617         break;
3618
3619       case Dali::Actor::Property::ANCHOR_POINT_X:
3620         property = &mNode->mAnchorPoint;
3621         break;
3622
3623       case Dali::Actor::Property::ANCHOR_POINT_Y:
3624         property = &mNode->mAnchorPoint;
3625         break;
3626
3627       case Dali::Actor::Property::ANCHOR_POINT_Z:
3628         property = &mNode->mAnchorPoint;
3629         break;
3630
3631       case Dali::Actor::Property::SIZE:
3632         property = &mNode->mSize;
3633         break;
3634
3635       case Dali::Actor::Property::SIZE_WIDTH:
3636         property = &mNode->mSize;
3637         break;
3638
3639       case Dali::Actor::Property::SIZE_HEIGHT:
3640         property = &mNode->mSize;
3641         break;
3642
3643       case Dali::Actor::Property::SIZE_DEPTH:
3644         property = &mNode->mSize;
3645         break;
3646
3647       case Dali::Actor::Property::POSITION:
3648         property = &mNode->mPosition;
3649         break;
3650
3651       case Dali::Actor::Property::POSITION_X:
3652         property = &mNode->mPosition;
3653         break;
3654
3655       case Dali::Actor::Property::POSITION_Y:
3656         property = &mNode->mPosition;
3657         break;
3658
3659       case Dali::Actor::Property::POSITION_Z:
3660         property = &mNode->mPosition;
3661         break;
3662
3663       case Dali::Actor::Property::WORLD_POSITION:
3664         property = &mNode->mWorldPosition;
3665         break;
3666
3667       case Dali::Actor::Property::WORLD_POSITION_X:
3668         property = &mNode->mWorldPosition;
3669         break;
3670
3671       case Dali::Actor::Property::WORLD_POSITION_Y:
3672         property = &mNode->mWorldPosition;
3673         break;
3674
3675       case Dali::Actor::Property::WORLD_POSITION_Z:
3676         property = &mNode->mWorldPosition;
3677         break;
3678
3679       case Dali::Actor::Property::ORIENTATION:
3680         property = &mNode->mOrientation;
3681         break;
3682
3683       case Dali::Actor::Property::WORLD_ORIENTATION:
3684         property = &mNode->mWorldOrientation;
3685         break;
3686
3687       case Dali::Actor::Property::SCALE:
3688         property = &mNode->mScale;
3689         break;
3690
3691       case Dali::Actor::Property::SCALE_X:
3692         property = &mNode->mScale;
3693         break;
3694
3695       case Dali::Actor::Property::SCALE_Y:
3696         property = &mNode->mScale;
3697         break;
3698
3699       case Dali::Actor::Property::SCALE_Z:
3700         property = &mNode->mScale;
3701         break;
3702
3703       case Dali::Actor::Property::WORLD_SCALE:
3704         property = &mNode->mWorldScale;
3705         break;
3706
3707       case Dali::Actor::Property::VISIBLE:
3708         property = &mNode->mVisible;
3709         break;
3710
3711       case Dali::Actor::Property::COLOR:
3712         property = &mNode->mColor;
3713         break;
3714
3715       case Dali::Actor::Property::COLOR_RED:
3716         property = &mNode->mColor;
3717         break;
3718
3719       case Dali::Actor::Property::COLOR_GREEN:
3720         property = &mNode->mColor;
3721         break;
3722
3723       case Dali::Actor::Property::COLOR_BLUE:
3724         property = &mNode->mColor;
3725         break;
3726
3727       case Dali::Actor::Property::COLOR_ALPHA:
3728         property = &mNode->mColor;
3729         break;
3730
3731       case Dali::Actor::Property::WORLD_COLOR:
3732         property = &mNode->mWorldColor;
3733         break;
3734
3735       case Dali::Actor::Property::WORLD_MATRIX:
3736         property = &mNode->mWorldMatrix;
3737         break;
3738
3739       default:
3740         break;
3741     }
3742   }
3743
3744   return property;
3745 }
3746
3747 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3748 {
3749   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3750
3751   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3752   {
3753     // check whether the animatable property is registered already, if not then register one.
3754     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3755     if( animatableProperty )
3756     {
3757       componentIndex = animatableProperty->componentIndex;
3758     }
3759   }
3760   else
3761   {
3762     switch( index )
3763     {
3764       case Dali::Actor::Property::PARENT_ORIGIN_X:
3765       case Dali::Actor::Property::ANCHOR_POINT_X:
3766       case Dali::Actor::Property::SIZE_WIDTH:
3767       case Dali::Actor::Property::POSITION_X:
3768       case Dali::Actor::Property::WORLD_POSITION_X:
3769       case Dali::Actor::Property::SCALE_X:
3770       case Dali::Actor::Property::COLOR_RED:
3771       {
3772         componentIndex = 0;
3773         break;
3774       }
3775
3776       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3777       case Dali::Actor::Property::ANCHOR_POINT_Y:
3778       case Dali::Actor::Property::SIZE_HEIGHT:
3779       case Dali::Actor::Property::POSITION_Y:
3780       case Dali::Actor::Property::WORLD_POSITION_Y:
3781       case Dali::Actor::Property::SCALE_Y:
3782       case Dali::Actor::Property::COLOR_GREEN:
3783       {
3784         componentIndex = 1;
3785         break;
3786       }
3787
3788       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3789       case Dali::Actor::Property::ANCHOR_POINT_Z:
3790       case Dali::Actor::Property::SIZE_DEPTH:
3791       case Dali::Actor::Property::POSITION_Z:
3792       case Dali::Actor::Property::WORLD_POSITION_Z:
3793       case Dali::Actor::Property::SCALE_Z:
3794       case Dali::Actor::Property::COLOR_BLUE:
3795       {
3796         componentIndex = 2;
3797         break;
3798       }
3799
3800       case Dali::Actor::Property::COLOR_ALPHA:
3801       {
3802         componentIndex = 3;
3803         break;
3804       }
3805
3806       default:
3807       {
3808         // Do nothing
3809         break;
3810       }
3811     }
3812   }
3813
3814   return componentIndex;
3815 }
3816
3817 void Actor::SetParent( Actor* parent, int index )
3818 {
3819   if( parent )
3820   {
3821     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3822
3823     mParent = parent;
3824
3825     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3826          parent->OnStage() )
3827     {
3828       // Instruct each actor to create a corresponding node in the scene graph
3829       ConnectToStage( index );
3830     }
3831   }
3832   else // parent being set to NULL
3833   {
3834     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3835
3836     mParent = NULL;
3837
3838     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3839          OnStage() )
3840     {
3841       DALI_ASSERT_ALWAYS( mNode != NULL );
3842
3843       if( NULL != mNode )
3844       {
3845         // Disconnect the Node & its children from the scene-graph.
3846         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3847       }
3848
3849       // Instruct each actor to discard pointers to the scene-graph
3850       DisconnectFromStage();
3851     }
3852   }
3853 }
3854
3855 SceneGraph::Node* Actor::CreateNode() const
3856 {
3857   return Node::New();
3858 }
3859
3860 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3861 {
3862   bool done = false;
3863   Actor* actor = dynamic_cast< Actor* >( object );
3864
3865   if( actor )
3866   {
3867     if( 0 == actionName.compare( ACTION_SHOW ) )
3868     {
3869       actor->SetVisible( true );
3870       done = true;
3871     }
3872     else if( 0 == actionName.compare( ACTION_HIDE ) )
3873     {
3874       actor->SetVisible( false );
3875       done = true;
3876     }
3877   }
3878
3879   return done;
3880 }
3881
3882 void Actor::EnsureRelayoutData() const
3883 {
3884   // Assign relayout data.
3885   if( !mRelayoutData )
3886   {
3887     mRelayoutData = new RelayoutData();
3888   }
3889 }
3890
3891 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3892 {
3893   // Check if actor is dependent on parent
3894   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3895   {
3896     if( ( dimension & ( 1 << i ) ) )
3897     {
3898       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3899       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3900       {
3901         return true;
3902       }
3903     }
3904   }
3905
3906   return false;
3907 }
3908
3909 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3910 {
3911   // Check if actor is dependent on children
3912   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3913   {
3914     if( ( dimension & ( 1 << i ) ) )
3915     {
3916       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3917       switch( resizePolicy )
3918       {
3919         case ResizePolicy::FIT_TO_CHILDREN:
3920         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3921         {
3922           return true;
3923         }
3924
3925         default:
3926         {
3927           break;
3928         }
3929       }
3930     }
3931   }
3932
3933   return false;
3934 }
3935
3936 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3937 {
3938   return Actor::RelayoutDependentOnChildren( dimension );
3939 }
3940
3941 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3942 {
3943   // Check each possible dimension and see if it is dependent on the input one
3944   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3945   {
3946     if( dimension & ( 1 << i ) )
3947     {
3948       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3949     }
3950   }
3951
3952   return false;
3953 }
3954
3955 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3956 {
3957   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3958   {
3959     if( dimension & ( 1 << i ) )
3960     {
3961       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3962     }
3963   }
3964 }
3965
3966 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3967 {
3968   // If more than one dimension is requested, just return the first one found
3969   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3970   {
3971     if( ( dimension & ( 1 << i ) ) )
3972     {
3973       return mRelayoutData->negotiatedDimensions[ i ];
3974     }
3975   }
3976
3977   return 0.0f;   // Default
3978 }
3979
3980 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3981 {
3982   EnsureRelayoutData();
3983
3984   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3985   {
3986     if( dimension & ( 1 << i ) )
3987     {
3988       mRelayoutData->dimensionPadding[ i ] = padding;
3989     }
3990   }
3991 }
3992
3993 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3994 {
3995   EnsureRelayoutData();
3996
3997   // If more than one dimension is requested, just return the first one found
3998   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3999   {
4000     if( ( dimension & ( 1 << i ) ) )
4001     {
4002       return mRelayoutData->dimensionPadding[ i ];
4003     }
4004   }
4005
4006   return Vector2( 0.0f, 0.0f );   // Default
4007 }
4008
4009 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4010 {
4011   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4012   {
4013     if( dimension & ( 1 << i ) )
4014     {
4015       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4016     }
4017   }
4018 }
4019
4020 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4021 {
4022   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4023   {
4024     if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4025     {
4026       return true;
4027     }
4028   }
4029
4030   return false;
4031 }
4032
4033 float Actor::GetHeightForWidthBase( float width )
4034 {
4035   float height = 0.0f;
4036
4037   const Vector3 naturalSize = GetNaturalSize();
4038   if( naturalSize.width > 0.0f )
4039   {
4040     height = naturalSize.height * width / naturalSize.width;
4041   }
4042   else // we treat 0 as 1:1 aspect ratio
4043   {
4044     height = width;
4045   }
4046
4047   return height;
4048 }
4049
4050 float Actor::GetWidthForHeightBase( float height )
4051 {
4052   float width = 0.0f;
4053
4054   const Vector3 naturalSize = GetNaturalSize();
4055   if( naturalSize.height > 0.0f )
4056   {
4057     width = naturalSize.width * height / naturalSize.height;
4058   }
4059   else // we treat 0 as 1:1 aspect ratio
4060   {
4061     width = height;
4062   }
4063
4064   return width;
4065 }
4066
4067 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4068 {
4069   // Fill to parent, taking size mode factor into account
4070   switch( child.GetResizePolicy( dimension ) )
4071   {
4072     case ResizePolicy::FILL_TO_PARENT:
4073     {
4074       return GetLatestSize( dimension );
4075     }
4076
4077     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4078     {
4079       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4080     }
4081
4082     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4083     {
4084       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4085     }
4086
4087     default:
4088     {
4089       return GetLatestSize( dimension );
4090     }
4091   }
4092 }
4093
4094 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4095 {
4096   // Can be overridden in derived class
4097   return CalculateChildSizeBase( child, dimension );
4098 }
4099
4100 float Actor::GetHeightForWidth( float width )
4101 {
4102   // Can be overridden in derived class
4103   return GetHeightForWidthBase( width );
4104 }
4105
4106 float Actor::GetWidthForHeight( float height )
4107 {
4108   // Can be overridden in derived class
4109   return GetWidthForHeightBase( height );
4110 }
4111
4112 float Actor::GetLatestSize( Dimension::Type dimension ) const
4113 {
4114   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4115 }
4116
4117 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4118 {
4119   Vector2 padding = GetPadding( dimension );
4120
4121   return GetLatestSize( dimension ) + padding.x + padding.y;
4122 }
4123
4124 float Actor::NegotiateFromParent( Dimension::Type dimension )
4125 {
4126   Actor* parent = GetParent();
4127   if( parent )
4128   {
4129     Vector2 padding( GetPadding( dimension ) );
4130     Vector2 parentPadding( parent->GetPadding( dimension ) );
4131     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4132   }
4133
4134   return 0.0f;
4135 }
4136
4137 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4138 {
4139   float maxDimensionPoint = 0.0f;
4140
4141   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4142   {
4143     Dali::Actor child = GetChildAt( i );
4144     Actor& childImpl = GetImplementation( child );
4145
4146     if( !childImpl.RelayoutDependentOnParent( dimension ) )
4147     {
4148       // Calculate the min and max points that the children range across
4149       float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4150       float dimensionSize = childImpl.GetRelayoutSize( dimension );
4151       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4152     }
4153   }
4154
4155   return maxDimensionPoint;
4156 }
4157
4158 float Actor::GetSize( Dimension::Type dimension ) const
4159 {
4160   return GetDimensionValue( GetTargetSize(), dimension );
4161 }
4162
4163 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4164 {
4165   return GetDimensionValue( GetNaturalSize(), dimension );
4166 }
4167
4168 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4169 {
4170   switch( GetResizePolicy( dimension ) )
4171   {
4172     case ResizePolicy::USE_NATURAL_SIZE:
4173     {
4174       return GetNaturalSize( dimension );
4175     }
4176
4177     case ResizePolicy::FIXED:
4178     {
4179       return GetDimensionValue( GetPreferredSize(), dimension );
4180     }
4181
4182     case ResizePolicy::USE_ASSIGNED_SIZE:
4183     {
4184       return GetDimensionValue( maximumSize, dimension );
4185     }
4186
4187     case ResizePolicy::FILL_TO_PARENT:
4188     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4189     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4190     {
4191       return NegotiateFromParent( dimension );
4192     }
4193
4194     case ResizePolicy::FIT_TO_CHILDREN:
4195     {
4196       return NegotiateFromChildren( dimension );
4197     }
4198
4199     case ResizePolicy::DIMENSION_DEPENDENCY:
4200     {
4201       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4202
4203       // Custom rules
4204       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4205       {
4206         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4207       }
4208
4209       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4210       {
4211         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4212       }
4213
4214       break;
4215     }
4216
4217     default:
4218     {
4219       break;
4220     }
4221   }
4222
4223   return 0.0f;  // Default
4224 }
4225
4226 float Actor::ClampDimension( float size, Dimension::Type dimension )
4227 {
4228   const float minSize = GetMinimumSize( dimension );
4229   const float maxSize = GetMaximumSize( dimension );
4230
4231   return std::max( minSize, std::min( size, maxSize ) );
4232 }
4233
4234 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4235 {
4236   // Check if it needs to be negotiated
4237   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4238   {
4239     // Check that we havn't gotten into an infinite loop
4240     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4241     bool recursionFound = false;
4242     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4243     {
4244       if( *it == searchActor )
4245       {
4246         recursionFound = true;
4247         break;
4248       }
4249     }
4250
4251     if( !recursionFound )
4252     {
4253       // Record the path that we have taken
4254       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4255
4256       // Dimension dependency check
4257       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4258       {
4259         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4260
4261         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4262         {
4263           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4264         }
4265       }
4266
4267       // Parent dependency check
4268       Actor* parent = GetParent();
4269       if( parent && RelayoutDependentOnParent( dimension ) )
4270       {
4271         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4272       }
4273
4274       // Children dependency check
4275       if( RelayoutDependentOnChildren( dimension ) )
4276       {
4277         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4278         {
4279           Dali::Actor child = GetChildAt( i );
4280           Actor& childImpl = GetImplementation( child );
4281
4282           // Only relayout child first if it is not dependent on this actor
4283           if( !childImpl.RelayoutDependentOnParent( dimension ) )
4284           {
4285             childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4286           }
4287         }
4288       }
4289
4290       // For deriving classes
4291       OnCalculateRelayoutSize( dimension );
4292
4293       // All dependencies checked, calculate the size and set negotiated flag
4294       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4295
4296       SetNegotiatedDimension( newSize, dimension );
4297       SetLayoutNegotiated( true, dimension );
4298
4299       // For deriving classes
4300       OnLayoutNegotiated( newSize, dimension );
4301
4302       // This actor has been successfully processed, pop it off the recursion stack
4303       recursionStack.pop_back();
4304     }
4305     else
4306     {
4307       // TODO: Break infinite loop
4308       SetLayoutNegotiated( true, dimension );
4309     }
4310   }
4311 }
4312
4313 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4314 {
4315   // Negotiate all dimensions that require it
4316   ActorDimensionStack recursionStack;
4317
4318   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4319   {
4320     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4321
4322     // Negotiate
4323     NegotiateDimension( dimension, allocatedSize, recursionStack );
4324   }
4325 }
4326
4327 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4328 {
4329   switch( mRelayoutData->sizeSetPolicy )
4330   {
4331     case SizeScalePolicy::USE_SIZE_SET:
4332     {
4333       return size;
4334     }
4335
4336     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4337     {
4338       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4339       const Vector3 naturalSize = GetNaturalSize();
4340       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4341       {
4342         const float sizeRatio = size.width / size.height;
4343         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4344
4345         if( naturalSizeRatio < sizeRatio )
4346         {
4347           return Vector2( naturalSizeRatio * size.height, size.height );
4348         }
4349         else if( naturalSizeRatio > sizeRatio )
4350         {
4351           return Vector2( size.width, size.width / naturalSizeRatio );
4352         }
4353         else
4354         {
4355           return size;
4356         }
4357       }
4358
4359       break;
4360     }
4361
4362     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4363     {
4364       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4365       const Vector3 naturalSize = GetNaturalSize();
4366       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4367       {
4368         const float sizeRatio = size.width / size.height;
4369         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4370
4371         if( naturalSizeRatio < sizeRatio )
4372         {
4373           return Vector2( size.width, size.width / naturalSizeRatio );
4374         }
4375         else if( naturalSizeRatio > sizeRatio )
4376         {
4377           return Vector2( naturalSizeRatio * size.height, size.height );
4378         }
4379         else
4380         {
4381           return size;
4382         }
4383       }
4384     }
4385
4386     default:
4387     {
4388       break;
4389     }
4390   }
4391
4392   return size;
4393 }
4394
4395 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4396 {
4397   // Do the set actor size
4398   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4399
4400   // Adjust for size set policy
4401   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4402
4403   // Lock the flag to stop recursive relayouts on set size
4404   mRelayoutData->insideRelayout = true;
4405   SetSize( negotiatedSize );
4406   mRelayoutData->insideRelayout = false;
4407
4408   // Clear flags for all dimensions
4409   SetLayoutDirty( false );
4410
4411   // Give deriving classes a chance to respond
4412   OnRelayout( negotiatedSize, container );
4413
4414   if( !mOnRelayoutSignal.Empty() )
4415   {
4416     Dali::Actor handle( this );
4417     mOnRelayoutSignal.Emit( handle );
4418   }
4419 }
4420
4421 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4422 {
4423   // Do the negotiation
4424   NegotiateDimensions( allocatedSize );
4425
4426   // Set the actor size
4427   SetNegotiatedSize( container );
4428
4429   // Negotiate down to children
4430   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4431
4432   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4433   {
4434     Dali::Actor child = GetChildAt( i );
4435
4436     // Only relayout if required
4437     if( GetImplementation( child ).RelayoutRequired() )
4438     {
4439       container.Add( child, newBounds );
4440     }
4441   }
4442 }
4443
4444 void Actor::RelayoutRequest( Dimension::Type dimension )
4445 {
4446   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4447   if( relayoutController )
4448   {
4449     Dali::Actor self( this );
4450     relayoutController->RequestRelayout( self, dimension );
4451   }
4452 }
4453
4454 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4455 {
4456 }
4457
4458 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4459 {
4460 }
4461
4462 void Actor::SetPreferredSize( const Vector2& size )
4463 {
4464   EnsureRelayoutData();
4465
4466   if( size.width > 0.0f )
4467   {
4468     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4469   }
4470
4471   if( size.height > 0.0f )
4472   {
4473     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4474   }
4475
4476   mRelayoutData->preferredSize = size;
4477
4478   RelayoutRequest();
4479 }
4480
4481 Vector2 Actor::GetPreferredSize() const
4482 {
4483   EnsureRelayoutData();
4484
4485   return mRelayoutData->preferredSize;
4486 }
4487
4488 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4489 {
4490   EnsureRelayoutData();
4491
4492   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4493   {
4494     if( dimension & ( 1 << i ) )
4495     {
4496       mRelayoutData->minimumSize[ i ] = size;
4497     }
4498   }
4499
4500   RelayoutRequest();
4501 }
4502
4503 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4504 {
4505   EnsureRelayoutData();
4506
4507   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4508   {
4509     if( dimension & ( 1 << i ) )
4510     {
4511       return mRelayoutData->minimumSize[ i ];
4512     }
4513   }
4514
4515   return 0.0f;  // Default
4516 }
4517
4518 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4519 {
4520   EnsureRelayoutData();
4521
4522   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4523   {
4524     if( dimension & ( 1 << i ) )
4525     {
4526       mRelayoutData->maximumSize[ i ] = size;
4527     }
4528   }
4529
4530   RelayoutRequest();
4531 }
4532
4533 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4534 {
4535   EnsureRelayoutData();
4536
4537   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4538   {
4539     if( dimension & ( 1 << i ) )
4540     {
4541       return mRelayoutData->maximumSize[ i ];
4542     }
4543   }
4544
4545   return 0.0f;  // Default
4546 }
4547
4548 } // namespace Internal
4549
4550 } // namespace Dali