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