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