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