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