[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,  false, 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 Rect<> Actor::CalculateScreenExtents( ) const
3483 {
3484   auto screenPosition = GetCurrentScreenPosition();
3485   Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
3486   Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
3487   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
3488   return { position.x, position.y, size.x, size.y };
3489 }
3490
3491 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3492 {
3493   bool valueSet = true;
3494
3495   switch( index )
3496   {
3497     case Dali::Actor::Property::PARENT_ORIGIN:
3498     {
3499       value = GetCurrentParentOrigin();
3500       break;
3501     }
3502
3503     case Dali::Actor::Property::PARENT_ORIGIN_X:
3504     {
3505       value = GetCurrentParentOrigin().x;
3506       break;
3507     }
3508
3509     case Dali::Actor::Property::PARENT_ORIGIN_Y:
3510     {
3511       value = GetCurrentParentOrigin().y;
3512       break;
3513     }
3514
3515     case Dali::Actor::Property::PARENT_ORIGIN_Z:
3516     {
3517       value = GetCurrentParentOrigin().z;
3518       break;
3519     }
3520
3521     case Dali::Actor::Property::ANCHOR_POINT:
3522     {
3523       value = GetCurrentAnchorPoint();
3524       break;
3525     }
3526
3527     case Dali::Actor::Property::ANCHOR_POINT_X:
3528     {
3529       value = GetCurrentAnchorPoint().x;
3530       break;
3531     }
3532
3533     case Dali::Actor::Property::ANCHOR_POINT_Y:
3534     {
3535       value = GetCurrentAnchorPoint().y;
3536       break;
3537     }
3538
3539     case Dali::Actor::Property::ANCHOR_POINT_Z:
3540     {
3541       value = GetCurrentAnchorPoint().z;
3542       break;
3543     }
3544
3545     case Dali::Actor::Property::SIZE:
3546     {
3547       value = GetTargetSize();
3548       break;
3549     }
3550
3551     case Dali::Actor::Property::SIZE_WIDTH:
3552     {
3553       value = GetTargetSize().width;
3554       break;
3555     }
3556
3557     case Dali::Actor::Property::SIZE_HEIGHT:
3558     {
3559       value = GetTargetSize().height;
3560       break;
3561     }
3562
3563     case Dali::Actor::Property::SIZE_DEPTH:
3564     {
3565       value = GetTargetSize().depth;
3566       break;
3567     }
3568
3569     case Dali::Actor::Property::POSITION:
3570     {
3571       value = GetTargetPosition();
3572       break;
3573     }
3574
3575     case Dali::Actor::Property::POSITION_X:
3576     {
3577       value = GetTargetPosition().x;
3578       break;
3579     }
3580
3581     case Dali::Actor::Property::POSITION_Y:
3582     {
3583       value = GetTargetPosition().y;
3584       break;
3585     }
3586
3587     case Dali::Actor::Property::POSITION_Z:
3588     {
3589       value = GetTargetPosition().z;
3590       break;
3591     }
3592
3593     case Dali::Actor::Property::ORIENTATION:
3594     {
3595       value = mTargetOrientation;
3596       break;
3597     }
3598
3599     case Dali::Actor::Property::SCALE:
3600     {
3601       value = mTargetScale;
3602       break;
3603     }
3604
3605     case Dali::Actor::Property::SCALE_X:
3606     {
3607       value = mTargetScale.x;
3608       break;
3609     }
3610
3611     case Dali::Actor::Property::SCALE_Y:
3612     {
3613       value = mTargetScale.y;
3614       break;
3615     }
3616
3617     case Dali::Actor::Property::SCALE_Z:
3618     {
3619       value = mTargetScale.z;
3620       break;
3621     }
3622
3623     case Dali::Actor::Property::VISIBLE:
3624     {
3625       value = mVisible;
3626       break;
3627     }
3628
3629     case Dali::Actor::Property::COLOR:
3630     {
3631       value = mTargetColor;
3632       break;
3633     }
3634
3635     case Dali::Actor::Property::COLOR_RED:
3636     {
3637       value = mTargetColor.r;
3638       break;
3639     }
3640
3641     case Dali::Actor::Property::COLOR_GREEN:
3642     {
3643       value = mTargetColor.g;
3644       break;
3645     }
3646
3647     case Dali::Actor::Property::COLOR_BLUE:
3648     {
3649       value = mTargetColor.b;
3650       break;
3651     }
3652
3653     case Dali::Actor::Property::COLOR_ALPHA:
3654     case Dali::DevelActor::Property::OPACITY:
3655     {
3656       value = mTargetColor.a;
3657       break;
3658     }
3659
3660     case Dali::Actor::Property::NAME:
3661     {
3662       value = GetName();
3663       break;
3664     }
3665
3666     case Dali::Actor::Property::SENSITIVE:
3667     {
3668       value = IsSensitive();
3669       break;
3670     }
3671
3672     case Dali::Actor::Property::LEAVE_REQUIRED:
3673     {
3674       value = GetLeaveRequired();
3675       break;
3676     }
3677
3678     case Dali::Actor::Property::INHERIT_POSITION:
3679     {
3680       value = IsPositionInherited();
3681       break;
3682     }
3683
3684     case Dali::Actor::Property::INHERIT_ORIENTATION:
3685     {
3686       value = IsOrientationInherited();
3687       break;
3688     }
3689
3690     case Dali::Actor::Property::INHERIT_SCALE:
3691     {
3692       value = IsScaleInherited();
3693       break;
3694     }
3695
3696     case Dali::Actor::Property::COLOR_MODE:
3697     {
3698       value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3699       break;
3700     }
3701
3702     case Dali::Actor::Property::DRAW_MODE:
3703     {
3704       value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3705       break;
3706     }
3707
3708     case Dali::Actor::Property::SIZE_MODE_FACTOR:
3709     {
3710       value = GetSizeModeFactor();
3711       break;
3712     }
3713
3714     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3715     {
3716       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3717       break;
3718     }
3719
3720     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3721     {
3722       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3723       break;
3724     }
3725
3726     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3727     {
3728       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3729       break;
3730     }
3731
3732     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3733     {
3734       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3735       break;
3736     }
3737
3738     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3739     {
3740       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3741       break;
3742     }
3743
3744     case Dali::Actor::Property::PADDING:
3745     {
3746       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3747       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3748       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3749       break;
3750     }
3751
3752     case Dali::Actor::Property::MINIMUM_SIZE:
3753     {
3754       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3755       break;
3756     }
3757
3758     case Dali::Actor::Property::MAXIMUM_SIZE:
3759     {
3760       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3761       break;
3762     }
3763
3764     case Dali::Actor::Property::CLIPPING_MODE:
3765     {
3766       value = mClippingMode;
3767       break;
3768     }
3769
3770     case Dali::DevelActor::Property::SIBLING_ORDER:
3771     {
3772       value = static_cast<int>( GetSiblingOrder() );
3773       break;
3774     }
3775
3776     case Dali::DevelActor::Property::SCREEN_POSITION:
3777     {
3778       value = GetCurrentScreenPosition();
3779       break;
3780     }
3781
3782     case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3783     {
3784       value = mPositionUsesAnchorPoint;
3785       break;
3786     }
3787
3788     case Dali::Actor::Property::LAYOUT_DIRECTION:
3789     {
3790       value = mLayoutDirection;
3791       break;
3792     }
3793
3794     case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3795     {
3796       value = IsLayoutDirectionInherited();
3797       break;
3798     }
3799
3800     default:
3801     {
3802       // Must be a scene-graph only property
3803       valueSet = false;
3804       break;
3805     }
3806   }
3807
3808   return valueSet;
3809 }
3810
3811 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value  ) const
3812 {
3813   bool valueSet = true;
3814
3815   switch( index )
3816   {
3817     case Dali::Actor::Property::SIZE:
3818     {
3819       value = GetCurrentSize();
3820       break;
3821     }
3822
3823     case Dali::Actor::Property::SIZE_WIDTH:
3824     {
3825       value = GetCurrentSize().width;
3826       break;
3827     }
3828
3829     case Dali::Actor::Property::SIZE_HEIGHT:
3830     {
3831       value = GetCurrentSize().height;
3832       break;
3833     }
3834
3835     case Dali::Actor::Property::SIZE_DEPTH:
3836     {
3837       value = GetCurrentSize().depth;
3838       break;
3839     }
3840
3841     case Dali::Actor::Property::POSITION:
3842     {
3843       value = GetCurrentPosition();
3844       break;
3845     }
3846
3847     case Dali::Actor::Property::POSITION_X:
3848     {
3849       value = GetCurrentPosition().x;
3850       break;
3851     }
3852
3853     case Dali::Actor::Property::POSITION_Y:
3854     {
3855       value = GetCurrentPosition().y;
3856       break;
3857     }
3858
3859     case Dali::Actor::Property::POSITION_Z:
3860     {
3861       value = GetCurrentPosition().z;
3862       break;
3863     }
3864
3865     case Dali::Actor::Property::WORLD_POSITION:
3866     {
3867       value = GetCurrentWorldPosition();
3868       break;
3869     }
3870
3871     case Dali::Actor::Property::WORLD_POSITION_X:
3872     {
3873       value = GetCurrentWorldPosition().x;
3874       break;
3875     }
3876
3877     case Dali::Actor::Property::WORLD_POSITION_Y:
3878     {
3879       value = GetCurrentWorldPosition().y;
3880       break;
3881     }
3882
3883     case Dali::Actor::Property::WORLD_POSITION_Z:
3884     {
3885       value = GetCurrentWorldPosition().z;
3886       break;
3887     }
3888
3889     case Dali::Actor::Property::ORIENTATION:
3890     {
3891       value = GetCurrentOrientation();
3892       break;
3893     }
3894
3895     case Dali::Actor::Property::WORLD_ORIENTATION:
3896     {
3897       value = GetCurrentWorldOrientation();
3898       break;
3899     }
3900
3901     case Dali::Actor::Property::SCALE:
3902     {
3903       value = GetCurrentScale();
3904       break;
3905     }
3906
3907     case Dali::Actor::Property::SCALE_X:
3908     {
3909       value = GetCurrentScale().x;
3910       break;
3911     }
3912
3913     case Dali::Actor::Property::SCALE_Y:
3914     {
3915       value = GetCurrentScale().y;
3916       break;
3917     }
3918
3919     case Dali::Actor::Property::SCALE_Z:
3920     {
3921       value = GetCurrentScale().z;
3922       break;
3923     }
3924
3925     case Dali::Actor::Property::WORLD_SCALE:
3926     {
3927       value = GetCurrentWorldScale();
3928       break;
3929     }
3930
3931     case Dali::Actor::Property::COLOR:
3932     {
3933       value = GetCurrentColor();
3934       break;
3935     }
3936
3937     case Dali::Actor::Property::COLOR_RED:
3938     {
3939       value = GetCurrentColor().r;
3940       break;
3941     }
3942
3943     case Dali::Actor::Property::COLOR_GREEN:
3944     {
3945       value = GetCurrentColor().g;
3946       break;
3947     }
3948
3949     case Dali::Actor::Property::COLOR_BLUE:
3950     {
3951       value = GetCurrentColor().b;
3952       break;
3953     }
3954
3955     case Dali::Actor::Property::COLOR_ALPHA:
3956     case Dali::DevelActor::Property::OPACITY:
3957     {
3958       value = GetCurrentColor().a;
3959       break;
3960     }
3961
3962     case Dali::Actor::Property::WORLD_COLOR:
3963     {
3964       value = GetCurrentWorldColor();
3965       break;
3966     }
3967
3968     case Dali::Actor::Property::WORLD_MATRIX:
3969     {
3970       value = GetCurrentWorldMatrix();
3971       break;
3972     }
3973
3974     case Dali::Actor::Property::VISIBLE:
3975     {
3976       value = IsVisible();
3977       break;
3978     }
3979
3980     case DevelActor::Property::CULLED:
3981     {
3982       value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3983       break;
3984     }
3985
3986     case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
3987     {
3988       value = GetUpdateSizeHint();
3989       break;
3990     }
3991
3992     default:
3993     {
3994       // Must be an event-side only property
3995       valueSet = false;
3996       break;
3997     }
3998   }
3999
4000   return valueSet;
4001 }
4002
4003 void Actor::EnsureRelayoutData()
4004 {
4005   // Assign relayout data.
4006   if( !mRelayoutData )
4007   {
4008     mRelayoutData = new RelayoutData();
4009   }
4010 }
4011
4012 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4013 {
4014   // Check if actor is dependent on parent
4015   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4016   {
4017     if( ( dimension & ( 1 << i ) ) )
4018     {
4019       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4020       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4021       {
4022         return true;
4023       }
4024     }
4025   }
4026
4027   return false;
4028 }
4029
4030 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4031 {
4032   // Check if actor is dependent on children
4033   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4034   {
4035     if( ( dimension & ( 1 << i ) ) )
4036     {
4037       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4038       switch( resizePolicy )
4039       {
4040         case ResizePolicy::FIT_TO_CHILDREN:
4041         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
4042         {
4043           return true;
4044         }
4045
4046         default:
4047         {
4048           break;
4049         }
4050       }
4051     }
4052   }
4053
4054   return false;
4055 }
4056
4057 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4058 {
4059   return Actor::RelayoutDependentOnChildren( dimension );
4060 }
4061
4062 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4063 {
4064   // Check each possible dimension and see if it is dependent on the input one
4065   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4066   {
4067     if( dimension & ( 1 << i ) )
4068     {
4069       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4070     }
4071   }
4072
4073   return false;
4074 }
4075
4076 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4077 {
4078   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4079   {
4080     if( dimension & ( 1 << i ) )
4081     {
4082       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4083     }
4084   }
4085 }
4086
4087 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4088 {
4089   // If more than one dimension is requested, just return the first one found
4090   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4091   {
4092     if( ( dimension & ( 1 << i ) ) )
4093     {
4094       return mRelayoutData->negotiatedDimensions[ i ];
4095     }
4096   }
4097
4098   return 0.0f;   // Default
4099 }
4100
4101 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4102 {
4103   EnsureRelayoutData();
4104
4105   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4106   {
4107     if( dimension & ( 1 << i ) )
4108     {
4109       mRelayoutData->dimensionPadding[ i ] = padding;
4110     }
4111   }
4112 }
4113
4114 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4115 {
4116   if ( mRelayoutData )
4117   {
4118     // If more than one dimension is requested, just return the first one found
4119     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4120     {
4121       if( ( dimension & ( 1 << i ) ) )
4122       {
4123         return mRelayoutData->dimensionPadding[ i ];
4124       }
4125     }
4126   }
4127
4128   return GetDefaultDimensionPadding();
4129 }
4130
4131 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4132 {
4133   EnsureRelayoutData();
4134
4135   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4136   {
4137     if( dimension & ( 1 << i ) )
4138     {
4139       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4140     }
4141   }
4142 }
4143
4144 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4145 {
4146   if ( mRelayoutData )
4147   {
4148     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4149     {
4150       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4151       {
4152         return true;
4153       }
4154     }
4155   }
4156
4157   return false;
4158 }
4159
4160 float Actor::GetHeightForWidthBase( float width )
4161 {
4162   float height = 0.0f;
4163
4164   const Vector3 naturalSize = GetNaturalSize();
4165   if( naturalSize.width > 0.0f )
4166   {
4167     height = naturalSize.height * width / naturalSize.width;
4168   }
4169   else // we treat 0 as 1:1 aspect ratio
4170   {
4171     height = width;
4172   }
4173
4174   return height;
4175 }
4176
4177 float Actor::GetWidthForHeightBase( float height )
4178 {
4179   float width = 0.0f;
4180
4181   const Vector3 naturalSize = GetNaturalSize();
4182   if( naturalSize.height > 0.0f )
4183   {
4184     width = naturalSize.width * height / naturalSize.height;
4185   }
4186   else // we treat 0 as 1:1 aspect ratio
4187   {
4188     width = height;
4189   }
4190
4191   return width;
4192 }
4193
4194 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4195 {
4196   // Fill to parent, taking size mode factor into account
4197   switch( child.GetResizePolicy( dimension ) )
4198   {
4199     case ResizePolicy::FILL_TO_PARENT:
4200     {
4201       return GetLatestSize( dimension );
4202     }
4203
4204     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4205     {
4206       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4207     }
4208
4209     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4210     {
4211       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4212     }
4213
4214     default:
4215     {
4216       return GetLatestSize( dimension );
4217     }
4218   }
4219 }
4220
4221 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4222 {
4223   // Can be overridden in derived class
4224   return CalculateChildSizeBase( child, dimension );
4225 }
4226
4227 float Actor::GetHeightForWidth( float width )
4228 {
4229   // Can be overridden in derived class
4230   return GetHeightForWidthBase( width );
4231 }
4232
4233 float Actor::GetWidthForHeight( float height )
4234 {
4235   // Can be overridden in derived class
4236   return GetWidthForHeightBase( height );
4237 }
4238
4239 float Actor::GetLatestSize( Dimension::Type dimension ) const
4240 {
4241   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4242 }
4243
4244 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4245 {
4246   Vector2 padding = GetPadding( dimension );
4247
4248   return GetLatestSize( dimension ) + padding.x + padding.y;
4249 }
4250
4251 float Actor::NegotiateFromParent( Dimension::Type dimension )
4252 {
4253   Actor* parent = GetParent();
4254   if( parent )
4255   {
4256     Vector2 padding( GetPadding( dimension ) );
4257     Vector2 parentPadding( parent->GetPadding( dimension ) );
4258     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4259   }
4260
4261   return 0.0f;
4262 }
4263
4264 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4265 {
4266   float maxDimensionPoint = 0.0f;
4267
4268   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4269   {
4270     ActorPtr child = GetChildAt( i );
4271
4272     if( !child->RelayoutDependentOnParent( dimension ) )
4273     {
4274       // Calculate the min and max points that the children range across
4275       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4276       float dimensionSize = child->GetRelayoutSize( dimension );
4277       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4278     }
4279   }
4280
4281   return maxDimensionPoint;
4282 }
4283
4284 float Actor::GetSize( Dimension::Type dimension ) const
4285 {
4286   return GetDimensionValue( mTargetSize, dimension );
4287 }
4288
4289 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4290 {
4291   return GetDimensionValue( GetNaturalSize(), dimension );
4292 }
4293
4294 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4295 {
4296   switch( GetResizePolicy( dimension ) )
4297   {
4298     case ResizePolicy::USE_NATURAL_SIZE:
4299     {
4300       return GetNaturalSize( dimension );
4301     }
4302
4303     case ResizePolicy::FIXED:
4304     {
4305       return GetDimensionValue( GetPreferredSize(), dimension );
4306     }
4307
4308     case ResizePolicy::USE_ASSIGNED_SIZE:
4309     {
4310       return GetDimensionValue( maximumSize, dimension );
4311     }
4312
4313     case ResizePolicy::FILL_TO_PARENT:
4314     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4315     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4316     {
4317       return NegotiateFromParent( dimension );
4318     }
4319
4320     case ResizePolicy::FIT_TO_CHILDREN:
4321     {
4322       return NegotiateFromChildren( dimension );
4323     }
4324
4325     case ResizePolicy::DIMENSION_DEPENDENCY:
4326     {
4327       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4328
4329       // Custom rules
4330       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4331       {
4332         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4333       }
4334
4335       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4336       {
4337         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4338       }
4339
4340       break;
4341     }
4342
4343     default:
4344     {
4345       break;
4346     }
4347   }
4348
4349   return 0.0f;  // Default
4350 }
4351
4352 float Actor::ClampDimension( float size, Dimension::Type dimension )
4353 {
4354   const float minSize = GetMinimumSize( dimension );
4355   const float maxSize = GetMaximumSize( dimension );
4356
4357   return std::max( minSize, std::min( size, maxSize ) );
4358 }
4359
4360 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4361 {
4362   // Check if it needs to be negotiated
4363   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4364   {
4365     // Check that we havn't gotten into an infinite loop
4366     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4367     bool recursionFound = false;
4368     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4369     {
4370       if( *it == searchActor )
4371       {
4372         recursionFound = true;
4373         break;
4374       }
4375     }
4376
4377     if( !recursionFound )
4378     {
4379       // Record the path that we have taken
4380       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4381
4382       // Dimension dependency check
4383       for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4384       {
4385         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4386
4387         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4388         {
4389           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4390         }
4391       }
4392
4393       // Parent dependency check
4394       Actor* parent = GetParent();
4395       if( parent && RelayoutDependentOnParent( dimension ) )
4396       {
4397         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4398       }
4399
4400       // Children dependency check
4401       if( RelayoutDependentOnChildren( dimension ) )
4402       {
4403         for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4404         {
4405           ActorPtr child = GetChildAt( i );
4406
4407           // Only relayout child first if it is not dependent on this actor
4408           if( !child->RelayoutDependentOnParent( dimension ) )
4409           {
4410             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4411           }
4412         }
4413       }
4414
4415       // For deriving classes
4416       OnCalculateRelayoutSize( dimension );
4417
4418       // All dependencies checked, calculate the size and set negotiated flag
4419       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4420
4421       SetNegotiatedDimension( newSize, dimension );
4422       SetLayoutNegotiated( true, dimension );
4423
4424       // For deriving classes
4425       OnLayoutNegotiated( newSize, dimension );
4426
4427       // This actor has been successfully processed, pop it off the recursion stack
4428       recursionStack.pop_back();
4429     }
4430     else
4431     {
4432       // TODO: Break infinite loop
4433       SetLayoutNegotiated( true, dimension );
4434     }
4435   }
4436 }
4437
4438 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4439 {
4440   // Negotiate all dimensions that require it
4441   ActorDimensionStack recursionStack;
4442
4443   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4444   {
4445     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4446
4447     // Negotiate
4448     NegotiateDimension( dimension, allocatedSize, recursionStack );
4449   }
4450 }
4451
4452 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4453 {
4454   switch( mRelayoutData->sizeSetPolicy )
4455   {
4456     case SizeScalePolicy::USE_SIZE_SET:
4457     {
4458       return size;
4459     }
4460
4461     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4462     {
4463       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4464       const Vector3 naturalSize = GetNaturalSize();
4465       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4466       {
4467         const float sizeRatio = size.width / size.height;
4468         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4469
4470         if( naturalSizeRatio < sizeRatio )
4471         {
4472           return Vector2( naturalSizeRatio * size.height, size.height );
4473         }
4474         else if( naturalSizeRatio > sizeRatio )
4475         {
4476           return Vector2( size.width, size.width / naturalSizeRatio );
4477         }
4478         else
4479         {
4480           return size;
4481         }
4482       }
4483
4484       break;
4485     }
4486
4487     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4488     {
4489       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4490       const Vector3 naturalSize = GetNaturalSize();
4491       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4492       {
4493         const float sizeRatio = size.width / size.height;
4494         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4495
4496         if( naturalSizeRatio < sizeRatio )
4497         {
4498           return Vector2( size.width, size.width / naturalSizeRatio );
4499         }
4500         else if( naturalSizeRatio > sizeRatio )
4501         {
4502           return Vector2( naturalSizeRatio * size.height, size.height );
4503         }
4504         else
4505         {
4506           return size;
4507         }
4508       }
4509       break;
4510     }
4511
4512     default:
4513     {
4514       break;
4515     }
4516   }
4517
4518   return size;
4519 }
4520
4521 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4522 {
4523   // Do the set actor size
4524   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4525
4526   // Adjust for size set policy
4527   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4528
4529   // Lock the flag to stop recursive relayouts on set size
4530   mRelayoutData->insideRelayout = true;
4531   SetSize( negotiatedSize );
4532   mRelayoutData->insideRelayout = false;
4533
4534   // Clear flags for all dimensions
4535   SetLayoutDirty( false );
4536
4537   // Give deriving classes a chance to respond
4538   OnRelayout( negotiatedSize, container );
4539
4540   if( !mOnRelayoutSignal.Empty() )
4541   {
4542     Dali::Actor handle( this );
4543     mOnRelayoutSignal.Emit( handle );
4544   }
4545 }
4546
4547 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4548 {
4549   // Force a size negotiation for actors that has assigned size during relayout
4550   // This is required as otherwise the flags that force a relayout will not
4551   // necessarilly be set. This will occur if the actor has already been laid out.
4552   // The dirty flags are then cleared. Then if the actor is added back into the
4553   // relayout container afterwards, the dirty flags would still be clear...
4554   // causing a relayout to be skipped. Here we force any actors added to the
4555   // container to be relayed out.
4556   DALI_LOG_TIMER_START( NegSizeTimer1 );
4557
4558   if( GetUseAssignedSize(Dimension::WIDTH ) )
4559   {
4560     SetLayoutNegotiated( false, Dimension::WIDTH );
4561   }
4562   if( GetUseAssignedSize( Dimension::HEIGHT ) )
4563   {
4564     SetLayoutNegotiated( false, Dimension::HEIGHT );
4565   }
4566
4567   // Do the negotiation
4568   NegotiateDimensions( allocatedSize );
4569
4570   // Set the actor size
4571   SetNegotiatedSize( container );
4572
4573   // Negotiate down to children
4574   for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4575   {
4576     ActorPtr child = GetChildAt( i );
4577
4578     // Forces children that have already been laid out to be relayed out
4579     // if they have assigned size during relayout.
4580     if( child->GetUseAssignedSize(Dimension::WIDTH) )
4581     {
4582       child->SetLayoutNegotiated(false, Dimension::WIDTH);
4583       child->SetLayoutDirty(true, Dimension::WIDTH);
4584     }
4585
4586     if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4587     {
4588       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4589       child->SetLayoutDirty(true, Dimension::HEIGHT);
4590     }
4591
4592     // Only relayout if required
4593     if( child->RelayoutRequired() )
4594     {
4595       container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4596     }
4597   }
4598   DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4599 }
4600
4601 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4602 {
4603   if( mRelayoutData )
4604   {
4605     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4606     {
4607       if( dimension & ( 1 << i ) )
4608       {
4609         mRelayoutData->useAssignedSize[ i ] = use;
4610       }
4611     }
4612   }
4613 }
4614
4615 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4616 {
4617   if ( mRelayoutData )
4618   {
4619     // If more than one dimension is requested, just return the first one found
4620     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4621     {
4622       if( dimension & ( 1 << i ) )
4623       {
4624         return mRelayoutData->useAssignedSize[ i ];
4625       }
4626     }
4627   }
4628
4629   return false;
4630 }
4631
4632 void Actor::RelayoutRequest( Dimension::Type dimension )
4633 {
4634   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4635   if( relayoutController )
4636   {
4637     Dali::Actor self( this );
4638     relayoutController->RequestRelayout( self, dimension );
4639   }
4640 }
4641
4642 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4643 {
4644 }
4645
4646 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4647 {
4648 }
4649
4650 void Actor::SetPreferredSize( const Vector2& size )
4651 {
4652   EnsureRelayoutData();
4653
4654   if( size.width > 0.0f )
4655   {
4656     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4657   }
4658
4659   if( size.height > 0.0f )
4660   {
4661     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4662   }
4663
4664   mRelayoutData->preferredSize = size;
4665
4666   RelayoutRequest();
4667 }
4668
4669 Vector2 Actor::GetPreferredSize() const
4670 {
4671   if ( mRelayoutData )
4672   {
4673     return Vector2( mRelayoutData->preferredSize );
4674   }
4675
4676   return GetDefaultPreferredSize();
4677 }
4678
4679 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4680 {
4681   EnsureRelayoutData();
4682
4683   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4684   {
4685     if( dimension & ( 1 << i ) )
4686     {
4687       mRelayoutData->minimumSize[ i ] = size;
4688     }
4689   }
4690
4691   RelayoutRequest();
4692 }
4693
4694 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4695 {
4696   if ( mRelayoutData )
4697   {
4698     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4699     {
4700       if( dimension & ( 1 << i ) )
4701       {
4702         return mRelayoutData->minimumSize[ i ];
4703       }
4704     }
4705   }
4706
4707   return 0.0f;  // Default
4708 }
4709
4710 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4711 {
4712   EnsureRelayoutData();
4713
4714   for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4715   {
4716     if( dimension & ( 1 << i ) )
4717     {
4718       mRelayoutData->maximumSize[ i ] = size;
4719     }
4720   }
4721
4722   RelayoutRequest();
4723 }
4724
4725 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4726 {
4727   if ( mRelayoutData )
4728   {
4729     for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4730     {
4731       if( dimension & ( 1 << i ) )
4732       {
4733         return mRelayoutData->maximumSize[ i ];
4734       }
4735     }
4736   }
4737
4738   return FLT_MAX;  // Default
4739 }
4740
4741 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
4742 {
4743   // node is being used in a separate thread; queue a message to set the value & base value
4744   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
4745 }
4746
4747 Vector2 Actor::GetUpdateSizeHint() const
4748 {
4749   // node is being used in a separate thread; copy the value from the previous update
4750   Vector3 updateSizeHint = GetNode().GetUpdateSizeHint( GetEventThreadServices().GetEventBufferIndex() );
4751   return Vector2( updateSizeHint.width, updateSizeHint.height );
4752 }
4753
4754 Object* Actor::GetParentObject() const
4755 {
4756   return mParent;
4757 }
4758
4759 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4760 {
4761   if( mVisible != visible )
4762   {
4763     if( sendMessage == SendMessage::TRUE )
4764     {
4765       // node is being used in a separate thread; queue a message to set the value & base value
4766       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4767     }
4768
4769     mVisible = visible;
4770
4771     // Emit the signal on this actor and all its children
4772     EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4773   }
4774 }
4775
4776 void Actor::SetSiblingOrder( uint32_t order )
4777 {
4778   if ( mParent )
4779   {
4780     ActorContainer& siblings = *(mParent->mChildren);
4781     uint32_t currentOrder = GetSiblingOrder();
4782
4783     if( order != currentOrder )
4784     {
4785       if( order == 0 )
4786       {
4787         LowerToBottom();
4788       }
4789       else if( order < siblings.size() -1 )
4790       {
4791         if( order > currentOrder )
4792         {
4793           RaiseAbove( *siblings[order] );
4794         }
4795         else
4796         {
4797           LowerBelow( *siblings[order] );
4798         }
4799       }
4800       else
4801       {
4802         RaiseToTop();
4803       }
4804     }
4805   }
4806 }
4807
4808 uint32_t Actor::GetSiblingOrder() const
4809 {
4810   uint32_t order = 0;
4811
4812   if ( mParent )
4813   {
4814     ActorContainer& siblings = *(mParent->mChildren);
4815     for( std::size_t i = 0; i < siblings.size(); ++i )
4816     {
4817       if( siblings[i] == this )
4818       {
4819         order = static_cast<uint32_t>( i );
4820         break;
4821       }
4822     }
4823   }
4824
4825   return order;
4826 }
4827
4828 void Actor::RequestRebuildDepthTree()
4829 {
4830   if( mIsOnStage )
4831   {
4832     if( mScene )
4833     {
4834       mScene->RequestRebuildDepthTree();
4835     }
4836   }
4837 }
4838
4839 void Actor::Raise()
4840 {
4841   if ( mParent )
4842   {
4843     ActorContainer& siblings = *(mParent->mChildren);
4844     if( siblings.back() != this ) // If not already at end
4845     {
4846       for( std::size_t i=0; i<siblings.size(); ++i )
4847       {
4848         if( siblings[i] == this )
4849         {
4850           // Swap with next
4851           ActorPtr next = siblings[i+1];
4852           siblings[i+1] = this;
4853           siblings[i] = next;
4854           break;
4855         }
4856       }
4857     }
4858
4859     Dali::Actor handle( this );
4860     mParent->mChildOrderChangedSignal.Emit( handle );
4861
4862     RequestRebuildDepthTree();
4863   }
4864   else
4865   {
4866     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4867   }
4868 }
4869
4870 void Actor::Lower()
4871 {
4872   if ( mParent )
4873   {
4874     ActorContainer& siblings = *(mParent->mChildren);
4875     if( siblings.front() != this ) // If not already at beginning
4876     {
4877       for( std::size_t i=1; i<siblings.size(); ++i )
4878       {
4879         if( siblings[i] == this )
4880         {
4881           // Swap with previous
4882           ActorPtr previous = siblings[i-1];
4883           siblings[i-1] = this;
4884           siblings[i] = previous;
4885           break;
4886         }
4887       }
4888     }
4889
4890     Dali::Actor handle( this );
4891     mParent->mChildOrderChangedSignal.Emit( handle );
4892
4893     RequestRebuildDepthTree();
4894   }
4895   else
4896   {
4897     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4898   }
4899 }
4900
4901 void Actor::RaiseToTop()
4902 {
4903   if ( mParent )
4904   {
4905     ActorContainer& siblings = *(mParent->mChildren);
4906     if( siblings.back() != this ) // If not already at end
4907     {
4908       ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4909       if( iter != siblings.end() )
4910       {
4911         siblings.erase(iter);
4912         siblings.push_back(ActorPtr(this));
4913       }
4914     }
4915
4916     Dali::Actor handle( this );
4917     mParent->mChildOrderChangedSignal.Emit( handle );
4918
4919     RequestRebuildDepthTree();
4920   }
4921   else
4922   {
4923     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4924   }
4925 }
4926
4927 void Actor::LowerToBottom()
4928 {
4929   if ( mParent )
4930   {
4931     ActorContainer& siblings = *(mParent->mChildren);
4932     if( siblings.front() != this ) // If not already at bottom,
4933     {
4934       ActorPtr thisPtr(this); // ensure this actor remains referenced.
4935
4936       ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4937       if( iter != siblings.end() )
4938       {
4939         siblings.erase(iter);
4940         siblings.insert(siblings.begin(), thisPtr);
4941       }
4942     }
4943
4944     Dali::Actor handle( this );
4945     mParent->mChildOrderChangedSignal.Emit( handle );
4946
4947     RequestRebuildDepthTree();
4948   }
4949   else
4950   {
4951     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4952   }
4953 }
4954
4955 void Actor::RaiseAbove( Internal::Actor& target )
4956 {
4957   if ( mParent )
4958   {
4959     ActorContainer& siblings = *(mParent->mChildren);
4960     if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4961     {
4962       ActorPtr thisPtr(this); // ensure this actor remains referenced.
4963
4964       ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4965       ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4966       if( thisIter < targetIter )
4967       {
4968         siblings.erase(thisIter);
4969         // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4970         // invalidate thisIter)
4971         targetIter = std::find( siblings.begin(), siblings.end(), &target );
4972         ++targetIter;
4973         siblings.insert(targetIter, thisPtr);
4974       }
4975
4976       Dali::Actor handle( this );
4977       mParent->mChildOrderChangedSignal.Emit( handle );
4978
4979       RequestRebuildDepthTree();
4980     }
4981   }
4982   else
4983   {
4984     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4985   }
4986 }
4987
4988 void Actor::LowerBelow( Internal::Actor& target )
4989 {
4990   if ( mParent )
4991   {
4992     ActorContainer& siblings = *(mParent->mChildren);
4993     if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4994     {
4995       ActorPtr thisPtr(this); // ensure this actor remains referenced.
4996
4997       ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4998       ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4999
5000       if( thisIter > targetIter )
5001       {
5002         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5003         siblings.insert(targetIter, thisPtr);
5004       }
5005
5006       Dali::Actor handle( this );
5007       mParent->mChildOrderChangedSignal.Emit( handle );
5008
5009       RequestRebuildDepthTree();
5010     }
5011   }
5012   else
5013   {
5014     DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5015   }
5016 }
5017
5018 void Actor::SetScene( Scene& scene )
5019 {
5020   mScene = &scene;
5021 }
5022
5023 Scene& Actor::GetScene() const
5024 {
5025   return *mScene;
5026 }
5027
5028 void Actor::SetInheritLayoutDirection( bool inherit )
5029 {
5030   if( mInheritLayoutDirection != inherit )
5031   {
5032     mInheritLayoutDirection = inherit;
5033
5034     if( inherit && mParent )
5035     {
5036       InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5037     }
5038   }
5039 }
5040
5041 bool Actor::IsLayoutDirectionInherited() const
5042 {
5043   return mInheritLayoutDirection;
5044 }
5045
5046 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5047 {
5048   if( actor && ( actor->mInheritLayoutDirection || set ) )
5049   {
5050     if( actor->mLayoutDirection != direction )
5051     {
5052       actor->mLayoutDirection = direction;
5053       actor->EmitLayoutDirectionChangedSignal( direction );
5054       actor->RelayoutRequest();
5055     }
5056
5057     if( actor->GetChildCount() > 0 )
5058     {
5059       ActorContainer& children = actor->GetChildrenInternal();
5060       for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5061       {
5062         InheritLayoutDirectionRecursively( *iter, direction );
5063       }
5064     }
5065   }
5066 }
5067
5068 } // namespace Internal
5069
5070 } // namespace Dali