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