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