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