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