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