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