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