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