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