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