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