Merge "Remove Node::ResolveVisibilty()" 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( const 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   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1883   mIsOnStage( false ),
1884   mSensitive( true ),
1885   mLeaveRequired( false ),
1886   mKeyboardFocusable( false ),
1887   mDerivedRequiresTouch( false ),
1888   mDerivedRequiresHover( false ),
1889   mDerivedRequiresWheelEvent( false ),
1890   mOnStageSignalled( false ),
1891   mInsideOnSizeSet( false ),
1892   mInheritOrientation( true ),
1893   mInheritScale( true ),
1894   mDrawMode( DrawMode::NORMAL ),
1895   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1896   mColorMode( Node::DEFAULT_COLOR_MODE )
1897 {
1898 }
1899
1900 void Actor::Initialize()
1901 {
1902   // Node creation
1903   SceneGraph::Node* node = CreateNode();
1904
1905   AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1906   mNode = node; // Keep raw-pointer to Node
1907
1908   OnInitialize();
1909
1910   GetEventThreadServices().RegisterObject( this );
1911 }
1912
1913 Actor::~Actor()
1914 {
1915   // Remove mParent pointers from children even if we're destroying core,
1916   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1917   if( mChildren )
1918   {
1919     ActorConstIter endIter = mChildren->end();
1920     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1921     {
1922       (*iter)->SetParent( NULL );
1923     }
1924   }
1925   delete mChildren;
1926   delete mRenderers;
1927
1928   // Guard to allow handle destruction after Core has been destroyed
1929   if( EventThreadServices::IsCoreRunning() )
1930   {
1931     if( NULL != mNode )
1932     {
1933       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1934       mNode = NULL; // Node is about to be destroyed
1935     }
1936
1937     GetEventThreadServices().UnregisterObject( this );
1938   }
1939
1940   // Cleanup optional gesture data
1941   delete mGestureData;
1942
1943   // Cleanup optional parent origin and anchor
1944   delete mParentOrigin;
1945   delete mAnchorPoint;
1946
1947   // Delete optional relayout data
1948   if( mRelayoutData )
1949   {
1950     delete mRelayoutData;
1951   }
1952 }
1953
1954 void Actor::ConnectToStage( unsigned int parentDepth )
1955 {
1956   // This container is used instead of walking the Actor hierarchy.
1957   // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1958   ActorContainer connectionList;
1959
1960   // This stage is atomic i.e. not interrupted by user callbacks.
1961   RecursiveConnectToStage( connectionList, parentDepth + 1 );
1962
1963   // Notify applications about the newly connected actors.
1964   const ActorIter endIter = connectionList.end();
1965   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1966   {
1967     (*iter)->NotifyStageConnection();
1968   }
1969
1970   RelayoutRequest();
1971 }
1972
1973 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
1974 {
1975   DALI_ASSERT_ALWAYS( !OnStage() );
1976
1977   mIsOnStage = true;
1978   mDepth = depth;
1979
1980   ConnectToSceneGraph();
1981
1982   // Notification for internal derived classes
1983   OnStageConnectionInternal();
1984
1985   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1986   connectionList.push_back( ActorPtr( this ) );
1987
1988   // Recursively connect children
1989   if( mChildren )
1990   {
1991     ActorConstIter endIter = mChildren->end();
1992     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1993     {
1994       (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1995     }
1996   }
1997 }
1998
1999 /**
2000  * This method is called when the Actor is connected to the Stage.
2001  * The parent must have added its Node to the scene-graph.
2002  * The child must connect its Node to the parent's Node.
2003  * This is recursive; the child calls ConnectToStage() for its children.
2004  */
2005 void Actor::ConnectToSceneGraph()
2006 {
2007   DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2008
2009   if( NULL != mNode )
2010   {
2011     // Reparent Node in next Update
2012     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2013   }
2014
2015   // Notify attachment
2016   if( mAttachment )
2017   {
2018     mAttachment->Connect();
2019   }
2020
2021   unsigned int rendererCount( GetRendererCount() );
2022   for( unsigned int i(0); i<rendererCount; ++i )
2023   {
2024     GetRendererAt(i)->Connect();
2025   }
2026
2027   // Request relayout on all actors that are added to the scenegraph
2028   RelayoutRequest();
2029
2030   // Notification for Object::Observers
2031   OnSceneObjectAdd();
2032 }
2033
2034 void Actor::NotifyStageConnection()
2035 {
2036   // Actors can be removed (in a callback), before the on-stage stage is reported.
2037   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2038   if( OnStage() && !mOnStageSignalled )
2039   {
2040     // Notification for external (CustomActor) derived classes
2041     OnStageConnectionExternal( mDepth );
2042
2043     if( !mOnStageSignal.Empty() )
2044     {
2045       Dali::Actor handle( this );
2046       mOnStageSignal.Emit( handle );
2047     }
2048
2049     // Guard against Remove during callbacks
2050     if( OnStage() )
2051     {
2052       mOnStageSignalled = true; // signal required next time Actor is removed
2053     }
2054   }
2055 }
2056
2057 void Actor::DisconnectFromStage()
2058 {
2059   // This container is used instead of walking the Actor hierachy.
2060   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2061   ActorContainer disconnectionList;
2062
2063   // This stage is atomic i.e. not interrupted by user callbacks
2064   RecursiveDisconnectFromStage( disconnectionList );
2065
2066   // Notify applications about the newly disconnected actors.
2067   const ActorIter endIter = disconnectionList.end();
2068   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2069   {
2070     (*iter)->NotifyStageDisconnection();
2071   }
2072 }
2073
2074 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2075 {
2076   DALI_ASSERT_ALWAYS( OnStage() );
2077
2078   // Recursively disconnect children
2079   if( mChildren )
2080   {
2081     ActorConstIter endIter = mChildren->end();
2082     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2083     {
2084       (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2085     }
2086   }
2087
2088   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2089   disconnectionList.push_back( ActorPtr( this ) );
2090
2091   // Notification for internal derived classes
2092   OnStageDisconnectionInternal();
2093
2094   DisconnectFromSceneGraph();
2095
2096   mIsOnStage = false;
2097 }
2098
2099 /**
2100  * This method is called by an actor or its parent, before a node removal message is sent.
2101  * This is recursive; the child calls DisconnectFromStage() for its children.
2102  */
2103 void Actor::DisconnectFromSceneGraph()
2104 {
2105   // Notification for Object::Observers
2106   OnSceneObjectRemove();
2107
2108   // Notify attachment
2109   if( mAttachment )
2110   {
2111     mAttachment->Disconnect();
2112   }
2113
2114   unsigned int rendererCount( GetRendererCount() );
2115   for( unsigned int i(0); i<rendererCount; ++i )
2116   {
2117     GetRendererAt(i)->Disconnect();
2118   }
2119 }
2120
2121 void Actor::NotifyStageDisconnection()
2122 {
2123   // Actors can be added (in a callback), before the off-stage state is reported.
2124   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2125   // only do this step if there is a stage, i.e. Core is not being shut down
2126   if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2127   {
2128     // Notification for external (CustomeActor) derived classes
2129     OnStageDisconnectionExternal();
2130
2131     if( !mOffStageSignal.Empty() )
2132     {
2133       Dali::Actor handle( this );
2134       mOffStageSignal.Emit( handle );
2135     }
2136
2137     // Guard against Add during callbacks
2138     if( !OnStage() )
2139     {
2140       mOnStageSignalled = false; // signal required next time Actor is added
2141     }
2142   }
2143 }
2144
2145 bool Actor::IsNodeConnected() const
2146 {
2147   bool connected( false );
2148
2149   if( OnStage() && ( NULL != mNode ) )
2150   {
2151     if( IsRoot() || mNode->GetParent() )
2152     {
2153       connected = true;
2154     }
2155   }
2156
2157   return connected;
2158 }
2159
2160 unsigned int Actor::GetDefaultPropertyCount() const
2161 {
2162   return DEFAULT_PROPERTY_COUNT;
2163 }
2164
2165 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2166 {
2167   indices.Reserve( DEFAULT_PROPERTY_COUNT );
2168
2169   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2170   {
2171     indices.PushBack( i );
2172   }
2173 }
2174
2175 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2176 {
2177   if( index < DEFAULT_PROPERTY_COUNT )
2178   {
2179     return DEFAULT_PROPERTY_DETAILS[ index ].name;
2180   }
2181
2182   return NULL;
2183 }
2184
2185 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2186 {
2187   Property::Index index = Property::INVALID_INDEX;
2188
2189   // Look for name in default properties
2190   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2191   {
2192     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2193     if( 0 == name.compare( property->name ) )
2194     {
2195       index = i;
2196       break;
2197     }
2198   }
2199
2200   return index;
2201 }
2202
2203 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2204 {
2205   if( index < DEFAULT_PROPERTY_COUNT )
2206   {
2207     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2208   }
2209
2210   return false;
2211 }
2212
2213 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2214 {
2215   if( index < DEFAULT_PROPERTY_COUNT )
2216   {
2217     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2218   }
2219
2220   return false;
2221 }
2222
2223 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2224 {
2225   if( index < DEFAULT_PROPERTY_COUNT )
2226   {
2227     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2228   }
2229
2230   return false;
2231 }
2232
2233 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2234 {
2235   if( index < DEFAULT_PROPERTY_COUNT )
2236   {
2237     return DEFAULT_PROPERTY_DETAILS[ index ].type;
2238   }
2239
2240   // index out of range...return Property::NONE
2241   return Property::NONE;
2242 }
2243
2244 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2245 {
2246   switch( index )
2247   {
2248     case Dali::Actor::Property::PARENT_ORIGIN:
2249     {
2250       SetParentOrigin( property.Get< Vector3 >() );
2251       break;
2252     }
2253
2254     case Dali::Actor::Property::PARENT_ORIGIN_X:
2255     {
2256       SetParentOriginX( property.Get< float >() );
2257       break;
2258     }
2259
2260     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2261     {
2262       SetParentOriginY( property.Get< float >() );
2263       break;
2264     }
2265
2266     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2267     {
2268       SetParentOriginZ( property.Get< float >() );
2269       break;
2270     }
2271
2272     case Dali::Actor::Property::ANCHOR_POINT:
2273     {
2274       SetAnchorPoint( property.Get< Vector3 >() );
2275       break;
2276     }
2277
2278     case Dali::Actor::Property::ANCHOR_POINT_X:
2279     {
2280       SetAnchorPointX( property.Get< float >() );
2281       break;
2282     }
2283
2284     case Dali::Actor::Property::ANCHOR_POINT_Y:
2285     {
2286       SetAnchorPointY( property.Get< float >() );
2287       break;
2288     }
2289
2290     case Dali::Actor::Property::ANCHOR_POINT_Z:
2291     {
2292       SetAnchorPointZ( property.Get< float >() );
2293       break;
2294     }
2295
2296     case Dali::Actor::Property::SIZE:
2297     {
2298       SetSize( property.Get< Vector3 >() );
2299       break;
2300     }
2301
2302     case Dali::Actor::Property::SIZE_WIDTH:
2303     {
2304       SetWidth( property.Get< float >() );
2305       break;
2306     }
2307
2308     case Dali::Actor::Property::SIZE_HEIGHT:
2309     {
2310       SetHeight( property.Get< float >() );
2311       break;
2312     }
2313
2314     case Dali::Actor::Property::SIZE_DEPTH:
2315     {
2316       SetDepth( property.Get< float >() );
2317       break;
2318     }
2319
2320     case Dali::Actor::Property::POSITION:
2321     {
2322       SetPosition( property.Get< Vector3 >() );
2323       break;
2324     }
2325
2326     case Dali::Actor::Property::POSITION_X:
2327     {
2328       SetX( property.Get< float >() );
2329       break;
2330     }
2331
2332     case Dali::Actor::Property::POSITION_Y:
2333     {
2334       SetY( property.Get< float >() );
2335       break;
2336     }
2337
2338     case Dali::Actor::Property::POSITION_Z:
2339     {
2340       SetZ( property.Get< float >() );
2341       break;
2342     }
2343
2344     case Dali::Actor::Property::ORIENTATION:
2345     {
2346       SetOrientation( property.Get< Quaternion >() );
2347       break;
2348     }
2349
2350     case Dali::Actor::Property::SCALE:
2351     {
2352       SetScale( property.Get< Vector3 >() );
2353       break;
2354     }
2355
2356     case Dali::Actor::Property::SCALE_X:
2357     {
2358       SetScaleX( property.Get< float >() );
2359       break;
2360     }
2361
2362     case Dali::Actor::Property::SCALE_Y:
2363     {
2364       SetScaleY( property.Get< float >() );
2365       break;
2366     }
2367
2368     case Dali::Actor::Property::SCALE_Z:
2369     {
2370       SetScaleZ( property.Get< float >() );
2371       break;
2372     }
2373
2374     case Dali::Actor::Property::VISIBLE:
2375     {
2376       SetVisible( property.Get< bool >() );
2377       break;
2378     }
2379
2380     case Dali::Actor::Property::COLOR:
2381     {
2382       SetColor( property.Get< Vector4 >() );
2383       break;
2384     }
2385
2386     case Dali::Actor::Property::COLOR_RED:
2387     {
2388       SetColorRed( property.Get< float >() );
2389       break;
2390     }
2391
2392     case Dali::Actor::Property::COLOR_GREEN:
2393     {
2394       SetColorGreen( property.Get< float >() );
2395       break;
2396     }
2397
2398     case Dali::Actor::Property::COLOR_BLUE:
2399     {
2400       SetColorBlue( property.Get< float >() );
2401       break;
2402     }
2403
2404     case Dali::Actor::Property::COLOR_ALPHA:
2405     {
2406       SetOpacity( property.Get< float >() );
2407       break;
2408     }
2409
2410     case Dali::Actor::Property::NAME:
2411     {
2412       SetName( property.Get< std::string >() );
2413       break;
2414     }
2415
2416     case Dali::Actor::Property::SENSITIVE:
2417     {
2418       SetSensitive( property.Get< bool >() );
2419       break;
2420     }
2421
2422     case Dali::Actor::Property::LEAVE_REQUIRED:
2423     {
2424       SetLeaveRequired( property.Get< bool >() );
2425       break;
2426     }
2427
2428     case Dali::Actor::Property::INHERIT_ORIENTATION:
2429     {
2430       SetInheritOrientation( property.Get< bool >() );
2431       break;
2432     }
2433
2434     case Dali::Actor::Property::INHERIT_SCALE:
2435     {
2436       SetInheritScale( property.Get< bool >() );
2437       break;
2438     }
2439
2440     case Dali::Actor::Property::COLOR_MODE:
2441     {
2442       SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2443       break;
2444     }
2445
2446     case Dali::Actor::Property::POSITION_INHERITANCE:
2447     {
2448       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2449       break;
2450     }
2451
2452     case Dali::Actor::Property::DRAW_MODE:
2453     {
2454       SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2455       break;
2456     }
2457
2458     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2459     {
2460       SetSizeModeFactor( property.Get< Vector3 >() );
2461       break;
2462     }
2463
2464     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2465     {
2466       ResizePolicy::Type type;
2467       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2468       {
2469         SetResizePolicy( type, Dimension::WIDTH );
2470       }
2471       break;
2472     }
2473
2474     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2475     {
2476       ResizePolicy::Type type;
2477       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2478       {
2479         SetResizePolicy( type, Dimension::HEIGHT );
2480       }
2481       break;
2482     }
2483
2484     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2485     {
2486       SizeScalePolicy::Type type;
2487       if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2488       {
2489         SetSizeScalePolicy( type );
2490       }
2491       break;
2492     }
2493
2494     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2495     {
2496       if( property.Get< bool >() )
2497       {
2498         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2499       }
2500       break;
2501     }
2502
2503     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2504     {
2505       if( property.Get< bool >() )
2506       {
2507         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2508       }
2509       break;
2510     }
2511
2512     case Dali::Actor::Property::PADDING:
2513     {
2514       Vector4 padding = property.Get< Vector4 >();
2515       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2516       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2517       break;
2518     }
2519
2520     case Dali::Actor::Property::MINIMUM_SIZE:
2521     {
2522       Vector2 size = property.Get< Vector2 >();
2523       SetMinimumSize( size.x, Dimension::WIDTH );
2524       SetMinimumSize( size.y, Dimension::HEIGHT );
2525       break;
2526     }
2527
2528     case Dali::Actor::Property::MAXIMUM_SIZE:
2529     {
2530       Vector2 size = property.Get< Vector2 >();
2531       SetMaximumSize( size.x, Dimension::WIDTH );
2532       SetMaximumSize( size.y, Dimension::HEIGHT );
2533       break;
2534     }
2535
2536     default:
2537     {
2538       // this can happen in the case of a non-animatable default property so just do nothing
2539       break;
2540     }
2541   }
2542 }
2543
2544 // TODO: This method needs to be removed
2545 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2546 {
2547   switch( entry.GetType() )
2548   {
2549     case Property::BOOLEAN:
2550     {
2551       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2552       DALI_ASSERT_DEBUG( NULL != property );
2553
2554       // property is being used in a separate thread; queue a message to set the property
2555       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2556
2557       break;
2558     }
2559
2560     case Property::INTEGER:
2561     {
2562       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2563       DALI_ASSERT_DEBUG( NULL != property );
2564
2565       // property is being used in a separate thread; queue a message to set the property
2566       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2567
2568       break;
2569     }
2570
2571     case Property::FLOAT:
2572     {
2573       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2574       DALI_ASSERT_DEBUG( NULL != property );
2575
2576       // property is being used in a separate thread; queue a message to set the property
2577       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2578
2579       break;
2580     }
2581
2582     case Property::VECTOR2:
2583     {
2584       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2585       DALI_ASSERT_DEBUG( NULL != property );
2586
2587       // property is being used in a separate thread; queue a message to set the property
2588       if(entry.componentIndex == 0)
2589       {
2590         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2591       }
2592       else if(entry.componentIndex == 1)
2593       {
2594         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2595       }
2596       else
2597       {
2598         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2599       }
2600
2601       break;
2602     }
2603
2604     case Property::VECTOR3:
2605     {
2606       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2607       DALI_ASSERT_DEBUG( NULL != property );
2608
2609       // property is being used in a separate thread; queue a message to set the property
2610       if(entry.componentIndex == 0)
2611       {
2612         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2613       }
2614       else if(entry.componentIndex == 1)
2615       {
2616         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2617       }
2618       else if(entry.componentIndex == 2)
2619       {
2620         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2621       }
2622       else
2623       {
2624         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2625       }
2626
2627       break;
2628     }
2629
2630     case Property::VECTOR4:
2631     {
2632       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2633       DALI_ASSERT_DEBUG( NULL != property );
2634
2635       // property is being used in a separate thread; queue a message to set the property
2636       if(entry.componentIndex == 0)
2637       {
2638         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2639       }
2640       else if(entry.componentIndex == 1)
2641       {
2642         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2643       }
2644       else if(entry.componentIndex == 2)
2645       {
2646         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2647       }
2648       else if(entry.componentIndex == 3)
2649       {
2650         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2651       }
2652       else
2653       {
2654         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2655       }
2656
2657       break;
2658     }
2659
2660     case Property::ROTATION:
2661     {
2662       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2663       DALI_ASSERT_DEBUG( NULL != property );
2664
2665       // property is being used in a separate thread; queue a message to set the property
2666       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
2667
2668       break;
2669     }
2670
2671     case Property::MATRIX:
2672     {
2673       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2674       DALI_ASSERT_DEBUG( NULL != property );
2675
2676       // property is being used in a separate thread; queue a message to set the property
2677       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
2678
2679       break;
2680     }
2681
2682     case Property::MATRIX3:
2683     {
2684       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2685       DALI_ASSERT_DEBUG( NULL != property );
2686
2687       // property is being used in a separate thread; queue a message to set the property
2688       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
2689
2690       break;
2691     }
2692
2693     default:
2694     {
2695       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2696       break;
2697     }
2698   }
2699 }
2700
2701 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2702 {
2703   Property::Value value;
2704
2705   switch( index )
2706   {
2707     case Dali::Actor::Property::PARENT_ORIGIN:
2708     {
2709       value = GetCurrentParentOrigin();
2710       break;
2711     }
2712
2713     case Dali::Actor::Property::PARENT_ORIGIN_X:
2714     {
2715       value = GetCurrentParentOrigin().x;
2716       break;
2717     }
2718
2719     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2720     {
2721       value = GetCurrentParentOrigin().y;
2722       break;
2723     }
2724
2725     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2726     {
2727       value = GetCurrentParentOrigin().z;
2728       break;
2729     }
2730
2731     case Dali::Actor::Property::ANCHOR_POINT:
2732     {
2733       value = GetCurrentAnchorPoint();
2734       break;
2735     }
2736
2737     case Dali::Actor::Property::ANCHOR_POINT_X:
2738     {
2739       value = GetCurrentAnchorPoint().x;
2740       break;
2741     }
2742
2743     case Dali::Actor::Property::ANCHOR_POINT_Y:
2744     {
2745       value = GetCurrentAnchorPoint().y;
2746       break;
2747     }
2748
2749     case Dali::Actor::Property::ANCHOR_POINT_Z:
2750     {
2751       value = GetCurrentAnchorPoint().z;
2752       break;
2753     }
2754
2755     case Dali::Actor::Property::SIZE:
2756     {
2757       value = GetCurrentSize();
2758       break;
2759     }
2760
2761     case Dali::Actor::Property::SIZE_WIDTH:
2762     {
2763       value = GetCurrentSize().width;
2764       break;
2765     }
2766
2767     case Dali::Actor::Property::SIZE_HEIGHT:
2768     {
2769       value = GetCurrentSize().height;
2770       break;
2771     }
2772
2773     case Dali::Actor::Property::SIZE_DEPTH:
2774     {
2775       value = GetCurrentSize().depth;
2776       break;
2777     }
2778
2779     case Dali::Actor::Property::POSITION:
2780     {
2781       value = GetCurrentPosition();
2782       break;
2783     }
2784
2785     case Dali::Actor::Property::POSITION_X:
2786     {
2787       value = GetCurrentPosition().x;
2788       break;
2789     }
2790
2791     case Dali::Actor::Property::POSITION_Y:
2792     {
2793       value = GetCurrentPosition().y;
2794       break;
2795     }
2796
2797     case Dali::Actor::Property::POSITION_Z:
2798     {
2799       value = GetCurrentPosition().z;
2800       break;
2801     }
2802
2803     case Dali::Actor::Property::WORLD_POSITION:
2804     {
2805       value = GetCurrentWorldPosition();
2806       break;
2807     }
2808
2809     case Dali::Actor::Property::WORLD_POSITION_X:
2810     {
2811       value = GetCurrentWorldPosition().x;
2812       break;
2813     }
2814
2815     case Dali::Actor::Property::WORLD_POSITION_Y:
2816     {
2817       value = GetCurrentWorldPosition().y;
2818       break;
2819     }
2820
2821     case Dali::Actor::Property::WORLD_POSITION_Z:
2822     {
2823       value = GetCurrentWorldPosition().z;
2824       break;
2825     }
2826
2827     case Dali::Actor::Property::ORIENTATION:
2828     {
2829       value = GetCurrentOrientation();
2830       break;
2831     }
2832
2833     case Dali::Actor::Property::WORLD_ORIENTATION:
2834     {
2835       value = GetCurrentWorldOrientation();
2836       break;
2837     }
2838
2839     case Dali::Actor::Property::SCALE:
2840     {
2841       value = GetCurrentScale();
2842       break;
2843     }
2844
2845     case Dali::Actor::Property::SCALE_X:
2846     {
2847       value = GetCurrentScale().x;
2848       break;
2849     }
2850
2851     case Dali::Actor::Property::SCALE_Y:
2852     {
2853       value = GetCurrentScale().y;
2854       break;
2855     }
2856
2857     case Dali::Actor::Property::SCALE_Z:
2858     {
2859       value = GetCurrentScale().z;
2860       break;
2861     }
2862
2863     case Dali::Actor::Property::WORLD_SCALE:
2864     {
2865       value = GetCurrentWorldScale();
2866       break;
2867     }
2868
2869     case Dali::Actor::Property::VISIBLE:
2870     {
2871       value = IsVisible();
2872       break;
2873     }
2874
2875     case Dali::Actor::Property::COLOR:
2876     {
2877       value = GetCurrentColor();
2878       break;
2879     }
2880
2881     case Dali::Actor::Property::COLOR_RED:
2882     {
2883       value = GetCurrentColor().r;
2884       break;
2885     }
2886
2887     case Dali::Actor::Property::COLOR_GREEN:
2888     {
2889       value = GetCurrentColor().g;
2890       break;
2891     }
2892
2893     case Dali::Actor::Property::COLOR_BLUE:
2894     {
2895       value = GetCurrentColor().b;
2896       break;
2897     }
2898
2899     case Dali::Actor::Property::COLOR_ALPHA:
2900     {
2901       value = GetCurrentColor().a;
2902       break;
2903     }
2904
2905     case Dali::Actor::Property::WORLD_COLOR:
2906     {
2907       value = GetCurrentWorldColor();
2908       break;
2909     }
2910
2911     case Dali::Actor::Property::WORLD_MATRIX:
2912     {
2913       value = GetCurrentWorldMatrix();
2914       break;
2915     }
2916
2917     case Dali::Actor::Property::NAME:
2918     {
2919       value = GetName();
2920       break;
2921     }
2922
2923     case Dali::Actor::Property::SENSITIVE:
2924     {
2925       value = IsSensitive();
2926       break;
2927     }
2928
2929     case Dali::Actor::Property::LEAVE_REQUIRED:
2930     {
2931       value = GetLeaveRequired();
2932       break;
2933     }
2934
2935     case Dali::Actor::Property::INHERIT_ORIENTATION:
2936     {
2937       value = IsOrientationInherited();
2938       break;
2939     }
2940
2941     case Dali::Actor::Property::INHERIT_SCALE:
2942     {
2943       value = IsScaleInherited();
2944       break;
2945     }
2946
2947     case Dali::Actor::Property::COLOR_MODE:
2948     {
2949       value = Scripting::GetColorMode( GetColorMode() );
2950       break;
2951     }
2952
2953     case Dali::Actor::Property::POSITION_INHERITANCE:
2954     {
2955       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2956       break;
2957     }
2958
2959     case Dali::Actor::Property::DRAW_MODE:
2960     {
2961       value = Scripting::GetDrawMode( GetDrawMode() );
2962       break;
2963     }
2964
2965     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2966     {
2967       value = GetSizeModeFactor();
2968       break;
2969     }
2970
2971     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2972     {
2973       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2974       break;
2975     }
2976
2977     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2978     {
2979       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2980       break;
2981     }
2982
2983     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2984     {
2985       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2986       break;
2987     }
2988
2989     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2990     {
2991       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2992       break;
2993     }
2994
2995     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2996     {
2997       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2998       break;
2999     }
3000
3001     case Dali::Actor::Property::PADDING:
3002     {
3003       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3004       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3005       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3006       break;
3007     }
3008
3009     case Dali::Actor::Property::MINIMUM_SIZE:
3010     {
3011       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3012       break;
3013     }
3014
3015     case Dali::Actor::Property::MAXIMUM_SIZE:
3016     {
3017       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3018       break;
3019     }
3020
3021     default:
3022     {
3023       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3024       break;
3025     }
3026   }
3027
3028   return value;
3029 }
3030
3031 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3032 {
3033   return mNode;
3034 }
3035
3036 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3037 {
3038   // This method should only return an object connected to the scene-graph
3039   return OnStage() ? mNode : NULL;
3040 }
3041
3042 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3043 {
3044   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3045
3046   const PropertyBase* property( NULL );
3047
3048   // This method should only return a property of an object connected to the scene-graph
3049   if( !OnStage() )
3050   {
3051     return property;
3052   }
3053
3054   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3055   {
3056     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3057     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3058
3059     property = animatable->GetSceneGraphProperty();
3060   }
3061   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3062   {
3063     CustomPropertyMetadata* custom = FindCustomProperty( index );
3064     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3065
3066     property = custom->GetSceneGraphProperty();
3067   }
3068   else if( NULL != mNode )
3069   {
3070     switch( index )
3071     {
3072       case Dali::Actor::Property::SIZE:
3073         property = &mNode->mSize;
3074         break;
3075
3076       case Dali::Actor::Property::SIZE_WIDTH:
3077         property = &mNode->mSize;
3078         break;
3079
3080       case Dali::Actor::Property::SIZE_HEIGHT:
3081         property = &mNode->mSize;
3082         break;
3083
3084       case Dali::Actor::Property::SIZE_DEPTH:
3085         property = &mNode->mSize;
3086         break;
3087
3088       case Dali::Actor::Property::POSITION:
3089         property = &mNode->mPosition;
3090         break;
3091
3092       case Dali::Actor::Property::POSITION_X:
3093         property = &mNode->mPosition;
3094         break;
3095
3096       case Dali::Actor::Property::POSITION_Y:
3097         property = &mNode->mPosition;
3098         break;
3099
3100       case Dali::Actor::Property::POSITION_Z:
3101         property = &mNode->mPosition;
3102         break;
3103
3104       case Dali::Actor::Property::ORIENTATION:
3105         property = &mNode->mOrientation;
3106         break;
3107
3108       case Dali::Actor::Property::SCALE:
3109         property = &mNode->mScale;
3110         break;
3111
3112       case Dali::Actor::Property::SCALE_X:
3113         property = &mNode->mScale;
3114         break;
3115
3116       case Dali::Actor::Property::SCALE_Y:
3117         property = &mNode->mScale;
3118         break;
3119
3120       case Dali::Actor::Property::SCALE_Z:
3121         property = &mNode->mScale;
3122         break;
3123
3124       case Dali::Actor::Property::VISIBLE:
3125         property = &mNode->mVisible;
3126         break;
3127
3128       case Dali::Actor::Property::COLOR:
3129         property = &mNode->mColor;
3130         break;
3131
3132       case Dali::Actor::Property::COLOR_RED:
3133         property = &mNode->mColor;
3134         break;
3135
3136       case Dali::Actor::Property::COLOR_GREEN:
3137         property = &mNode->mColor;
3138         break;
3139
3140       case Dali::Actor::Property::COLOR_BLUE:
3141         property = &mNode->mColor;
3142         break;
3143
3144       case Dali::Actor::Property::COLOR_ALPHA:
3145         property = &mNode->mColor;
3146         break;
3147
3148       default:
3149         break;
3150     }
3151   }
3152
3153   return property;
3154 }
3155
3156 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3157 {
3158   const PropertyInputImpl* property( NULL );
3159
3160   // This method should only return a property of an object connected to the scene-graph
3161   if( !OnStage() )
3162   {
3163     return property;
3164   }
3165
3166   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3167   {
3168     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3169     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3170
3171     property = animatable->GetSceneGraphProperty();
3172   }
3173   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3174   {
3175     CustomPropertyMetadata* custom = FindCustomProperty( index );
3176     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3177     property = custom->GetSceneGraphProperty();
3178   }
3179   else if( NULL != mNode )
3180   {
3181     switch( index )
3182     {
3183       case Dali::Actor::Property::PARENT_ORIGIN:
3184         property = &mNode->mParentOrigin;
3185         break;
3186
3187       case Dali::Actor::Property::PARENT_ORIGIN_X:
3188         property = &mNode->mParentOrigin;
3189         break;
3190
3191       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3192         property = &mNode->mParentOrigin;
3193         break;
3194
3195       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3196         property = &mNode->mParentOrigin;
3197         break;
3198
3199       case Dali::Actor::Property::ANCHOR_POINT:
3200         property = &mNode->mAnchorPoint;
3201         break;
3202
3203       case Dali::Actor::Property::ANCHOR_POINT_X:
3204         property = &mNode->mAnchorPoint;
3205         break;
3206
3207       case Dali::Actor::Property::ANCHOR_POINT_Y:
3208         property = &mNode->mAnchorPoint;
3209         break;
3210
3211       case Dali::Actor::Property::ANCHOR_POINT_Z:
3212         property = &mNode->mAnchorPoint;
3213         break;
3214
3215       case Dali::Actor::Property::SIZE:
3216         property = &mNode->mSize;
3217         break;
3218
3219       case Dali::Actor::Property::SIZE_WIDTH:
3220         property = &mNode->mSize;
3221         break;
3222
3223       case Dali::Actor::Property::SIZE_HEIGHT:
3224         property = &mNode->mSize;
3225         break;
3226
3227       case Dali::Actor::Property::SIZE_DEPTH:
3228         property = &mNode->mSize;
3229         break;
3230
3231       case Dali::Actor::Property::POSITION:
3232         property = &mNode->mPosition;
3233         break;
3234
3235       case Dali::Actor::Property::POSITION_X:
3236         property = &mNode->mPosition;
3237         break;
3238
3239       case Dali::Actor::Property::POSITION_Y:
3240         property = &mNode->mPosition;
3241         break;
3242
3243       case Dali::Actor::Property::POSITION_Z:
3244         property = &mNode->mPosition;
3245         break;
3246
3247       case Dali::Actor::Property::WORLD_POSITION:
3248         property = &mNode->mWorldPosition;
3249         break;
3250
3251       case Dali::Actor::Property::WORLD_POSITION_X:
3252         property = &mNode->mWorldPosition;
3253         break;
3254
3255       case Dali::Actor::Property::WORLD_POSITION_Y:
3256         property = &mNode->mWorldPosition;
3257         break;
3258
3259       case Dali::Actor::Property::WORLD_POSITION_Z:
3260         property = &mNode->mWorldPosition;
3261         break;
3262
3263       case Dali::Actor::Property::ORIENTATION:
3264         property = &mNode->mOrientation;
3265         break;
3266
3267       case Dali::Actor::Property::WORLD_ORIENTATION:
3268         property = &mNode->mWorldOrientation;
3269         break;
3270
3271       case Dali::Actor::Property::SCALE:
3272         property = &mNode->mScale;
3273         break;
3274
3275       case Dali::Actor::Property::SCALE_X:
3276         property = &mNode->mScale;
3277         break;
3278
3279       case Dali::Actor::Property::SCALE_Y:
3280         property = &mNode->mScale;
3281         break;
3282
3283       case Dali::Actor::Property::SCALE_Z:
3284         property = &mNode->mScale;
3285         break;
3286
3287       case Dali::Actor::Property::WORLD_SCALE:
3288         property = &mNode->mWorldScale;
3289         break;
3290
3291       case Dali::Actor::Property::VISIBLE:
3292         property = &mNode->mVisible;
3293         break;
3294
3295       case Dali::Actor::Property::COLOR:
3296         property = &mNode->mColor;
3297         break;
3298
3299       case Dali::Actor::Property::COLOR_RED:
3300         property = &mNode->mColor;
3301         break;
3302
3303       case Dali::Actor::Property::COLOR_GREEN:
3304         property = &mNode->mColor;
3305         break;
3306
3307       case Dali::Actor::Property::COLOR_BLUE:
3308         property = &mNode->mColor;
3309         break;
3310
3311       case Dali::Actor::Property::COLOR_ALPHA:
3312         property = &mNode->mColor;
3313         break;
3314
3315       case Dali::Actor::Property::WORLD_COLOR:
3316         property = &mNode->mWorldColor;
3317         break;
3318
3319       case Dali::Actor::Property::WORLD_MATRIX:
3320         property = &mNode->mWorldMatrix;
3321         break;
3322
3323       default:
3324         break;
3325     }
3326   }
3327
3328   return property;
3329 }
3330
3331 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3332 {
3333   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3334
3335   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3336   {
3337     // check whether the animatable property is registered already, if not then register one.
3338     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3339     if( animatableProperty )
3340     {
3341       componentIndex = animatableProperty->componentIndex;
3342     }
3343   }
3344   else
3345   {
3346     switch( index )
3347     {
3348       case Dali::Actor::Property::PARENT_ORIGIN_X:
3349       case Dali::Actor::Property::ANCHOR_POINT_X:
3350       case Dali::Actor::Property::SIZE_WIDTH:
3351       case Dali::Actor::Property::POSITION_X:
3352       case Dali::Actor::Property::WORLD_POSITION_X:
3353       case Dali::Actor::Property::SCALE_X:
3354       case Dali::Actor::Property::COLOR_RED:
3355       {
3356         componentIndex = 0;
3357         break;
3358       }
3359
3360       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3361       case Dali::Actor::Property::ANCHOR_POINT_Y:
3362       case Dali::Actor::Property::SIZE_HEIGHT:
3363       case Dali::Actor::Property::POSITION_Y:
3364       case Dali::Actor::Property::WORLD_POSITION_Y:
3365       case Dali::Actor::Property::SCALE_Y:
3366       case Dali::Actor::Property::COLOR_GREEN:
3367       {
3368         componentIndex = 1;
3369         break;
3370       }
3371
3372       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3373       case Dali::Actor::Property::ANCHOR_POINT_Z:
3374       case Dali::Actor::Property::SIZE_DEPTH:
3375       case Dali::Actor::Property::POSITION_Z:
3376       case Dali::Actor::Property::WORLD_POSITION_Z:
3377       case Dali::Actor::Property::SCALE_Z:
3378       case Dali::Actor::Property::COLOR_BLUE:
3379       {
3380         componentIndex = 2;
3381         break;
3382       }
3383
3384       case Dali::Actor::Property::COLOR_ALPHA:
3385       {
3386         componentIndex = 3;
3387         break;
3388       }
3389
3390       default:
3391       {
3392         // Do nothing
3393         break;
3394       }
3395     }
3396   }
3397
3398   return componentIndex;
3399 }
3400
3401 void Actor::SetParent( Actor* parent )
3402 {
3403   if( parent )
3404   {
3405     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3406
3407     mParent = parent;
3408
3409     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3410          parent->OnStage() )
3411     {
3412       // Instruct each actor to create a corresponding node in the scene graph
3413       ConnectToStage( parent->GetHierarchyDepth() );
3414     }
3415   }
3416   else // parent being set to NULL
3417   {
3418     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3419
3420     mParent = NULL;
3421
3422     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3423          OnStage() )
3424     {
3425       DALI_ASSERT_ALWAYS( mNode != NULL );
3426
3427       if( NULL != mNode )
3428       {
3429         // Disconnect the Node & its children from the scene-graph.
3430         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3431       }
3432
3433       // Instruct each actor to discard pointers to the scene-graph
3434       DisconnectFromStage();
3435     }
3436   }
3437 }
3438
3439 SceneGraph::Node* Actor::CreateNode() const
3440 {
3441   return Node::New();
3442 }
3443
3444 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3445 {
3446   bool done = false;
3447   Actor* actor = dynamic_cast< Actor* >( object );
3448
3449   if( actor )
3450   {
3451     if( 0 == actionName.compare( ACTION_SHOW ) )
3452     {
3453       actor->SetVisible( true );
3454       done = true;
3455     }
3456     else if( 0 == actionName.compare( ACTION_HIDE ) )
3457     {
3458       actor->SetVisible( false );
3459       done = true;
3460     }
3461   }
3462
3463   return done;
3464 }
3465
3466 void Actor::EnsureRelayoutData()
3467 {
3468   // Assign relayout data.
3469   if( !mRelayoutData )
3470   {
3471     mRelayoutData = new RelayoutData();
3472   }
3473 }
3474
3475 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3476 {
3477   // Check if actor is dependent on parent
3478   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3479   {
3480     if( ( dimension & ( 1 << i ) ) )
3481     {
3482       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3483       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3484       {
3485         return true;
3486       }
3487     }
3488   }
3489
3490   return false;
3491 }
3492
3493 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3494 {
3495   // Check if actor is dependent on children
3496   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3497   {
3498     if( ( dimension & ( 1 << i ) ) )
3499     {
3500       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3501       switch( resizePolicy )
3502       {
3503         case ResizePolicy::FIT_TO_CHILDREN:
3504         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3505         {
3506           return true;
3507         }
3508
3509         default:
3510         {
3511           break;
3512         }
3513       }
3514     }
3515   }
3516
3517   return false;
3518 }
3519
3520 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3521 {
3522   return Actor::RelayoutDependentOnChildren( dimension );
3523 }
3524
3525 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3526 {
3527   // Check each possible dimension and see if it is dependent on the input one
3528   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3529   {
3530     if( dimension & ( 1 << i ) )
3531     {
3532       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3533     }
3534   }
3535
3536   return false;
3537 }
3538
3539 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3540 {
3541   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3542   {
3543     if( dimension & ( 1 << i ) )
3544     {
3545       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3546     }
3547   }
3548 }
3549
3550 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3551 {
3552   // If more than one dimension is requested, just return the first one found
3553   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3554   {
3555     if( ( dimension & ( 1 << i ) ) )
3556     {
3557       return mRelayoutData->negotiatedDimensions[ i ];
3558     }
3559   }
3560
3561   return 0.0f;   // Default
3562 }
3563
3564 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3565 {
3566   EnsureRelayoutData();
3567
3568   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3569   {
3570     if( dimension & ( 1 << i ) )
3571     {
3572       mRelayoutData->dimensionPadding[ i ] = padding;
3573     }
3574   }
3575 }
3576
3577 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3578 {
3579   if ( mRelayoutData )
3580   {
3581     // If more than one dimension is requested, just return the first one found
3582     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3583     {
3584       if( ( dimension & ( 1 << i ) ) )
3585       {
3586         return mRelayoutData->dimensionPadding[ i ];
3587       }
3588     }
3589   }
3590
3591   return GetDefaultDimensionPadding();
3592 }
3593
3594 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3595 {
3596   EnsureRelayoutData();
3597
3598   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3599   {
3600     if( dimension & ( 1 << i ) )
3601     {
3602       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3603     }
3604   }
3605 }
3606
3607 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3608 {
3609   if ( mRelayoutData )
3610   {
3611     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3612     {
3613       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3614       {
3615         return true;
3616       }
3617     }
3618   }
3619
3620   return false;
3621 }
3622
3623 float Actor::GetHeightForWidthBase( float width )
3624 {
3625   float height = 0.0f;
3626
3627   const Vector3 naturalSize = GetNaturalSize();
3628   if( naturalSize.width > 0.0f )
3629   {
3630     height = naturalSize.height * width / naturalSize.width;
3631   }
3632   else // we treat 0 as 1:1 aspect ratio
3633   {
3634     height = width;
3635   }
3636
3637   return height;
3638 }
3639
3640 float Actor::GetWidthForHeightBase( float height )
3641 {
3642   float width = 0.0f;
3643
3644   const Vector3 naturalSize = GetNaturalSize();
3645   if( naturalSize.height > 0.0f )
3646   {
3647     width = naturalSize.width * height / naturalSize.height;
3648   }
3649   else // we treat 0 as 1:1 aspect ratio
3650   {
3651     width = height;
3652   }
3653
3654   return width;
3655 }
3656
3657 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3658 {
3659   // Fill to parent, taking size mode factor into account
3660   switch( child.GetResizePolicy( dimension ) )
3661   {
3662     case ResizePolicy::FILL_TO_PARENT:
3663     {
3664       return GetLatestSize( dimension );
3665     }
3666
3667     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3668     {
3669       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3670     }
3671
3672     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3673     {
3674       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3675     }
3676
3677     default:
3678     {
3679       return GetLatestSize( dimension );
3680     }
3681   }
3682 }
3683
3684 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3685 {
3686   // Can be overridden in derived class
3687   return CalculateChildSizeBase( child, dimension );
3688 }
3689
3690 float Actor::GetHeightForWidth( float width )
3691 {
3692   // Can be overridden in derived class
3693   return GetHeightForWidthBase( width );
3694 }
3695
3696 float Actor::GetWidthForHeight( float height )
3697 {
3698   // Can be overridden in derived class
3699   return GetWidthForHeightBase( height );
3700 }
3701
3702 float Actor::GetLatestSize( Dimension::Type dimension ) const
3703 {
3704   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3705 }
3706
3707 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3708 {
3709   Vector2 padding = GetPadding( dimension );
3710
3711   return GetLatestSize( dimension ) + padding.x + padding.y;
3712 }
3713
3714 float Actor::NegotiateFromParent( Dimension::Type dimension )
3715 {
3716   Actor* parent = GetParent();
3717   if( parent )
3718   {
3719     Vector2 padding( GetPadding( dimension ) );
3720     Vector2 parentPadding( parent->GetPadding( dimension ) );
3721     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3722   }
3723
3724   return 0.0f;
3725 }
3726
3727 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3728 {
3729   float maxDimensionPoint = 0.0f;
3730
3731   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3732   {
3733     ActorPtr child = GetChildAt( i );
3734
3735     if( !child->RelayoutDependentOnParent( dimension ) )
3736     {
3737       // Calculate the min and max points that the children range across
3738       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3739       float dimensionSize = child->GetRelayoutSize( dimension );
3740       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3741     }
3742   }
3743
3744   return maxDimensionPoint;
3745 }
3746
3747 float Actor::GetSize( Dimension::Type dimension ) const
3748 {
3749   return GetDimensionValue( GetTargetSize(), dimension );
3750 }
3751
3752 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3753 {
3754   return GetDimensionValue( GetNaturalSize(), dimension );
3755 }
3756
3757 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3758 {
3759   switch( GetResizePolicy( dimension ) )
3760   {
3761     case ResizePolicy::USE_NATURAL_SIZE:
3762     {
3763       return GetNaturalSize( dimension );
3764     }
3765
3766     case ResizePolicy::FIXED:
3767     {
3768       return GetDimensionValue( GetPreferredSize(), dimension );
3769     }
3770
3771     case ResizePolicy::USE_ASSIGNED_SIZE:
3772     {
3773       return GetDimensionValue( maximumSize, dimension );
3774     }
3775
3776     case ResizePolicy::FILL_TO_PARENT:
3777     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3778     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3779     {
3780       return NegotiateFromParent( dimension );
3781     }
3782
3783     case ResizePolicy::FIT_TO_CHILDREN:
3784     {
3785       return NegotiateFromChildren( dimension );
3786     }
3787
3788     case ResizePolicy::DIMENSION_DEPENDENCY:
3789     {
3790       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3791
3792       // Custom rules
3793       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3794       {
3795         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3796       }
3797
3798       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3799       {
3800         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3801       }
3802
3803       break;
3804     }
3805
3806     default:
3807     {
3808       break;
3809     }
3810   }
3811
3812   return 0.0f;  // Default
3813 }
3814
3815 float Actor::ClampDimension( float size, Dimension::Type dimension )
3816 {
3817   const float minSize = GetMinimumSize( dimension );
3818   const float maxSize = GetMaximumSize( dimension );
3819
3820   return std::max( minSize, std::min( size, maxSize ) );
3821 }
3822
3823 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3824 {
3825   // Check if it needs to be negotiated
3826   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3827   {
3828     // Check that we havn't gotten into an infinite loop
3829     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3830     bool recursionFound = false;
3831     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3832     {
3833       if( *it == searchActor )
3834       {
3835         recursionFound = true;
3836         break;
3837       }
3838     }
3839
3840     if( !recursionFound )
3841     {
3842       // Record the path that we have taken
3843       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3844
3845       // Dimension dependency check
3846       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3847       {
3848         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3849
3850         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3851         {
3852           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3853         }
3854       }
3855
3856       // Parent dependency check
3857       Actor* parent = GetParent();
3858       if( parent && RelayoutDependentOnParent( dimension ) )
3859       {
3860         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3861       }
3862
3863       // Children dependency check
3864       if( RelayoutDependentOnChildren( dimension ) )
3865       {
3866         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3867         {
3868           ActorPtr child = GetChildAt( i );
3869
3870           // Only relayout child first if it is not dependent on this actor
3871           if( !child->RelayoutDependentOnParent( dimension ) )
3872           {
3873             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3874           }
3875         }
3876       }
3877
3878       // For deriving classes
3879       OnCalculateRelayoutSize( dimension );
3880
3881       // All dependencies checked, calculate the size and set negotiated flag
3882       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3883
3884       SetNegotiatedDimension( newSize, dimension );
3885       SetLayoutNegotiated( true, dimension );
3886
3887       // For deriving classes
3888       OnLayoutNegotiated( newSize, dimension );
3889
3890       // This actor has been successfully processed, pop it off the recursion stack
3891       recursionStack.pop_back();
3892     }
3893     else
3894     {
3895       // TODO: Break infinite loop
3896       SetLayoutNegotiated( true, dimension );
3897     }
3898   }
3899 }
3900
3901 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3902 {
3903   // Negotiate all dimensions that require it
3904   ActorDimensionStack recursionStack;
3905
3906   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3907   {
3908     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3909
3910     // Negotiate
3911     NegotiateDimension( dimension, allocatedSize, recursionStack );
3912   }
3913 }
3914
3915 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3916 {
3917   switch( mRelayoutData->sizeSetPolicy )
3918   {
3919     case SizeScalePolicy::USE_SIZE_SET:
3920     {
3921       return size;
3922     }
3923
3924     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3925     {
3926       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3927       const Vector3 naturalSize = GetNaturalSize();
3928       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3929       {
3930         const float sizeRatio = size.width / size.height;
3931         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3932
3933         if( naturalSizeRatio < sizeRatio )
3934         {
3935           return Vector2( naturalSizeRatio * size.height, size.height );
3936         }
3937         else if( naturalSizeRatio > sizeRatio )
3938         {
3939           return Vector2( size.width, size.width / naturalSizeRatio );
3940         }
3941         else
3942         {
3943           return size;
3944         }
3945       }
3946
3947       break;
3948     }
3949
3950     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3951     {
3952       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3953       const Vector3 naturalSize = GetNaturalSize();
3954       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3955       {
3956         const float sizeRatio = size.width / size.height;
3957         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3958
3959         if( naturalSizeRatio < sizeRatio )
3960         {
3961           return Vector2( size.width, size.width / naturalSizeRatio );
3962         }
3963         else if( naturalSizeRatio > sizeRatio )
3964         {
3965           return Vector2( naturalSizeRatio * size.height, size.height );
3966         }
3967         else
3968         {
3969           return size;
3970         }
3971       }
3972     }
3973
3974     default:
3975     {
3976       break;
3977     }
3978   }
3979
3980   return size;
3981 }
3982
3983 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3984 {
3985   // Do the set actor size
3986   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3987
3988   // Adjust for size set policy
3989   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3990
3991   // Lock the flag to stop recursive relayouts on set size
3992   mRelayoutData->insideRelayout = true;
3993   SetSize( negotiatedSize );
3994   mRelayoutData->insideRelayout = false;
3995
3996   // Clear flags for all dimensions
3997   SetLayoutDirty( false );
3998
3999   // Give deriving classes a chance to respond
4000   OnRelayout( negotiatedSize, container );
4001
4002   if( !mOnRelayoutSignal.Empty() )
4003   {
4004     Dali::Actor handle( this );
4005     mOnRelayoutSignal.Emit( handle );
4006   }
4007 }
4008
4009 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4010 {
4011   // Do the negotiation
4012   NegotiateDimensions( allocatedSize );
4013
4014   // Set the actor size
4015   SetNegotiatedSize( container );
4016
4017   // Negotiate down to children
4018   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4019
4020   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4021   {
4022     ActorPtr child = GetChildAt( i );
4023
4024     // Only relayout if required
4025     if( child->RelayoutRequired() )
4026     {
4027       container.Add( Dali::Actor( child.Get() ), newBounds );
4028     }
4029   }
4030 }
4031
4032 void Actor::RelayoutRequest( Dimension::Type dimension )
4033 {
4034   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4035   if( relayoutController )
4036   {
4037     Dali::Actor self( this );
4038     relayoutController->RequestRelayout( self, dimension );
4039   }
4040 }
4041
4042 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4043 {
4044 }
4045
4046 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4047 {
4048 }
4049
4050 void Actor::SetPreferredSize( const Vector2& size )
4051 {
4052   EnsureRelayoutData();
4053
4054   if( size.width > 0.0f )
4055   {
4056     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4057   }
4058
4059   if( size.height > 0.0f )
4060   {
4061     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4062   }
4063
4064   mRelayoutData->preferredSize = size;
4065
4066   RelayoutRequest();
4067 }
4068
4069 Vector2 Actor::GetPreferredSize() const
4070 {
4071   if ( mRelayoutData )
4072   {
4073     return Vector2( mRelayoutData->preferredSize );
4074   }
4075
4076   return GetDefaultPreferredSize();
4077 }
4078
4079 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4080 {
4081   EnsureRelayoutData();
4082
4083   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4084   {
4085     if( dimension & ( 1 << i ) )
4086     {
4087       mRelayoutData->minimumSize[ i ] = size;
4088     }
4089   }
4090
4091   RelayoutRequest();
4092 }
4093
4094 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4095 {
4096   if ( mRelayoutData )
4097   {
4098     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4099     {
4100       if( dimension & ( 1 << i ) )
4101       {
4102         return mRelayoutData->minimumSize[ i ];
4103       }
4104     }
4105   }
4106
4107   return 0.0f;  // Default
4108 }
4109
4110 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4111 {
4112   EnsureRelayoutData();
4113
4114   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4115   {
4116     if( dimension & ( 1 << i ) )
4117     {
4118       mRelayoutData->maximumSize[ i ] = size;
4119     }
4120   }
4121
4122   RelayoutRequest();
4123 }
4124
4125 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4126 {
4127   if ( mRelayoutData )
4128   {
4129     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4130     {
4131       if( dimension & ( 1 << i ) )
4132       {
4133         return mRelayoutData->maximumSize[ i ];
4134       }
4135     }
4136   }
4137
4138   return FLT_MAX;  // Default
4139 }
4140
4141 } // namespace Internal
4142
4143 } // namespace Dali