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