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