00d0f45c3440c6415f2a487d3f2247b63e7343a9
[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       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2854       break;
2855     }
2856   } // entry.GetType
2857 }
2858
2859 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2860 {
2861   Property::Value value;
2862
2863   switch( index )
2864   {
2865     case Dali::Actor::Property::PARENT_ORIGIN:
2866     {
2867       value = GetCurrentParentOrigin();
2868       break;
2869     }
2870
2871     case Dali::Actor::Property::PARENT_ORIGIN_X:
2872     {
2873       value = GetCurrentParentOrigin().x;
2874       break;
2875     }
2876
2877     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2878     {
2879       value = GetCurrentParentOrigin().y;
2880       break;
2881     }
2882
2883     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2884     {
2885       value = GetCurrentParentOrigin().z;
2886       break;
2887     }
2888
2889     case Dali::Actor::Property::ANCHOR_POINT:
2890     {
2891       value = GetCurrentAnchorPoint();
2892       break;
2893     }
2894
2895     case Dali::Actor::Property::ANCHOR_POINT_X:
2896     {
2897       value = GetCurrentAnchorPoint().x;
2898       break;
2899     }
2900
2901     case Dali::Actor::Property::ANCHOR_POINT_Y:
2902     {
2903       value = GetCurrentAnchorPoint().y;
2904       break;
2905     }
2906
2907     case Dali::Actor::Property::ANCHOR_POINT_Z:
2908     {
2909       value = GetCurrentAnchorPoint().z;
2910       break;
2911     }
2912
2913     case Dali::Actor::Property::SIZE:
2914     {
2915       value = GetTargetSize();
2916       break;
2917     }
2918
2919     case Dali::Actor::Property::SIZE_WIDTH:
2920     {
2921       value = GetTargetSize().width;
2922       break;
2923     }
2924
2925     case Dali::Actor::Property::SIZE_HEIGHT:
2926     {
2927       value = GetTargetSize().height;
2928       break;
2929     }
2930
2931     case Dali::Actor::Property::SIZE_DEPTH:
2932     {
2933       value = GetTargetSize().depth;
2934       break;
2935     }
2936
2937     case Dali::Actor::Property::POSITION:
2938     {
2939       value = GetTargetPosition();
2940       break;
2941     }
2942
2943     case Dali::Actor::Property::POSITION_X:
2944     {
2945       value = GetTargetPosition().x;
2946       break;
2947     }
2948
2949     case Dali::Actor::Property::POSITION_Y:
2950     {
2951       value = GetTargetPosition().y;
2952       break;
2953     }
2954
2955     case Dali::Actor::Property::POSITION_Z:
2956     {
2957       value = GetTargetPosition().z;
2958       break;
2959     }
2960
2961     case Dali::Actor::Property::WORLD_POSITION:
2962     {
2963       value = GetCurrentWorldPosition();
2964       break;
2965     }
2966
2967     case Dali::Actor::Property::WORLD_POSITION_X:
2968     {
2969       value = GetCurrentWorldPosition().x;
2970       break;
2971     }
2972
2973     case Dali::Actor::Property::WORLD_POSITION_Y:
2974     {
2975       value = GetCurrentWorldPosition().y;
2976       break;
2977     }
2978
2979     case Dali::Actor::Property::WORLD_POSITION_Z:
2980     {
2981       value = GetCurrentWorldPosition().z;
2982       break;
2983     }
2984
2985     case Dali::Actor::Property::ORIENTATION:
2986     {
2987       value = GetCurrentOrientation();
2988       break;
2989     }
2990
2991     case Dali::Actor::Property::WORLD_ORIENTATION:
2992     {
2993       value = GetCurrentWorldOrientation();
2994       break;
2995     }
2996
2997     case Dali::Actor::Property::SCALE:
2998     {
2999       value = GetCurrentScale();
3000       break;
3001     }
3002
3003     case Dali::Actor::Property::SCALE_X:
3004     {
3005       value = GetCurrentScale().x;
3006       break;
3007     }
3008
3009     case Dali::Actor::Property::SCALE_Y:
3010     {
3011       value = GetCurrentScale().y;
3012       break;
3013     }
3014
3015     case Dali::Actor::Property::SCALE_Z:
3016     {
3017       value = GetCurrentScale().z;
3018       break;
3019     }
3020
3021     case Dali::Actor::Property::WORLD_SCALE:
3022     {
3023       value = GetCurrentWorldScale();
3024       break;
3025     }
3026
3027     case Dali::Actor::Property::VISIBLE:
3028     {
3029       value = IsVisible();
3030       break;
3031     }
3032
3033     case Dali::Actor::Property::COLOR:
3034     {
3035       value = GetCurrentColor();
3036       break;
3037     }
3038
3039     case Dali::Actor::Property::COLOR_RED:
3040     {
3041       value = GetCurrentColor().r;
3042       break;
3043     }
3044
3045     case Dali::Actor::Property::COLOR_GREEN:
3046     {
3047       value = GetCurrentColor().g;
3048       break;
3049     }
3050
3051     case Dali::Actor::Property::COLOR_BLUE:
3052     {
3053       value = GetCurrentColor().b;
3054       break;
3055     }
3056
3057     case Dali::Actor::Property::COLOR_ALPHA:
3058     {
3059       value = GetCurrentColor().a;
3060       break;
3061     }
3062
3063     case Dali::Actor::Property::WORLD_COLOR:
3064     {
3065       value = GetCurrentWorldColor();
3066       break;
3067     }
3068
3069     case Dali::Actor::Property::WORLD_MATRIX:
3070     {
3071       value = GetCurrentWorldMatrix();
3072       break;
3073     }
3074
3075     case Dali::Actor::Property::NAME:
3076     {
3077       value = GetName();
3078       break;
3079     }
3080
3081     case Dali::Actor::Property::SENSITIVE:
3082     {
3083       value = IsSensitive();
3084       break;
3085     }
3086
3087     case Dali::Actor::Property::LEAVE_REQUIRED:
3088     {
3089       value = GetLeaveRequired();
3090       break;
3091     }
3092
3093     case Dali::Actor::Property::INHERIT_POSITION:
3094     {
3095       value = IsPositionInherited();
3096       break;
3097     }
3098
3099     case Dali::Actor::Property::INHERIT_ORIENTATION:
3100     {
3101       value = IsOrientationInherited();
3102       break;
3103     }
3104
3105     case Dali::Actor::Property::INHERIT_SCALE:
3106     {
3107       value = IsScaleInherited();
3108       break;
3109     }
3110
3111     case Dali::Actor::Property::COLOR_MODE:
3112     {
3113       value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3114       break;
3115     }
3116
3117     case Dali::Actor::Property::POSITION_INHERITANCE:
3118     {
3119       value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3120       break;
3121     }
3122
3123     case Dali::Actor::Property::DRAW_MODE:
3124     {
3125       value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3126       break;
3127     }
3128
3129     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3130     {
3131       value = GetSizeModeFactor();
3132       break;
3133     }
3134
3135     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3136     {
3137       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3138       break;
3139     }
3140
3141     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3142     {
3143       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3144       break;
3145     }
3146
3147     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3148     {
3149       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3150       break;
3151     }
3152
3153     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3154     {
3155       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3156       break;
3157     }
3158
3159     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3160     {
3161       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3162       break;
3163     }
3164
3165     case Dali::Actor::Property::PADDING:
3166     {
3167       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3168       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3169       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3170       break;
3171     }
3172
3173     case Dali::Actor::Property::MINIMUM_SIZE:
3174     {
3175       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3176       break;
3177     }
3178
3179     case Dali::Actor::Property::MAXIMUM_SIZE:
3180     {
3181       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3182       break;
3183     }
3184
3185     case Dali::DevelActor::Property::BATCH_PARENT:
3186     {
3187       value = mIsBatchParent;
3188       break;
3189     }
3190
3191     case Dali::Actor::Property::CLIPPING_MODE:
3192     {
3193       value = mClippingMode;
3194       break;
3195     }
3196
3197     default:
3198     {
3199       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3200       break;
3201     }
3202   }
3203
3204   return value;
3205 }
3206
3207 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3208 {
3209   return mNode;
3210 }
3211
3212 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3213 {
3214   // This method should only return an object connected to the scene-graph
3215   return OnStage() ? mNode : NULL;
3216 }
3217
3218 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3219 {
3220   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3221
3222   const PropertyBase* property( NULL );
3223
3224   // This method should only return a property of an object connected to the scene-graph
3225   if( !OnStage() )
3226   {
3227     return property;
3228   }
3229
3230   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3231   {
3232     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3233     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3234
3235     property = animatable->GetSceneGraphProperty();
3236   }
3237   else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3238             ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3239   {
3240     CustomPropertyMetadata* custom = FindCustomProperty( index );
3241     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3242
3243     property = custom->GetSceneGraphProperty();
3244   }
3245   else if( NULL != mNode )
3246   {
3247     switch( index )
3248     {
3249       case Dali::Actor::Property::SIZE:
3250         property = &mNode->mSize;
3251         break;
3252
3253       case Dali::Actor::Property::SIZE_WIDTH:
3254         property = &mNode->mSize;
3255         break;
3256
3257       case Dali::Actor::Property::SIZE_HEIGHT:
3258         property = &mNode->mSize;
3259         break;
3260
3261       case Dali::Actor::Property::SIZE_DEPTH:
3262         property = &mNode->mSize;
3263         break;
3264
3265       case Dali::Actor::Property::POSITION:
3266         property = &mNode->mPosition;
3267         break;
3268
3269       case Dali::Actor::Property::POSITION_X:
3270         property = &mNode->mPosition;
3271         break;
3272
3273       case Dali::Actor::Property::POSITION_Y:
3274         property = &mNode->mPosition;
3275         break;
3276
3277       case Dali::Actor::Property::POSITION_Z:
3278         property = &mNode->mPosition;
3279         break;
3280
3281       case Dali::Actor::Property::ORIENTATION:
3282         property = &mNode->mOrientation;
3283         break;
3284
3285       case Dali::Actor::Property::SCALE:
3286         property = &mNode->mScale;
3287         break;
3288
3289       case Dali::Actor::Property::SCALE_X:
3290         property = &mNode->mScale;
3291         break;
3292
3293       case Dali::Actor::Property::SCALE_Y:
3294         property = &mNode->mScale;
3295         break;
3296
3297       case Dali::Actor::Property::SCALE_Z:
3298         property = &mNode->mScale;
3299         break;
3300
3301       case Dali::Actor::Property::VISIBLE:
3302         property = &mNode->mVisible;
3303         break;
3304
3305       case Dali::Actor::Property::COLOR:
3306         property = &mNode->mColor;
3307         break;
3308
3309       case Dali::Actor::Property::COLOR_RED:
3310         property = &mNode->mColor;
3311         break;
3312
3313       case Dali::Actor::Property::COLOR_GREEN:
3314         property = &mNode->mColor;
3315         break;
3316
3317       case Dali::Actor::Property::COLOR_BLUE:
3318         property = &mNode->mColor;
3319         break;
3320
3321       case Dali::Actor::Property::COLOR_ALPHA:
3322         property = &mNode->mColor;
3323         break;
3324
3325       default:
3326         break;
3327     }
3328   }
3329
3330   return property;
3331 }
3332
3333 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3334 {
3335   const PropertyInputImpl* property( NULL );
3336
3337   // This method should only return a property of an object connected to the scene-graph
3338   if( !OnStage() )
3339   {
3340     return property;
3341   }
3342
3343   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3344   {
3345     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3346     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3347
3348     property = animatable->GetSceneGraphProperty();
3349   }
3350   else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3351             ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3352   {
3353     CustomPropertyMetadata* custom = FindCustomProperty( index );
3354     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3355     property = custom->GetSceneGraphProperty();
3356   }
3357   else if( NULL != mNode )
3358   {
3359     switch( index )
3360     {
3361       case Dali::Actor::Property::PARENT_ORIGIN:
3362         property = &mNode->mParentOrigin;
3363         break;
3364
3365       case Dali::Actor::Property::PARENT_ORIGIN_X:
3366         property = &mNode->mParentOrigin;
3367         break;
3368
3369       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3370         property = &mNode->mParentOrigin;
3371         break;
3372
3373       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3374         property = &mNode->mParentOrigin;
3375         break;
3376
3377       case Dali::Actor::Property::ANCHOR_POINT:
3378         property = &mNode->mAnchorPoint;
3379         break;
3380
3381       case Dali::Actor::Property::ANCHOR_POINT_X:
3382         property = &mNode->mAnchorPoint;
3383         break;
3384
3385       case Dali::Actor::Property::ANCHOR_POINT_Y:
3386         property = &mNode->mAnchorPoint;
3387         break;
3388
3389       case Dali::Actor::Property::ANCHOR_POINT_Z:
3390         property = &mNode->mAnchorPoint;
3391         break;
3392
3393       case Dali::Actor::Property::SIZE:
3394         property = &mNode->mSize;
3395         break;
3396
3397       case Dali::Actor::Property::SIZE_WIDTH:
3398         property = &mNode->mSize;
3399         break;
3400
3401       case Dali::Actor::Property::SIZE_HEIGHT:
3402         property = &mNode->mSize;
3403         break;
3404
3405       case Dali::Actor::Property::SIZE_DEPTH:
3406         property = &mNode->mSize;
3407         break;
3408
3409       case Dali::Actor::Property::POSITION:
3410         property = &mNode->mPosition;
3411         break;
3412
3413       case Dali::Actor::Property::POSITION_X:
3414         property = &mNode->mPosition;
3415         break;
3416
3417       case Dali::Actor::Property::POSITION_Y:
3418         property = &mNode->mPosition;
3419         break;
3420
3421       case Dali::Actor::Property::POSITION_Z:
3422         property = &mNode->mPosition;
3423         break;
3424
3425       case Dali::Actor::Property::WORLD_POSITION:
3426         property = &mNode->mWorldPosition;
3427         break;
3428
3429       case Dali::Actor::Property::WORLD_POSITION_X:
3430         property = &mNode->mWorldPosition;
3431         break;
3432
3433       case Dali::Actor::Property::WORLD_POSITION_Y:
3434         property = &mNode->mWorldPosition;
3435         break;
3436
3437       case Dali::Actor::Property::WORLD_POSITION_Z:
3438         property = &mNode->mWorldPosition;
3439         break;
3440
3441       case Dali::Actor::Property::ORIENTATION:
3442         property = &mNode->mOrientation;
3443         break;
3444
3445       case Dali::Actor::Property::WORLD_ORIENTATION:
3446         property = &mNode->mWorldOrientation;
3447         break;
3448
3449       case Dali::Actor::Property::SCALE:
3450         property = &mNode->mScale;
3451         break;
3452
3453       case Dali::Actor::Property::SCALE_X:
3454         property = &mNode->mScale;
3455         break;
3456
3457       case Dali::Actor::Property::SCALE_Y:
3458         property = &mNode->mScale;
3459         break;
3460
3461       case Dali::Actor::Property::SCALE_Z:
3462         property = &mNode->mScale;
3463         break;
3464
3465       case Dali::Actor::Property::WORLD_SCALE:
3466         property = &mNode->mWorldScale;
3467         break;
3468
3469       case Dali::Actor::Property::VISIBLE:
3470         property = &mNode->mVisible;
3471         break;
3472
3473       case Dali::Actor::Property::COLOR:
3474         property = &mNode->mColor;
3475         break;
3476
3477       case Dali::Actor::Property::COLOR_RED:
3478         property = &mNode->mColor;
3479         break;
3480
3481       case Dali::Actor::Property::COLOR_GREEN:
3482         property = &mNode->mColor;
3483         break;
3484
3485       case Dali::Actor::Property::COLOR_BLUE:
3486         property = &mNode->mColor;
3487         break;
3488
3489       case Dali::Actor::Property::COLOR_ALPHA:
3490         property = &mNode->mColor;
3491         break;
3492
3493       case Dali::Actor::Property::WORLD_COLOR:
3494         property = &mNode->mWorldColor;
3495         break;
3496
3497       case Dali::Actor::Property::WORLD_MATRIX:
3498         property = &mNode->mWorldMatrix;
3499         break;
3500
3501       default:
3502         break;
3503     }
3504   }
3505
3506   return property;
3507 }
3508
3509 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3510 {
3511   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3512
3513   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3514   {
3515     // check whether the animatable property is registered already, if not then register one.
3516     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3517     if( animatableProperty )
3518     {
3519       componentIndex = animatableProperty->componentIndex;
3520     }
3521   }
3522   else
3523   {
3524     switch( index )
3525     {
3526       case Dali::Actor::Property::PARENT_ORIGIN_X:
3527       case Dali::Actor::Property::ANCHOR_POINT_X:
3528       case Dali::Actor::Property::SIZE_WIDTH:
3529       case Dali::Actor::Property::POSITION_X:
3530       case Dali::Actor::Property::WORLD_POSITION_X:
3531       case Dali::Actor::Property::SCALE_X:
3532       case Dali::Actor::Property::COLOR_RED:
3533       {
3534         componentIndex = 0;
3535         break;
3536       }
3537
3538       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3539       case Dali::Actor::Property::ANCHOR_POINT_Y:
3540       case Dali::Actor::Property::SIZE_HEIGHT:
3541       case Dali::Actor::Property::POSITION_Y:
3542       case Dali::Actor::Property::WORLD_POSITION_Y:
3543       case Dali::Actor::Property::SCALE_Y:
3544       case Dali::Actor::Property::COLOR_GREEN:
3545       {
3546         componentIndex = 1;
3547         break;
3548       }
3549
3550       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3551       case Dali::Actor::Property::ANCHOR_POINT_Z:
3552       case Dali::Actor::Property::SIZE_DEPTH:
3553       case Dali::Actor::Property::POSITION_Z:
3554       case Dali::Actor::Property::WORLD_POSITION_Z:
3555       case Dali::Actor::Property::SCALE_Z:
3556       case Dali::Actor::Property::COLOR_BLUE:
3557       {
3558         componentIndex = 2;
3559         break;
3560       }
3561
3562       case Dali::Actor::Property::COLOR_ALPHA:
3563       {
3564         componentIndex = 3;
3565         break;
3566       }
3567
3568       default:
3569       {
3570         // Do nothing
3571         break;
3572       }
3573     }
3574   }
3575
3576   return componentIndex;
3577 }
3578
3579 void Actor::SetParent( Actor* parent )
3580 {
3581   if( parent )
3582   {
3583     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3584
3585     mParent = parent;
3586
3587     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3588          parent->OnStage() )
3589     {
3590       // Instruct each actor to create a corresponding node in the scene graph
3591       ConnectToStage( parent->GetHierarchyDepth() );
3592     }
3593
3594     // Resolve the name and index for the child properties if any
3595     ResolveChildProperties();
3596   }
3597   else // parent being set to NULL
3598   {
3599     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3600
3601     mParent = NULL;
3602
3603     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3604          OnStage() )
3605     {
3606       DALI_ASSERT_ALWAYS( mNode != NULL );
3607
3608       if( NULL != mNode )
3609       {
3610         // Disconnect the Node & its children from the scene-graph.
3611         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3612       }
3613
3614       // Instruct each actor to discard pointers to the scene-graph
3615       DisconnectFromStage();
3616     }
3617   }
3618 }
3619
3620 SceneGraph::Node* Actor::CreateNode() const
3621 {
3622   return Node::New();
3623 }
3624
3625 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3626 {
3627   bool done = false;
3628   Actor* actor = dynamic_cast< Actor* >( object );
3629
3630   if( actor )
3631   {
3632     if( 0 == actionName.compare( ACTION_SHOW ) )
3633     {
3634       actor->SetVisible( true );
3635       done = true;
3636     }
3637     else if( 0 == actionName.compare( ACTION_HIDE ) )
3638     {
3639       actor->SetVisible( false );
3640       done = true;
3641     }
3642   }
3643
3644   return done;
3645 }
3646
3647 void Actor::EnsureRelayoutData()
3648 {
3649   // Assign relayout data.
3650   if( !mRelayoutData )
3651   {
3652     mRelayoutData = new RelayoutData();
3653   }
3654 }
3655
3656 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3657 {
3658   // Check if actor is dependent on parent
3659   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3660   {
3661     if( ( dimension & ( 1 << i ) ) )
3662     {
3663       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3664       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3665       {
3666         return true;
3667       }
3668     }
3669   }
3670
3671   return false;
3672 }
3673
3674 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3675 {
3676   // Check if actor is dependent on children
3677   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3678   {
3679     if( ( dimension & ( 1 << i ) ) )
3680     {
3681       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3682       switch( resizePolicy )
3683       {
3684         case ResizePolicy::FIT_TO_CHILDREN:
3685         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3686         {
3687           return true;
3688         }
3689
3690         default:
3691         {
3692           break;
3693         }
3694       }
3695     }
3696   }
3697
3698   return false;
3699 }
3700
3701 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3702 {
3703   return Actor::RelayoutDependentOnChildren( dimension );
3704 }
3705
3706 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3707 {
3708   // Check each possible dimension and see if it is dependent on the input one
3709   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3710   {
3711     if( dimension & ( 1 << i ) )
3712     {
3713       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3714     }
3715   }
3716
3717   return false;
3718 }
3719
3720 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3721 {
3722   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3723   {
3724     if( dimension & ( 1 << i ) )
3725     {
3726       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3727     }
3728   }
3729 }
3730
3731 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3732 {
3733   // If more than one dimension is requested, just return the first one found
3734   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3735   {
3736     if( ( dimension & ( 1 << i ) ) )
3737     {
3738       return mRelayoutData->negotiatedDimensions[ i ];
3739     }
3740   }
3741
3742   return 0.0f;   // Default
3743 }
3744
3745 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3746 {
3747   EnsureRelayoutData();
3748
3749   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3750   {
3751     if( dimension & ( 1 << i ) )
3752     {
3753       mRelayoutData->dimensionPadding[ i ] = padding;
3754     }
3755   }
3756 }
3757
3758 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3759 {
3760   if ( mRelayoutData )
3761   {
3762     // If more than one dimension is requested, just return the first one found
3763     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3764     {
3765       if( ( dimension & ( 1 << i ) ) )
3766       {
3767         return mRelayoutData->dimensionPadding[ i ];
3768       }
3769     }
3770   }
3771
3772   return GetDefaultDimensionPadding();
3773 }
3774
3775 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3776 {
3777   EnsureRelayoutData();
3778
3779   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3780   {
3781     if( dimension & ( 1 << i ) )
3782     {
3783       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3784     }
3785   }
3786 }
3787
3788 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3789 {
3790   if ( mRelayoutData )
3791   {
3792     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3793     {
3794       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3795       {
3796         return true;
3797       }
3798     }
3799   }
3800
3801   return false;
3802 }
3803
3804 float Actor::GetHeightForWidthBase( float width )
3805 {
3806   float height = 0.0f;
3807
3808   const Vector3 naturalSize = GetNaturalSize();
3809   if( naturalSize.width > 0.0f )
3810   {
3811     height = naturalSize.height * width / naturalSize.width;
3812   }
3813   else // we treat 0 as 1:1 aspect ratio
3814   {
3815     height = width;
3816   }
3817
3818   return height;
3819 }
3820
3821 float Actor::GetWidthForHeightBase( float height )
3822 {
3823   float width = 0.0f;
3824
3825   const Vector3 naturalSize = GetNaturalSize();
3826   if( naturalSize.height > 0.0f )
3827   {
3828     width = naturalSize.width * height / naturalSize.height;
3829   }
3830   else // we treat 0 as 1:1 aspect ratio
3831   {
3832     width = height;
3833   }
3834
3835   return width;
3836 }
3837
3838 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3839 {
3840   // Fill to parent, taking size mode factor into account
3841   switch( child.GetResizePolicy( dimension ) )
3842   {
3843     case ResizePolicy::FILL_TO_PARENT:
3844     {
3845       return GetLatestSize( dimension );
3846     }
3847
3848     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3849     {
3850       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3851     }
3852
3853     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3854     {
3855       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3856     }
3857
3858     default:
3859     {
3860       return GetLatestSize( dimension );
3861     }
3862   }
3863 }
3864
3865 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3866 {
3867   // Can be overridden in derived class
3868   return CalculateChildSizeBase( child, dimension );
3869 }
3870
3871 float Actor::GetHeightForWidth( float width )
3872 {
3873   // Can be overridden in derived class
3874   return GetHeightForWidthBase( width );
3875 }
3876
3877 float Actor::GetWidthForHeight( float height )
3878 {
3879   // Can be overridden in derived class
3880   return GetWidthForHeightBase( height );
3881 }
3882
3883 float Actor::GetLatestSize( Dimension::Type dimension ) const
3884 {
3885   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3886 }
3887
3888 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3889 {
3890   Vector2 padding = GetPadding( dimension );
3891
3892   return GetLatestSize( dimension ) + padding.x + padding.y;
3893 }
3894
3895 float Actor::NegotiateFromParent( Dimension::Type dimension )
3896 {
3897   Actor* parent = GetParent();
3898   if( parent )
3899   {
3900     Vector2 padding( GetPadding( dimension ) );
3901     Vector2 parentPadding( parent->GetPadding( dimension ) );
3902     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3903   }
3904
3905   return 0.0f;
3906 }
3907
3908 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3909 {
3910   float maxDimensionPoint = 0.0f;
3911
3912   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3913   {
3914     ActorPtr child = GetChildAt( i );
3915
3916     if( !child->RelayoutDependentOnParent( dimension ) )
3917     {
3918       // Calculate the min and max points that the children range across
3919       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3920       float dimensionSize = child->GetRelayoutSize( dimension );
3921       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3922     }
3923   }
3924
3925   return maxDimensionPoint;
3926 }
3927
3928 float Actor::GetSize( Dimension::Type dimension ) const
3929 {
3930   return GetDimensionValue( GetTargetSize(), dimension );
3931 }
3932
3933 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3934 {
3935   return GetDimensionValue( GetNaturalSize(), dimension );
3936 }
3937
3938 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3939 {
3940   switch( GetResizePolicy( dimension ) )
3941   {
3942     case ResizePolicy::USE_NATURAL_SIZE:
3943     {
3944       return GetNaturalSize( dimension );
3945     }
3946
3947     case ResizePolicy::FIXED:
3948     {
3949       return GetDimensionValue( GetPreferredSize(), dimension );
3950     }
3951
3952     case ResizePolicy::USE_ASSIGNED_SIZE:
3953     {
3954       return GetDimensionValue( maximumSize, dimension );
3955     }
3956
3957     case ResizePolicy::FILL_TO_PARENT:
3958     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3959     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3960     {
3961       return NegotiateFromParent( dimension );
3962     }
3963
3964     case ResizePolicy::FIT_TO_CHILDREN:
3965     {
3966       return NegotiateFromChildren( dimension );
3967     }
3968
3969     case ResizePolicy::DIMENSION_DEPENDENCY:
3970     {
3971       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3972
3973       // Custom rules
3974       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3975       {
3976         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3977       }
3978
3979       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3980       {
3981         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3982       }
3983
3984       break;
3985     }
3986
3987     default:
3988     {
3989       break;
3990     }
3991   }
3992
3993   return 0.0f;  // Default
3994 }
3995
3996 float Actor::ClampDimension( float size, Dimension::Type dimension )
3997 {
3998   const float minSize = GetMinimumSize( dimension );
3999   const float maxSize = GetMaximumSize( dimension );
4000
4001   return std::max( minSize, std::min( size, maxSize ) );
4002 }
4003
4004 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4005 {
4006   // Check if it needs to be negotiated
4007   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4008   {
4009     // Check that we havn't gotten into an infinite loop
4010     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4011     bool recursionFound = false;
4012     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4013     {
4014       if( *it == searchActor )
4015       {
4016         recursionFound = true;
4017         break;
4018       }
4019     }
4020
4021     if( !recursionFound )
4022     {
4023       // Record the path that we have taken
4024       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4025
4026       // Dimension dependency check
4027       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4028       {
4029         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4030
4031         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4032         {
4033           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4034         }
4035       }
4036
4037       // Parent dependency check
4038       Actor* parent = GetParent();
4039       if( parent && RelayoutDependentOnParent( dimension ) )
4040       {
4041         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4042       }
4043
4044       // Children dependency check
4045       if( RelayoutDependentOnChildren( dimension ) )
4046       {
4047         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4048         {
4049           ActorPtr child = GetChildAt( i );
4050
4051           // Only relayout child first if it is not dependent on this actor
4052           if( !child->RelayoutDependentOnParent( dimension ) )
4053           {
4054             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4055           }
4056         }
4057       }
4058
4059       // For deriving classes
4060       OnCalculateRelayoutSize( dimension );
4061
4062       // All dependencies checked, calculate the size and set negotiated flag
4063       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4064
4065       SetNegotiatedDimension( newSize, dimension );
4066       SetLayoutNegotiated( true, dimension );
4067
4068       // For deriving classes
4069       OnLayoutNegotiated( newSize, dimension );
4070
4071       // This actor has been successfully processed, pop it off the recursion stack
4072       recursionStack.pop_back();
4073     }
4074     else
4075     {
4076       // TODO: Break infinite loop
4077       SetLayoutNegotiated( true, dimension );
4078     }
4079   }
4080 }
4081
4082 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4083 {
4084   // Negotiate all dimensions that require it
4085   ActorDimensionStack recursionStack;
4086
4087   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4088   {
4089     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4090
4091     // Negotiate
4092     NegotiateDimension( dimension, allocatedSize, recursionStack );
4093   }
4094 }
4095
4096 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4097 {
4098   switch( mRelayoutData->sizeSetPolicy )
4099   {
4100     case SizeScalePolicy::USE_SIZE_SET:
4101     {
4102       return size;
4103     }
4104
4105     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4106     {
4107       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4108       const Vector3 naturalSize = GetNaturalSize();
4109       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4110       {
4111         const float sizeRatio = size.width / size.height;
4112         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4113
4114         if( naturalSizeRatio < sizeRatio )
4115         {
4116           return Vector2( naturalSizeRatio * size.height, size.height );
4117         }
4118         else if( naturalSizeRatio > sizeRatio )
4119         {
4120           return Vector2( size.width, size.width / naturalSizeRatio );
4121         }
4122         else
4123         {
4124           return size;
4125         }
4126       }
4127
4128       break;
4129     }
4130
4131     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4132     {
4133       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4134       const Vector3 naturalSize = GetNaturalSize();
4135       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4136       {
4137         const float sizeRatio = size.width / size.height;
4138         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4139
4140         if( naturalSizeRatio < sizeRatio )
4141         {
4142           return Vector2( size.width, size.width / naturalSizeRatio );
4143         }
4144         else if( naturalSizeRatio > sizeRatio )
4145         {
4146           return Vector2( naturalSizeRatio * size.height, size.height );
4147         }
4148         else
4149         {
4150           return size;
4151         }
4152       }
4153       break;
4154     }
4155
4156     default:
4157     {
4158       break;
4159     }
4160   }
4161
4162   return size;
4163 }
4164
4165 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4166 {
4167   // Do the set actor size
4168   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4169
4170   // Adjust for size set policy
4171   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4172
4173   // Lock the flag to stop recursive relayouts on set size
4174   mRelayoutData->insideRelayout = true;
4175   SetSize( negotiatedSize );
4176   mRelayoutData->insideRelayout = false;
4177
4178   // Clear flags for all dimensions
4179   SetLayoutDirty( false );
4180
4181   // Give deriving classes a chance to respond
4182   OnRelayout( negotiatedSize, container );
4183
4184   if( !mOnRelayoutSignal.Empty() )
4185   {
4186     Dali::Actor handle( this );
4187     mOnRelayoutSignal.Emit( handle );
4188   }
4189 }
4190
4191 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4192 {
4193   // Force a size negotiation for actors that has assigned size during relayout
4194   // This is required as otherwise the flags that force a relayout will not
4195   // necessarilly be set. This will occur if the actor has already been laid out.
4196   // The dirty flags are then cleared. Then if the actor is added back into the
4197   // relayout container afterwards, the dirty flags would still be clear...
4198   // causing a relayout to be skipped. Here we force any actors added to the
4199   // container to be relayed out.
4200   if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4201   {
4202     SetLayoutNegotiated(false, Dimension::WIDTH);
4203   }
4204   if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4205   {
4206     SetLayoutNegotiated(false, Dimension::HEIGHT);
4207   }
4208
4209   // Do the negotiation
4210   NegotiateDimensions( allocatedSize );
4211
4212   // Set the actor size
4213   SetNegotiatedSize( container );
4214
4215   // Negotiate down to children
4216   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4217
4218   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4219   {
4220     ActorPtr child = GetChildAt( i );
4221
4222     // Forces children that have already been laid out to be relayed out
4223     // if they have assigned size during relayout.
4224     if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4225     {
4226       child->SetLayoutNegotiated(false, Dimension::WIDTH);
4227       child->SetLayoutDirty(true, Dimension::WIDTH);
4228     }
4229     if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4230     {
4231       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4232       child->SetLayoutDirty(true, Dimension::HEIGHT);
4233     }
4234
4235     // Only relayout if required
4236     if( child->RelayoutRequired() )
4237     {
4238       container.Add( Dali::Actor( child.Get() ), newBounds );
4239     }
4240   }
4241 }
4242
4243 void Actor::RelayoutRequest( Dimension::Type dimension )
4244 {
4245   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4246   if( relayoutController )
4247   {
4248     Dali::Actor self( this );
4249     relayoutController->RequestRelayout( self, dimension );
4250   }
4251 }
4252
4253 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4254 {
4255 }
4256
4257 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4258 {
4259 }
4260
4261 void Actor::SetPreferredSize( const Vector2& size )
4262 {
4263   EnsureRelayoutData();
4264
4265   if( size.width > 0.0f )
4266   {
4267     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4268   }
4269
4270   if( size.height > 0.0f )
4271   {
4272     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4273   }
4274
4275   mRelayoutData->preferredSize = size;
4276
4277   RelayoutRequest();
4278 }
4279
4280 Vector2 Actor::GetPreferredSize() const
4281 {
4282   if ( mRelayoutData )
4283   {
4284     return Vector2( mRelayoutData->preferredSize );
4285   }
4286
4287   return GetDefaultPreferredSize();
4288 }
4289
4290 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4291 {
4292   EnsureRelayoutData();
4293
4294   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4295   {
4296     if( dimension & ( 1 << i ) )
4297     {
4298       mRelayoutData->minimumSize[ i ] = size;
4299     }
4300   }
4301
4302   RelayoutRequest();
4303 }
4304
4305 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4306 {
4307   if ( mRelayoutData )
4308   {
4309     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4310     {
4311       if( dimension & ( 1 << i ) )
4312       {
4313         return mRelayoutData->minimumSize[ i ];
4314       }
4315     }
4316   }
4317
4318   return 0.0f;  // Default
4319 }
4320
4321 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4322 {
4323   EnsureRelayoutData();
4324
4325   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4326   {
4327     if( dimension & ( 1 << i ) )
4328     {
4329       mRelayoutData->maximumSize[ i ] = size;
4330     }
4331   }
4332
4333   RelayoutRequest();
4334 }
4335
4336 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4337 {
4338   if ( mRelayoutData )
4339   {
4340     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4341     {
4342       if( dimension & ( 1 << i ) )
4343       {
4344         return mRelayoutData->maximumSize[ i ];
4345       }
4346     }
4347   }
4348
4349   return FLT_MAX;  // Default
4350 }
4351
4352 Object* Actor::GetParentObject() const
4353 {
4354   return mParent;
4355 }
4356
4357 } // namespace Internal
4358
4359 } // namespace Dali