2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
66 unsigned int Actor::mActorCounter = 0;
70 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
71 inline const Vector3& GetDefaultSizeModeFactor()
76 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
77 inline const Vector2& GetDefaultPreferredSize()
82 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
83 inline const Vector2& GetDefaultDimensionPadding()
88 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
90 int GetSiblingOrder( ActorPtr actor )
92 Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
98 bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
100 bool validTarget = true;
102 if( &actor == &target )
104 DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
107 else if( actor.GetParent() != target.GetParent() )
109 DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
116 } // unnamed namespace
119 * Struct to collect relayout variables
121 struct Actor::RelayoutData
124 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
126 // Set size negotiation defaults
127 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
129 resizePolicies[ i ] = ResizePolicy::DEFAULT;
130 negotiatedDimensions[ i ] = 0.0f;
131 dimensionNegotiated[ i ] = false;
132 dimensionDirty[ i ] = false;
133 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
134 dimensionPadding[ i ] = GetDefaultDimensionPadding();
135 minimumSize[ i ] = 0.0f;
136 maximumSize[ i ] = FLT_MAX;
140 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
142 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
144 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
146 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
148 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
149 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
151 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
152 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
154 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
156 Vector2 preferredSize; ///< The preferred size of the actor
158 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
160 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
161 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
164 namespace // unnamed namespace
170 * We want to discourage the use of property strings (minimize string comparisons),
171 * particularly for the default properties.
172 * Name Type writable animatable constraint-input enum for index-checking
174 DALI_PROPERTY_TABLE_BEGIN
175 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
176 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
177 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
178 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
179 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
180 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
181 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
182 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
183 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
184 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
185 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
186 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
187 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
188 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
189 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
190 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
191 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
192 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
193 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
194 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
195 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
196 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
197 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
198 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
199 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
200 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
201 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
202 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
203 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
204 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
205 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
206 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
207 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
208 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
209 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
210 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
211 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
212 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
213 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
214 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
215 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
216 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
217 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
218 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
219 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
220 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
221 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
222 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
223 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
224 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
225 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
226 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
227 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
228 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
229 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
230 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
231 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
232 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
243 const char* const SIGNAL_TOUCH = "touch";
247 const char* const ACTION_SHOW = "show";
248 const char* const ACTION_HIDE = "hide";
250 BaseHandle CreateActor()
252 return Dali::Actor::New();
255 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
257 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
263 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
265 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
266 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
271 const Vector3& value;
274 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
277 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
278 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
279 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
280 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
282 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
284 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
286 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
287 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
288 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
289 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
290 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
291 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
293 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
294 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
295 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
296 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
297 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
298 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
300 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
304 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
306 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
315 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
317 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
321 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
323 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
324 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
325 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
326 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
329 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
331 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
333 size_t sizeIgnored = 0;
334 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
336 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
343 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
345 // Values are the same so just use the same table as anchor-point
346 return GetAnchorPointConstant( value, parentOrigin );
350 * @brief Extract a given dimension from a Vector2
352 * @param[in] values The values to extract from
353 * @param[in] dimension The dimension to extract
354 * @return Return the value for the dimension
356 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
360 case Dimension::WIDTH:
364 case Dimension::HEIGHT:
366 return values.height;
377 * @brief Extract a given dimension from a Vector3
379 * @param[in] values The values to extract from
380 * @param[in] dimension The dimension to extract
381 * @return Return the value for the dimension
383 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
385 return GetDimensionValue( values.GetVectorXY(), dimension );
388 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
390 return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
393 } // unnamed namespace
395 ActorPtr Actor::New()
397 ActorPtr actor( new Actor( BASIC ) );
399 // Second-phase construction
405 const std::string& Actor::GetName() const
410 void Actor::SetName( const std::string& name )
416 // ATTENTION: string for debug purposes is not thread safe.
417 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
421 unsigned int Actor::GetId() const
426 bool Actor::OnStage() const
431 Dali::Layer Actor::GetLayer()
435 // Short-circuit for Layer derived actors
438 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
441 // Find the immediate Layer parent
442 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
444 if( parent->IsLayer() )
446 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
453 void Actor::Add( Actor& child )
455 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
456 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
460 mChildren = new ActorContainer;
463 Actor* const oldParent( child.mParent );
465 // child might already be ours
466 if( this != oldParent )
468 // if we already have parent, unparent us first
471 oldParent->Remove( child ); // This causes OnChildRemove callback
473 // Old parent may need to readjust to missing child
474 if( oldParent->RelayoutDependentOnChildren() )
476 oldParent->RelayoutRequest();
480 // Guard against Add() during previous OnChildRemove callback
483 // Do this first, since user callbacks from within SetParent() may need to remove child
484 mChildren->push_back( ActorPtr( &child ) );
486 // SetParent asserts that child can be added
487 child.SetParent( this );
489 // Notification for derived classes
492 // Only put in a relayout request if there is a suitable dependency
493 if( RelayoutDependentOnChildren() )
501 void Actor::Remove( Actor& child )
503 if( (this == &child) || (!mChildren) )
505 // no children or removing itself
511 // Find the child in mChildren, and unparent it
512 ActorIter end = mChildren->end();
513 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
515 ActorPtr actor = (*iter);
517 if( actor.Get() == &child )
519 // Keep handle for OnChildRemove notification
522 // Do this first, since user callbacks from within SetParent() may need to add the child
523 mChildren->erase( iter );
525 DALI_ASSERT_DEBUG( actor->GetParent() == this );
526 actor->SetParent( NULL );
534 // Only put in a relayout request if there is a suitable dependency
535 if( RelayoutDependentOnChildren() )
541 // Notification for derived classes
542 OnChildRemove( child );
545 void Actor::Unparent()
549 // Remove this actor from the parent. The remove will put a relayout request in for
550 // the parent if required
551 mParent->Remove( *this );
552 // mParent is now NULL!
556 unsigned int Actor::GetChildCount() const
558 return ( NULL != mChildren ) ? mChildren->size() : 0;
561 ActorPtr Actor::GetChildAt( unsigned int index ) const
563 DALI_ASSERT_ALWAYS( index < GetChildCount() );
565 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
568 ActorPtr Actor::FindChildByName( const std::string& actorName )
571 if( actorName == mName )
577 ActorIter end = mChildren->end();
578 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
580 child = (*iter)->FindChildByName( actorName );
591 ActorPtr Actor::FindChildById( const unsigned int id )
600 ActorIter end = mChildren->end();
601 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
603 child = (*iter)->FindChildById( id );
614 void Actor::SetParentOrigin( const Vector3& origin )
618 // mNode is being used in a separate thread; queue a message to set the value & base value
619 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
622 // Cache for event-thread access
625 // not allocated, check if different from default
626 if( ParentOrigin::DEFAULT != origin )
628 mParentOrigin = new Vector3( origin );
633 // check if different from current costs more than just set
634 *mParentOrigin = origin;
638 void Actor::SetParentOriginX( float x )
640 const Vector3& current = GetCurrentParentOrigin();
642 SetParentOrigin( Vector3( x, current.y, current.z ) );
645 void Actor::SetParentOriginY( float y )
647 const Vector3& current = GetCurrentParentOrigin();
649 SetParentOrigin( Vector3( current.x, y, current.z ) );
652 void Actor::SetParentOriginZ( float z )
654 const Vector3& current = GetCurrentParentOrigin();
656 SetParentOrigin( Vector3( current.x, current.y, z ) );
659 const Vector3& Actor::GetCurrentParentOrigin() const
661 // Cached for event-thread access
662 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
665 void Actor::SetAnchorPoint( const Vector3& anchor )
669 // mNode is being used in a separate thread; queue a message to set the value & base value
670 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
673 // Cache for event-thread access
676 // not allocated, check if different from default
677 if( AnchorPoint::DEFAULT != anchor )
679 mAnchorPoint = new Vector3( anchor );
684 // check if different from current costs more than just set
685 *mAnchorPoint = anchor;
689 void Actor::SetAnchorPointX( float x )
691 const Vector3& current = GetCurrentAnchorPoint();
693 SetAnchorPoint( Vector3( x, current.y, current.z ) );
696 void Actor::SetAnchorPointY( float y )
698 const Vector3& current = GetCurrentAnchorPoint();
700 SetAnchorPoint( Vector3( current.x, y, current.z ) );
703 void Actor::SetAnchorPointZ( float z )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( current.x, current.y, z ) );
710 const Vector3& Actor::GetCurrentAnchorPoint() const
712 // Cached for event-thread access
713 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
716 void Actor::SetPosition( float x, float y )
718 SetPosition( Vector3( x, y, 0.0f ) );
721 void Actor::SetPosition( float x, float y, float z )
723 SetPosition( Vector3( x, y, z ) );
726 void Actor::SetPosition( const Vector3& position )
728 mTargetPosition = position;
732 // mNode is being used in a separate thread; queue a message to set the value & base value
733 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
737 void Actor::SetX( float x )
739 mTargetPosition.x = x;
743 // mNode is being used in a separate thread; queue a message to set the value & base value
744 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
748 void Actor::SetY( float y )
750 mTargetPosition.y = y;
754 // mNode is being used in a separate thread; queue a message to set the value & base value
755 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
759 void Actor::SetZ( float z )
761 mTargetPosition.z = z;
765 // mNode is being used in a separate thread; queue a message to set the value & base value
766 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
770 void Actor::TranslateBy( const Vector3& distance )
772 mTargetPosition += distance;
776 // mNode is being used in a separate thread; queue a message to set the value & base value
777 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
781 const Vector3& Actor::GetCurrentPosition() const
785 // mNode is being used in a separate thread; copy the value from the previous update
786 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
789 return Vector3::ZERO;
792 const Vector3& Actor::GetTargetPosition() const
794 return mTargetPosition;
797 const Vector3& Actor::GetCurrentWorldPosition() const
801 // mNode is being used in a separate thread; copy the value from the previous update
802 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
805 return Vector3::ZERO;
808 const Vector2 Actor::GetCurrentScreenPosition() const
810 if( OnStage() && NULL != mNode )
812 StagePtr stage = Stage::GetCurrent();
813 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
814 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
815 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
816 Vector3 halfActorSize( actorSize * 0.5f );
817 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
819 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
820 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
823 return Vector2::ZERO;
826 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
828 // this flag is not animatable so keep the value
829 mPositionInheritanceMode = mode;
832 // mNode is being used in a separate thread; queue a message to set the value
833 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
837 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
839 // Cached for event-thread access
840 return mPositionInheritanceMode;
843 void Actor::SetInheritPosition( bool inherit )
845 if( mInheritPosition != inherit && NULL != mNode )
847 // non animateable so keep local copy
848 mInheritPosition = inherit;
849 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
853 bool Actor::IsPositionInherited() const
855 return mInheritPosition;
858 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
860 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
861 normalizedAxis.Normalize();
863 Quaternion orientation( angle, normalizedAxis );
865 SetOrientation( orientation );
868 void Actor::SetOrientation( const Quaternion& orientation )
872 // mNode is being used in a separate thread; queue a message to set the value & base value
873 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
877 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
881 // mNode is being used in a separate thread; queue a message to set the value & base value
882 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
886 void Actor::RotateBy( const Quaternion& relativeRotation )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
895 const Quaternion& Actor::GetCurrentOrientation() const
899 // mNode is being used in a separate thread; copy the value from the previous update
900 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
903 return Quaternion::IDENTITY;
906 const Quaternion& Actor::GetCurrentWorldOrientation() const
910 // mNode is being used in a separate thread; copy the value from the previous update
911 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
914 return Quaternion::IDENTITY;
917 void Actor::SetScale( float scale )
919 SetScale( Vector3( scale, scale, scale ) );
922 void Actor::SetScale( float x, float y, float z )
924 SetScale( Vector3( x, y, z ) );
927 void Actor::SetScale( const Vector3& scale )
931 // mNode is being used in a separate thread; queue a message to set the value & base value
932 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
936 void Actor::SetScaleX( float x )
940 // mNode is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
945 void Actor::SetScaleY( float y )
949 // mNode is being used in a separate thread; queue a message to set the value & base value
950 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
954 void Actor::SetScaleZ( float z )
958 // mNode is being used in a separate thread; queue a message to set the value & base value
959 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
963 void Actor::ScaleBy(const Vector3& relativeScale)
967 // mNode is being used in a separate thread; queue a message to set the value & base value
968 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
972 const Vector3& Actor::GetCurrentScale() const
976 // mNode is being used in a separate thread; copy the value from the previous update
977 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
983 const Vector3& Actor::GetCurrentWorldScale() const
987 // mNode is being used in a separate thread; copy the value from the previous update
988 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
994 void Actor::SetInheritScale( bool inherit )
997 if( mInheritScale != inherit && NULL != mNode )
999 // non animateable so keep local copy
1000 mInheritScale = inherit;
1001 // mNode is being used in a separate thread; queue a message to set the value
1002 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1006 bool Actor::IsScaleInherited() const
1008 return mInheritScale;
1011 Matrix Actor::GetCurrentWorldMatrix() const
1015 return mNode->GetWorldMatrix(0);
1018 return Matrix::IDENTITY;
1021 void Actor::SetVisible( bool visible )
1025 // mNode is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1030 bool Actor::IsVisible() const
1034 // mNode is being used in a separate thread; copy the value from the previous update
1035 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1041 void Actor::SetOpacity( float opacity )
1045 // mNode is being used in a separate thread; queue a message to set the value & base value
1046 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1050 float Actor::GetCurrentOpacity() const
1054 // mNode is being used in a separate thread; copy the value from the previous update
1055 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1061 ClippingMode::Type Actor::GetClippingMode() const
1063 return mClippingMode;
1066 unsigned int Actor::GetSortingDepth()
1068 return GetDepthIndex( mDepth, mSiblingOrder );
1071 const Vector4& Actor::GetCurrentWorldColor() const
1075 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1078 return Color::WHITE;
1081 void Actor::SetColor( const Vector4& color )
1085 // mNode is being used in a separate thread; queue a message to set the value & base value
1086 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1090 void Actor::SetColorRed( float red )
1094 // mNode is being used in a separate thread; queue a message to set the value & base value
1095 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1099 void Actor::SetColorGreen( float green )
1103 // mNode is being used in a separate thread; queue a message to set the value & base value
1104 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1108 void Actor::SetColorBlue( float blue )
1112 // mNode is being used in a separate thread; queue a message to set the value & base value
1113 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1117 const Vector4& Actor::GetCurrentColor() const
1121 // mNode is being used in a separate thread; copy the value from the previous update
1122 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1125 return Color::WHITE;
1128 void Actor::SetInheritOrientation( bool inherit )
1130 if( mInheritOrientation != inherit && NULL != mNode)
1132 // non animateable so keep local copy
1133 mInheritOrientation = inherit;
1134 // mNode is being used in a separate thread; queue a message to set the value
1135 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1139 bool Actor::IsOrientationInherited() const
1141 return mInheritOrientation;
1144 void Actor::SetSizeModeFactor( const Vector3& factor )
1146 EnsureRelayoutData();
1148 mRelayoutData->sizeModeFactor = factor;
1151 const Vector3& Actor::GetSizeModeFactor() const
1153 if ( mRelayoutData )
1155 return mRelayoutData->sizeModeFactor;
1158 return GetDefaultSizeModeFactor();
1161 void Actor::SetColorMode( ColorMode colorMode )
1163 // non animateable so keep local copy
1164 mColorMode = colorMode;
1167 // mNode is being used in a separate thread; queue a message to set the value
1168 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1172 ColorMode Actor::GetColorMode() const
1174 // we have cached copy
1178 void Actor::SetSize( float width, float height )
1180 SetSize( Vector2( width, height ) );
1183 void Actor::SetSize( float width, float height, float depth )
1185 SetSize( Vector3( width, height, depth ) );
1188 void Actor::SetSize( const Vector2& size )
1190 SetSize( Vector3( size.width, size.height, 0.f ) );
1193 void Actor::SetSizeInternal( const Vector2& size )
1195 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1198 void Actor::SetSize( const Vector3& size )
1200 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1202 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1203 SetPreferredSize( size.GetVectorXY() );
1207 SetSizeInternal( size );
1211 void Actor::SetSizeInternal( const Vector3& size )
1213 // dont allow recursive loop
1214 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1215 // 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
1216 if( ( NULL != mNode )&&
1217 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1218 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1219 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1223 // mNode is being used in a separate thread; queue a message to set the value & base value
1224 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1226 // Notification for derived classes
1227 mInsideOnSizeSet = true;
1228 OnSizeSet( mTargetSize );
1229 mInsideOnSizeSet = false;
1231 // Raise a relayout request if the flag is not locked
1232 if( mRelayoutData && !mRelayoutData->insideRelayout )
1239 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1241 mTargetSize = targetSize;
1243 // Notify deriving classes
1244 OnSizeAnimation( animation, mTargetSize );
1247 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1249 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1251 mTargetSize.width = targetSize;
1253 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1255 mTargetSize.height = targetSize;
1257 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1259 mTargetSize.depth = targetSize;
1261 // Notify deriving classes
1262 OnSizeAnimation( animation, mTargetSize );
1265 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1267 mTargetPosition = targetPosition;
1270 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1272 if ( Dali::Actor::Property::POSITION_X == property )
1274 mTargetPosition.x = targetPosition;
1276 else if ( Dali::Actor::Property::POSITION_Y == property )
1278 mTargetPosition.y = targetPosition;
1280 else if ( Dali::Actor::Property::POSITION_Z == property )
1282 mTargetPosition.z = targetPosition;
1286 void Actor::SetWidth( float width )
1288 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1290 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1291 mRelayoutData->preferredSize.width = width;
1295 mTargetSize.width = width;
1299 // mNode is being used in a separate thread; queue a message to set the value & base value
1300 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1307 void Actor::SetHeight( float height )
1309 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1311 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1312 mRelayoutData->preferredSize.height = height;
1316 mTargetSize.height = height;
1320 // mNode is being used in a separate thread; queue a message to set the value & base value
1321 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1328 void Actor::SetDepth( float depth )
1330 mTargetSize.depth = depth;
1334 // mNode is being used in a separate thread; queue a message to set the value & base value
1335 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1339 const Vector3& Actor::GetTargetSize() const
1344 const Vector3& Actor::GetCurrentSize() const
1348 // mNode is being used in a separate thread; copy the value from the previous update
1349 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1352 return Vector3::ZERO;
1355 Vector3 Actor::GetNaturalSize() const
1357 // It is up to deriving classes to return the appropriate natural size
1358 return Vector3( 0.0f, 0.0f, 0.0f );
1361 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1363 EnsureRelayoutData();
1365 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1366 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1368 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1370 if( dimension & ( 1 << i ) )
1372 mRelayoutData->resizePolicies[ i ] = policy;
1376 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1378 if( dimension & Dimension::WIDTH )
1380 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1383 if( dimension & Dimension::HEIGHT )
1385 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1389 // If calling SetResizePolicy, assume we want relayout enabled
1390 SetRelayoutEnabled( true );
1392 // If the resize policy is set to be FIXED, the preferred size
1393 // should be overrided by the target size. Otherwise the target
1394 // size should be overrided by the preferred size.
1396 if( dimension & Dimension::WIDTH )
1398 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1400 mRelayoutData->preferredSize.width = mTargetSize.width;
1402 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1404 mTargetSize.width = mRelayoutData->preferredSize.width;
1408 if( dimension & Dimension::HEIGHT )
1410 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1412 mRelayoutData->preferredSize.height = mTargetSize.height;
1414 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1416 mTargetSize.height = mRelayoutData->preferredSize.height;
1420 OnSetResizePolicy( policy, dimension );
1422 // Trigger relayout on this control
1426 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1428 if ( mRelayoutData )
1430 // If more than one dimension is requested, just return the first one found
1431 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1433 if( ( dimension & ( 1 << i ) ) )
1435 return mRelayoutData->resizePolicies[ i ];
1440 return ResizePolicy::DEFAULT;
1443 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1445 EnsureRelayoutData();
1447 mRelayoutData->sizeSetPolicy = policy;
1450 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1452 if ( mRelayoutData )
1454 return mRelayoutData->sizeSetPolicy;
1457 return DEFAULT_SIZE_SCALE_POLICY;
1460 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1462 EnsureRelayoutData();
1464 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1466 if( dimension & ( 1 << i ) )
1468 mRelayoutData->dimensionDependencies[ i ] = dependency;
1473 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1475 if ( mRelayoutData )
1477 // If more than one dimension is requested, just return the first one found
1478 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1480 if( ( dimension & ( 1 << i ) ) )
1482 return mRelayoutData->dimensionDependencies[ i ];
1487 return Dimension::ALL_DIMENSIONS; // Default
1490 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1492 // If relayout data has not been allocated yet and the client is requesting
1493 // to disable it, do nothing
1494 if( mRelayoutData || relayoutEnabled )
1496 EnsureRelayoutData();
1498 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1500 mRelayoutData->relayoutEnabled = relayoutEnabled;
1504 bool Actor::IsRelayoutEnabled() const
1506 // Assume that if relayout data has not been allocated yet then
1507 // relayout is disabled
1508 return mRelayoutData && mRelayoutData->relayoutEnabled;
1511 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1513 EnsureRelayoutData();
1515 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1517 if( dimension & ( 1 << i ) )
1519 mRelayoutData->dimensionDirty[ i ] = dirty;
1524 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1526 if ( mRelayoutData )
1528 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1530 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1540 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1542 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1545 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1547 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1550 unsigned int Actor::AddRenderer( Renderer& renderer )
1554 mRenderers = new RendererContainer;
1557 unsigned int index = mRenderers->size();
1558 RendererPtr rendererPtr = RendererPtr( &renderer );
1559 mRenderers->push_back( rendererPtr );
1560 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1564 unsigned int Actor::GetRendererCount() const
1566 unsigned int rendererCount(0);
1569 rendererCount = mRenderers->size();
1572 return rendererCount;
1575 RendererPtr Actor::GetRendererAt( unsigned int index )
1577 RendererPtr renderer;
1578 if( index < GetRendererCount() )
1580 renderer = ( *mRenderers )[ index ];
1586 void Actor::RemoveRenderer( Renderer& renderer )
1590 RendererIter end = mRenderers->end();
1591 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1593 if( (*iter).Get() == &renderer )
1595 mRenderers->erase( iter );
1596 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1603 void Actor::RemoveRenderer( unsigned int index )
1605 if( index < GetRendererCount() )
1607 RendererPtr renderer = ( *mRenderers )[ index ];
1608 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1609 mRenderers->erase( mRenderers->begin()+index );
1613 bool Actor::IsOverlay() const
1615 return ( DrawMode::OVERLAY_2D == mDrawMode );
1618 void Actor::SetDrawMode( DrawMode::Type drawMode )
1620 // this flag is not animatable so keep the value
1621 mDrawMode = drawMode;
1622 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1624 // mNode is being used in a separate thread; queue a message to set the value
1625 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1629 DrawMode::Type Actor::GetDrawMode() const
1634 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1636 // only valid when on-stage
1637 StagePtr stage = Stage::GetCurrent();
1638 if( stage && OnStage() )
1640 const RenderTaskList& taskList = stage->GetRenderTaskList();
1642 Vector2 converted( screenX, screenY );
1644 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1645 const int taskCount = taskList.GetTaskCount();
1646 for( int i = taskCount - 1; i >= 0; --i )
1648 Dali::RenderTask task = taskList.GetTask( i );
1649 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1651 // found a task where this conversion was ok so return
1659 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1661 bool retval = false;
1662 // only valid when on-stage
1665 CameraActor* camera = renderTask.GetCameraActor();
1669 renderTask.GetViewport( viewport );
1671 // need to translate coordinates to render tasks coordinate space
1672 Vector2 converted( screenX, screenY );
1673 if( renderTask.TranslateCoordinates( converted ) )
1675 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1682 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1684 // Early-out if mNode is NULL
1690 // Get the ModelView matrix
1692 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1694 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1695 Matrix invertedMvp( false/*don't init*/);
1696 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1697 bool success = invertedMvp.Invert();
1699 // Convert to GL coordinates
1700 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1705 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1712 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1718 if( XyPlaneIntersect( nearPos, farPos, local ) )
1720 Vector3 size = GetCurrentSize();
1721 localX = local.x + size.x * 0.5f;
1722 localY = local.y + size.y * 0.5f;
1733 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1736 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1738 Mathematical Formulation
1740 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1742 ( p - c ) dot ( p - c ) = r^2
1744 Given a ray with a point of origin 'o', and a direction vector 'd':
1746 ray(t) = o + td, t >= 0
1748 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1750 (o + td - c ) dot ( o + td - c ) = r^2
1752 To solve for t we first expand the above into a more recognisable quadratic equation form
1754 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1763 B = 2( o - c ) dot d
1764 C = ( o - c ) dot ( o - c ) - r^2
1766 which can be solved using a standard quadratic formula.
1768 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1770 Practical Simplification
1772 In a renderer, we often differentiate between world space and object space. In the object space
1773 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1774 into object space, the mathematical solution presented above can be simplified significantly.
1776 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1780 and we can find the t at which the (transformed) ray intersects the sphere by
1782 ( o + td ) dot ( o + td ) = r^2
1784 According to the reasoning above, we expand the above quadratic equation into the general form
1788 which now has coefficients:
1795 // Early out if mNode is NULL
1801 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1803 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1804 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1805 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1807 // Compute the radius is not needed, square radius it's enough.
1808 const Vector3& size( mNode->GetSize( bufferIndex ) );
1810 // Scale the sphere.
1811 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1813 const float width = size.width * scale.width;
1814 const float height = size.height * scale.height;
1816 float squareSphereRadius = 0.5f * ( width * width + height * height );
1818 float a = rayDir.Dot( rayDir ); // a
1819 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1820 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1822 return ( b2 * b2 - a * c ) >= 0.f;
1825 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1829 if( OnStage() && NULL != mNode )
1831 // Transforms the ray to the local reference system.
1832 // Calculate the inverse of Model matrix
1833 Matrix invModelMatrix( false/*don't init*/);
1835 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1836 invModelMatrix = mNode->GetWorldMatrix(0);
1837 invModelMatrix.Invert();
1839 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1840 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1842 // Test with the actor's XY plane (Normal = 0 0 1 1).
1844 float a = -rayOriginLocal.z;
1845 float b = rayDirLocal.z;
1847 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1849 // Ray travels distance * rayDirLocal to intersect with plane.
1852 const Vector3& size = mNode->GetSize( bufferIndex );
1854 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1855 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1857 // Test with the actor's geometry.
1858 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1865 void Actor::SetLeaveRequired( bool required )
1867 mLeaveRequired = required;
1870 bool Actor::GetLeaveRequired() const
1872 return mLeaveRequired;
1875 void Actor::SetKeyboardFocusable( bool focusable )
1877 mKeyboardFocusable = focusable;
1880 bool Actor::IsKeyboardFocusable() const
1882 return mKeyboardFocusable;
1885 bool Actor::GetTouchRequired() const
1887 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1890 bool Actor::GetHoverRequired() const
1892 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1895 bool Actor::GetWheelEventRequired() const
1897 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1900 bool Actor::IsHittable() const
1902 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1905 ActorGestureData& Actor::GetGestureData()
1907 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1908 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1909 if( NULL == mGestureData )
1911 mGestureData = new ActorGestureData;
1913 return *mGestureData;
1916 bool Actor::IsGestureRequred( Gesture::Type type ) const
1918 return mGestureData && mGestureData->IsGestureRequred( type );
1921 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1923 bool consumed = false;
1925 if( !mTouchSignal.Empty() )
1927 Dali::Actor handle( this );
1928 consumed = mTouchSignal.Emit( handle, touch );
1931 if( !mTouchedSignal.Empty() )
1933 Dali::Actor handle( this );
1934 consumed |= mTouchedSignal.Emit( handle, event );
1939 // Notification for derived classes
1940 consumed = OnTouchEvent( event ); // TODO
1946 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1948 bool consumed = false;
1950 if( !mHoveredSignal.Empty() )
1952 Dali::Actor handle( this );
1953 consumed = mHoveredSignal.Emit( handle, event );
1958 // Notification for derived classes
1959 consumed = OnHoverEvent( event );
1965 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1967 bool consumed = false;
1969 if( !mWheelEventSignal.Empty() )
1971 Dali::Actor handle( this );
1972 consumed = mWheelEventSignal.Emit( handle, event );
1977 // Notification for derived classes
1978 consumed = OnWheelEvent( event );
1984 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1986 return mTouchedSignal;
1989 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1991 return mTouchSignal;
1994 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1996 return mHoveredSignal;
1999 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2001 return mWheelEventSignal;
2004 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2006 return mOnStageSignal;
2009 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2011 return mOffStageSignal;
2014 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2016 return mOnRelayoutSignal;
2019 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2021 bool connected( true );
2022 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2024 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2026 actor->TouchedSignal().Connect( tracker, functor );
2028 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2030 actor->HoveredSignal().Connect( tracker, functor );
2032 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2034 actor->WheelEventSignal().Connect( tracker, functor );
2036 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2038 actor->OnStageSignal().Connect( tracker, functor );
2040 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2042 actor->OffStageSignal().Connect( tracker, functor );
2044 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2046 actor->OnRelayoutSignal().Connect( tracker, functor );
2048 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2050 actor->TouchSignal().Connect( tracker, functor );
2054 // signalName does not match any signal
2061 Actor::Actor( DerivedType derivedType )
2066 mParentOrigin( NULL ),
2067 mAnchorPoint( NULL ),
2068 mRelayoutData( NULL ),
2069 mGestureData( NULL ),
2070 mTargetSize( 0.0f, 0.0f, 0.0f ),
2072 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2075 mIsRoot( ROOT_LAYER == derivedType ),
2076 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2077 mIsOnStage( false ),
2079 mLeaveRequired( false ),
2080 mKeyboardFocusable( false ),
2081 mDerivedRequiresTouch( false ),
2082 mDerivedRequiresHover( false ),
2083 mDerivedRequiresWheelEvent( false ),
2084 mOnStageSignalled( false ),
2085 mInsideOnSizeSet( false ),
2086 mInheritPosition( true ),
2087 mInheritOrientation( true ),
2088 mInheritScale( true ),
2089 mPositionUsesAnchorPoint( true ),
2090 mDrawMode( DrawMode::NORMAL ),
2091 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2092 mColorMode( Node::DEFAULT_COLOR_MODE ),
2093 mClippingMode( ClippingMode::DISABLED )
2097 void Actor::Initialize()
2100 SceneGraph::Node* node = CreateNode();
2102 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2103 mNode = node; // Keep raw-pointer to Node
2107 GetEventThreadServices().RegisterObject( this );
2112 // Remove mParent pointers from children even if we're destroying core,
2113 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2116 ActorConstIter endIter = mChildren->end();
2117 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2119 (*iter)->SetParent( NULL );
2125 // Guard to allow handle destruction after Core has been destroyed
2126 if( EventThreadServices::IsCoreRunning() )
2130 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2131 mNode = NULL; // Node is about to be destroyed
2134 GetEventThreadServices().UnregisterObject( this );
2137 // Cleanup optional gesture data
2138 delete mGestureData;
2140 // Cleanup optional parent origin and anchor
2141 delete mParentOrigin;
2142 delete mAnchorPoint;
2144 // Delete optional relayout data
2147 delete mRelayoutData;
2151 void Actor::ConnectToStage( unsigned int parentDepth )
2153 // This container is used instead of walking the Actor hierarchy.
2154 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2155 ActorContainer connectionList;
2157 // This stage is atomic i.e. not interrupted by user callbacks.
2158 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2160 // Notify applications about the newly connected actors.
2161 const ActorIter endIter = connectionList.end();
2162 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2164 (*iter)->NotifyStageConnection();
2170 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2172 DALI_ASSERT_ALWAYS( !OnStage() );
2176 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2178 ConnectToSceneGraph();
2180 // Notification for internal derived classes
2181 OnStageConnectionInternal();
2183 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2184 connectionList.push_back( ActorPtr( this ) );
2186 // Recursively connect children
2189 ActorConstIter endIter = mChildren->end();
2190 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2192 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2198 * This method is called when the Actor is connected to the Stage.
2199 * The parent must have added its Node to the scene-graph.
2200 * The child must connect its Node to the parent's Node.
2201 * This is recursive; the child calls ConnectToStage() for its children.
2203 void Actor::ConnectToSceneGraph()
2205 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2209 // Reparent Node in next Update
2210 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2213 // Request relayout on all actors that are added to the scenegraph
2216 // Notification for Object::Observers
2220 void Actor::NotifyStageConnection()
2222 // Actors can be removed (in a callback), before the on-stage stage is reported.
2223 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2224 if( OnStage() && !mOnStageSignalled )
2226 // Notification for external (CustomActor) derived classes
2227 OnStageConnectionExternal( mDepth );
2229 if( !mOnStageSignal.Empty() )
2231 Dali::Actor handle( this );
2232 mOnStageSignal.Emit( handle );
2235 // Guard against Remove during callbacks
2238 mOnStageSignalled = true; // signal required next time Actor is removed
2243 void Actor::DisconnectFromStage()
2245 // This container is used instead of walking the Actor hierachy.
2246 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2247 ActorContainer disconnectionList;
2249 // This stage is atomic i.e. not interrupted by user callbacks
2250 RecursiveDisconnectFromStage( disconnectionList );
2252 // Notify applications about the newly disconnected actors.
2253 const ActorIter endIter = disconnectionList.end();
2254 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2256 (*iter)->NotifyStageDisconnection();
2260 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2262 DALI_ASSERT_ALWAYS( OnStage() );
2264 // Recursively disconnect children
2267 ActorConstIter endIter = mChildren->end();
2268 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2270 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2274 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2275 disconnectionList.push_back( ActorPtr( this ) );
2277 // Notification for internal derived classes
2278 OnStageDisconnectionInternal();
2280 DisconnectFromSceneGraph();
2286 * This method is called by an actor or its parent, before a node removal message is sent.
2287 * This is recursive; the child calls DisconnectFromStage() for its children.
2289 void Actor::DisconnectFromSceneGraph()
2291 // Notification for Object::Observers
2292 OnSceneObjectRemove();
2295 void Actor::NotifyStageDisconnection()
2297 // Actors can be added (in a callback), before the off-stage state is reported.
2298 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2299 // only do this step if there is a stage, i.e. Core is not being shut down
2300 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2302 // Notification for external (CustomeActor) derived classes
2303 OnStageDisconnectionExternal();
2305 if( !mOffStageSignal.Empty() )
2307 Dali::Actor handle( this );
2308 mOffStageSignal.Emit( handle );
2311 // Guard against Add during callbacks
2314 mOnStageSignalled = false; // signal required next time Actor is added
2319 bool Actor::IsNodeConnected() const
2321 bool connected( false );
2323 if( OnStage() && ( NULL != mNode ) )
2325 if( IsRoot() || mNode->GetParent() )
2334 unsigned int Actor::GetDefaultPropertyCount() const
2336 return DEFAULT_PROPERTY_COUNT;
2339 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2341 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2343 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2345 indices.PushBack( i );
2349 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2351 if( index < DEFAULT_PROPERTY_COUNT )
2353 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2359 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2361 Property::Index index = Property::INVALID_INDEX;
2363 // Look for name in default properties
2364 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2366 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2367 if( 0 == name.compare( property->name ) )
2377 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2379 if( index < DEFAULT_PROPERTY_COUNT )
2381 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2387 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2389 if( index < DEFAULT_PROPERTY_COUNT )
2391 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2397 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2399 if( index < DEFAULT_PROPERTY_COUNT )
2401 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2407 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2409 if( index < DEFAULT_PROPERTY_COUNT )
2411 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2414 // index out of range...return Property::NONE
2415 return Property::NONE;
2418 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2422 case Dali::Actor::Property::PARENT_ORIGIN:
2424 Property::Type type = property.GetType();
2425 if( type == Property::VECTOR3 )
2427 SetParentOrigin( property.Get< Vector3 >() );
2429 else if ( type == Property::STRING )
2431 std::string parentOriginString;
2432 property.Get( parentOriginString );
2433 Vector3 parentOrigin;
2434 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2436 SetParentOrigin( parentOrigin );
2442 case Dali::Actor::Property::PARENT_ORIGIN_X:
2444 SetParentOriginX( property.Get< float >() );
2448 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2450 SetParentOriginY( property.Get< float >() );
2454 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2456 SetParentOriginZ( property.Get< float >() );
2460 case Dali::Actor::Property::ANCHOR_POINT:
2462 Property::Type type = property.GetType();
2463 if( type == Property::VECTOR3 )
2465 SetAnchorPoint( property.Get< Vector3 >() );
2467 else if ( type == Property::STRING )
2469 std::string anchorPointString;
2470 property.Get( anchorPointString );
2472 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2474 SetAnchorPoint( anchor );
2480 case Dali::Actor::Property::ANCHOR_POINT_X:
2482 SetAnchorPointX( property.Get< float >() );
2486 case Dali::Actor::Property::ANCHOR_POINT_Y:
2488 SetAnchorPointY( property.Get< float >() );
2492 case Dali::Actor::Property::ANCHOR_POINT_Z:
2494 SetAnchorPointZ( property.Get< float >() );
2498 case Dali::Actor::Property::SIZE:
2500 SetSize( property.Get< Vector3 >() );
2504 case Dali::Actor::Property::SIZE_WIDTH:
2506 SetWidth( property.Get< float >() );
2510 case Dali::Actor::Property::SIZE_HEIGHT:
2512 SetHeight( property.Get< float >() );
2516 case Dali::Actor::Property::SIZE_DEPTH:
2518 SetDepth( property.Get< float >() );
2522 case Dali::Actor::Property::POSITION:
2524 SetPosition( property.Get< Vector3 >() );
2528 case Dali::Actor::Property::POSITION_X:
2530 SetX( property.Get< float >() );
2534 case Dali::Actor::Property::POSITION_Y:
2536 SetY( property.Get< float >() );
2540 case Dali::Actor::Property::POSITION_Z:
2542 SetZ( property.Get< float >() );
2546 case Dali::Actor::Property::ORIENTATION:
2548 SetOrientation( property.Get< Quaternion >() );
2552 case Dali::Actor::Property::SCALE:
2554 SetScale( property.Get< Vector3 >() );
2558 case Dali::Actor::Property::SCALE_X:
2560 SetScaleX( property.Get< float >() );
2564 case Dali::Actor::Property::SCALE_Y:
2566 SetScaleY( property.Get< float >() );
2570 case Dali::Actor::Property::SCALE_Z:
2572 SetScaleZ( property.Get< float >() );
2576 case Dali::Actor::Property::VISIBLE:
2578 SetVisible( property.Get< bool >() );
2582 case Dali::Actor::Property::COLOR:
2584 SetColor( property.Get< Vector4 >() );
2588 case Dali::Actor::Property::COLOR_RED:
2590 SetColorRed( property.Get< float >() );
2594 case Dali::Actor::Property::COLOR_GREEN:
2596 SetColorGreen( property.Get< float >() );
2600 case Dali::Actor::Property::COLOR_BLUE:
2602 SetColorBlue( property.Get< float >() );
2606 case Dali::Actor::Property::COLOR_ALPHA:
2607 case Dali::DevelActor::Property::OPACITY:
2610 if( property.Get( value ) )
2612 SetOpacity( value );
2617 case Dali::Actor::Property::NAME:
2619 SetName( property.Get< std::string >() );
2623 case Dali::Actor::Property::SENSITIVE:
2625 SetSensitive( property.Get< bool >() );
2629 case Dali::Actor::Property::LEAVE_REQUIRED:
2631 SetLeaveRequired( property.Get< bool >() );
2635 case Dali::Actor::Property::INHERIT_POSITION:
2637 SetInheritPosition( property.Get< bool >() );
2641 case Dali::Actor::Property::INHERIT_ORIENTATION:
2643 SetInheritOrientation( property.Get< bool >() );
2647 case Dali::Actor::Property::INHERIT_SCALE:
2649 SetInheritScale( property.Get< bool >() );
2653 case Dali::Actor::Property::COLOR_MODE:
2655 ColorMode mode = mColorMode;
2656 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2658 SetColorMode( mode );
2663 case Dali::Actor::Property::POSITION_INHERITANCE:
2665 PositionInheritanceMode mode = mPositionInheritanceMode;
2666 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2668 SetPositionInheritanceMode( mode );
2673 case Dali::Actor::Property::DRAW_MODE:
2675 DrawMode::Type mode = mDrawMode;
2676 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2678 SetDrawMode( mode );
2683 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2685 SetSizeModeFactor( property.Get< Vector3 >() );
2689 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2691 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2692 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2694 SetResizePolicy( type, Dimension::WIDTH );
2699 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2701 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2702 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2704 SetResizePolicy( type, Dimension::HEIGHT );
2709 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2711 SizeScalePolicy::Type type;
2712 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2714 SetSizeScalePolicy( type );
2719 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2721 if( property.Get< bool >() )
2723 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2728 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2730 if( property.Get< bool >() )
2732 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2737 case Dali::Actor::Property::PADDING:
2739 Vector4 padding = property.Get< Vector4 >();
2740 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2741 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2745 case Dali::Actor::Property::MINIMUM_SIZE:
2747 Vector2 size = property.Get< Vector2 >();
2748 SetMinimumSize( size.x, Dimension::WIDTH );
2749 SetMinimumSize( size.y, Dimension::HEIGHT );
2753 case Dali::Actor::Property::MAXIMUM_SIZE:
2755 Vector2 size = property.Get< Vector2 >();
2756 SetMaximumSize( size.x, Dimension::WIDTH );
2757 SetMaximumSize( size.y, Dimension::HEIGHT );
2761 case Dali::DevelActor::Property::SIBLING_ORDER:
2765 if( property.Get( value ) )
2767 if( static_cast<unsigned int>(value) != mSiblingOrder )
2769 SetSiblingOrder( value );
2775 case Dali::Actor::Property::CLIPPING_MODE:
2777 ClippingMode::Type convertedValue = mClippingMode;
2778 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2780 mClippingMode = convertedValue;
2783 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2789 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2792 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2794 mPositionUsesAnchorPoint = value;
2797 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2805 // this can happen in the case of a non-animatable default property so just do nothing
2811 // TODO: This method needs to be removed
2812 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2814 switch( entry.GetType() )
2816 case Property::BOOLEAN:
2818 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2819 DALI_ASSERT_DEBUG( NULL != property );
2821 // property is being used in a separate thread; queue a message to set the property
2822 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2827 case Property::INTEGER:
2829 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2830 DALI_ASSERT_DEBUG( NULL != property );
2832 // property is being used in a separate thread; queue a message to set the property
2833 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2838 case Property::FLOAT:
2840 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2841 DALI_ASSERT_DEBUG( NULL != property );
2843 // property is being used in a separate thread; queue a message to set the property
2844 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2849 case Property::VECTOR2:
2851 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2852 DALI_ASSERT_DEBUG( NULL != property );
2854 // property is being used in a separate thread; queue a message to set the property
2855 if(entry.componentIndex == 0)
2857 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2859 else if(entry.componentIndex == 1)
2861 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2865 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2871 case Property::VECTOR3:
2873 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2874 DALI_ASSERT_DEBUG( NULL != property );
2876 // property is being used in a separate thread; queue a message to set the property
2877 if(entry.componentIndex == 0)
2879 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2881 else if(entry.componentIndex == 1)
2883 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2885 else if(entry.componentIndex == 2)
2887 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2897 case Property::VECTOR4:
2899 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2900 DALI_ASSERT_DEBUG( NULL != property );
2902 // property is being used in a separate thread; queue a message to set the property
2903 if(entry.componentIndex == 0)
2905 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2907 else if(entry.componentIndex == 1)
2909 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2911 else if(entry.componentIndex == 2)
2913 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2915 else if(entry.componentIndex == 3)
2917 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2921 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2927 case Property::ROTATION:
2929 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2930 DALI_ASSERT_DEBUG( NULL != property );
2932 // property is being used in a separate thread; queue a message to set the property
2933 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2938 case Property::MATRIX:
2940 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2941 DALI_ASSERT_DEBUG( NULL != property );
2943 // property is being used in a separate thread; queue a message to set the property
2944 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2949 case Property::MATRIX3:
2951 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2952 DALI_ASSERT_DEBUG( NULL != property );
2954 // property is being used in a separate thread; queue a message to set the property
2955 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2962 // nothing to do for other types
2967 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2969 Property::Value value;
2971 if( index >= DEFAULT_PROPERTY_COUNT )
2978 case Dali::Actor::Property::PARENT_ORIGIN:
2980 value = GetCurrentParentOrigin();
2984 case Dali::Actor::Property::PARENT_ORIGIN_X:
2986 value = GetCurrentParentOrigin().x;
2990 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2992 value = GetCurrentParentOrigin().y;
2996 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2998 value = GetCurrentParentOrigin().z;
3002 case Dali::Actor::Property::ANCHOR_POINT:
3004 value = GetCurrentAnchorPoint();
3008 case Dali::Actor::Property::ANCHOR_POINT_X:
3010 value = GetCurrentAnchorPoint().x;
3014 case Dali::Actor::Property::ANCHOR_POINT_Y:
3016 value = GetCurrentAnchorPoint().y;
3020 case Dali::Actor::Property::ANCHOR_POINT_Z:
3022 value = GetCurrentAnchorPoint().z;
3026 case Dali::Actor::Property::SIZE:
3028 Vector3 size = GetTargetSize();
3030 // Should return preferred size if size is fixed as set by SetSize
3031 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3033 size.width = GetPreferredSize().width;
3035 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3037 size.height = GetPreferredSize().height;
3045 case Dali::Actor::Property::SIZE_WIDTH:
3047 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3049 // Should return preferred size if size is fixed as set by SetSize
3050 value = GetPreferredSize().width;
3054 value = GetTargetSize().width;
3059 case Dali::Actor::Property::SIZE_HEIGHT:
3061 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3063 // Should return preferred size if size is fixed as set by SetSize
3064 value = GetPreferredSize().height;
3068 value = GetTargetSize().height;
3073 case Dali::Actor::Property::SIZE_DEPTH:
3075 value = GetTargetSize().depth;
3079 case Dali::Actor::Property::POSITION:
3081 value = GetTargetPosition();
3085 case Dali::Actor::Property::POSITION_X:
3087 value = GetTargetPosition().x;
3091 case Dali::Actor::Property::POSITION_Y:
3093 value = GetTargetPosition().y;
3097 case Dali::Actor::Property::POSITION_Z:
3099 value = GetTargetPosition().z;
3103 case Dali::Actor::Property::WORLD_POSITION:
3105 value = GetCurrentWorldPosition();
3109 case Dali::Actor::Property::WORLD_POSITION_X:
3111 value = GetCurrentWorldPosition().x;
3115 case Dali::Actor::Property::WORLD_POSITION_Y:
3117 value = GetCurrentWorldPosition().y;
3121 case Dali::Actor::Property::WORLD_POSITION_Z:
3123 value = GetCurrentWorldPosition().z;
3127 case Dali::Actor::Property::ORIENTATION:
3129 value = GetCurrentOrientation();
3133 case Dali::Actor::Property::WORLD_ORIENTATION:
3135 value = GetCurrentWorldOrientation();
3139 case Dali::Actor::Property::SCALE:
3141 value = GetCurrentScale();
3145 case Dali::Actor::Property::SCALE_X:
3147 value = GetCurrentScale().x;
3151 case Dali::Actor::Property::SCALE_Y:
3153 value = GetCurrentScale().y;
3157 case Dali::Actor::Property::SCALE_Z:
3159 value = GetCurrentScale().z;
3163 case Dali::Actor::Property::WORLD_SCALE:
3165 value = GetCurrentWorldScale();
3169 case Dali::Actor::Property::VISIBLE:
3171 value = IsVisible();
3175 case Dali::Actor::Property::COLOR:
3177 value = GetCurrentColor();
3181 case Dali::Actor::Property::COLOR_RED:
3183 value = GetCurrentColor().r;
3187 case Dali::Actor::Property::COLOR_GREEN:
3189 value = GetCurrentColor().g;
3193 case Dali::Actor::Property::COLOR_BLUE:
3195 value = GetCurrentColor().b;
3199 case Dali::Actor::Property::COLOR_ALPHA:
3200 case Dali::DevelActor::Property::OPACITY:
3202 value = GetCurrentColor().a;
3206 case Dali::Actor::Property::WORLD_COLOR:
3208 value = GetCurrentWorldColor();
3212 case Dali::Actor::Property::WORLD_MATRIX:
3214 value = GetCurrentWorldMatrix();
3218 case Dali::Actor::Property::NAME:
3224 case Dali::Actor::Property::SENSITIVE:
3226 value = IsSensitive();
3230 case Dali::Actor::Property::LEAVE_REQUIRED:
3232 value = GetLeaveRequired();
3236 case Dali::Actor::Property::INHERIT_POSITION:
3238 value = IsPositionInherited();
3242 case Dali::Actor::Property::INHERIT_ORIENTATION:
3244 value = IsOrientationInherited();
3248 case Dali::Actor::Property::INHERIT_SCALE:
3250 value = IsScaleInherited();
3254 case Dali::Actor::Property::COLOR_MODE:
3256 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3260 case Dali::Actor::Property::POSITION_INHERITANCE:
3262 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3266 case Dali::Actor::Property::DRAW_MODE:
3268 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3272 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3274 value = GetSizeModeFactor();
3278 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3280 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3284 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3286 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3290 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3292 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3296 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3298 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3302 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3304 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3308 case Dali::Actor::Property::PADDING:
3310 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3311 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3312 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3316 case Dali::Actor::Property::MINIMUM_SIZE:
3318 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3322 case Dali::Actor::Property::MAXIMUM_SIZE:
3324 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3328 case Dali::DevelActor::Property::SIBLING_ORDER:
3330 value = static_cast<int>(mSiblingOrder);
3334 case Dali::Actor::Property::CLIPPING_MODE:
3336 value = mClippingMode;
3340 case Dali::DevelActor::Property::SCREEN_POSITION:
3342 value = GetCurrentScreenPosition();
3346 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3348 value = mPositionUsesAnchorPoint;
3356 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3361 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3363 // This method should only return an object connected to the scene-graph
3364 return OnStage() ? mNode : NULL;
3367 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3369 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3371 const PropertyBase* property( NULL );
3373 // This method should only return a property of an object connected to the scene-graph
3379 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3381 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3382 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3384 property = animatable->GetSceneGraphProperty();
3386 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3387 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3389 CustomPropertyMetadata* custom = FindCustomProperty( index );
3390 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3392 property = custom->GetSceneGraphProperty();
3394 else if( NULL != mNode )
3398 case Dali::Actor::Property::SIZE:
3399 property = &mNode->mSize;
3402 case Dali::Actor::Property::SIZE_WIDTH:
3403 property = &mNode->mSize;
3406 case Dali::Actor::Property::SIZE_HEIGHT:
3407 property = &mNode->mSize;
3410 case Dali::Actor::Property::SIZE_DEPTH:
3411 property = &mNode->mSize;
3414 case Dali::Actor::Property::POSITION:
3415 property = &mNode->mPosition;
3418 case Dali::Actor::Property::POSITION_X:
3419 property = &mNode->mPosition;
3422 case Dali::Actor::Property::POSITION_Y:
3423 property = &mNode->mPosition;
3426 case Dali::Actor::Property::POSITION_Z:
3427 property = &mNode->mPosition;
3430 case Dali::Actor::Property::ORIENTATION:
3431 property = &mNode->mOrientation;
3434 case Dali::Actor::Property::SCALE:
3435 property = &mNode->mScale;
3438 case Dali::Actor::Property::SCALE_X:
3439 property = &mNode->mScale;
3442 case Dali::Actor::Property::SCALE_Y:
3443 property = &mNode->mScale;
3446 case Dali::Actor::Property::SCALE_Z:
3447 property = &mNode->mScale;
3450 case Dali::Actor::Property::VISIBLE:
3451 property = &mNode->mVisible;
3454 case Dali::Actor::Property::COLOR:
3455 property = &mNode->mColor;
3458 case Dali::Actor::Property::COLOR_RED:
3459 property = &mNode->mColor;
3462 case Dali::Actor::Property::COLOR_GREEN:
3463 property = &mNode->mColor;
3466 case Dali::Actor::Property::COLOR_BLUE:
3467 property = &mNode->mColor;
3470 case Dali::Actor::Property::COLOR_ALPHA:
3471 case Dali::DevelActor::Property::OPACITY:
3472 property = &mNode->mColor;
3483 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3485 const PropertyInputImpl* property( NULL );
3487 // This method should only return a property of an object connected to the scene-graph
3493 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3495 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3496 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3498 property = animatable->GetSceneGraphProperty();
3500 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3501 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3503 CustomPropertyMetadata* custom = FindCustomProperty( index );
3504 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3505 property = custom->GetSceneGraphProperty();
3507 else if( NULL != mNode )
3511 case Dali::Actor::Property::PARENT_ORIGIN:
3512 property = &mNode->mParentOrigin;
3515 case Dali::Actor::Property::PARENT_ORIGIN_X:
3516 property = &mNode->mParentOrigin;
3519 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3520 property = &mNode->mParentOrigin;
3523 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3524 property = &mNode->mParentOrigin;
3527 case Dali::Actor::Property::ANCHOR_POINT:
3528 property = &mNode->mAnchorPoint;
3531 case Dali::Actor::Property::ANCHOR_POINT_X:
3532 property = &mNode->mAnchorPoint;
3535 case Dali::Actor::Property::ANCHOR_POINT_Y:
3536 property = &mNode->mAnchorPoint;
3539 case Dali::Actor::Property::ANCHOR_POINT_Z:
3540 property = &mNode->mAnchorPoint;
3543 case Dali::Actor::Property::SIZE:
3544 property = &mNode->mSize;
3547 case Dali::Actor::Property::SIZE_WIDTH:
3548 property = &mNode->mSize;
3551 case Dali::Actor::Property::SIZE_HEIGHT:
3552 property = &mNode->mSize;
3555 case Dali::Actor::Property::SIZE_DEPTH:
3556 property = &mNode->mSize;
3559 case Dali::Actor::Property::POSITION:
3560 property = &mNode->mPosition;
3563 case Dali::Actor::Property::POSITION_X:
3564 property = &mNode->mPosition;
3567 case Dali::Actor::Property::POSITION_Y:
3568 property = &mNode->mPosition;
3571 case Dali::Actor::Property::POSITION_Z:
3572 property = &mNode->mPosition;
3575 case Dali::Actor::Property::WORLD_POSITION:
3576 property = &mNode->mWorldPosition;
3579 case Dali::Actor::Property::WORLD_POSITION_X:
3580 property = &mNode->mWorldPosition;
3583 case Dali::Actor::Property::WORLD_POSITION_Y:
3584 property = &mNode->mWorldPosition;
3587 case Dali::Actor::Property::WORLD_POSITION_Z:
3588 property = &mNode->mWorldPosition;
3591 case Dali::Actor::Property::ORIENTATION:
3592 property = &mNode->mOrientation;
3595 case Dali::Actor::Property::WORLD_ORIENTATION:
3596 property = &mNode->mWorldOrientation;
3599 case Dali::Actor::Property::SCALE:
3600 property = &mNode->mScale;
3603 case Dali::Actor::Property::SCALE_X:
3604 property = &mNode->mScale;
3607 case Dali::Actor::Property::SCALE_Y:
3608 property = &mNode->mScale;
3611 case Dali::Actor::Property::SCALE_Z:
3612 property = &mNode->mScale;
3615 case Dali::Actor::Property::WORLD_SCALE:
3616 property = &mNode->mWorldScale;
3619 case Dali::Actor::Property::VISIBLE:
3620 property = &mNode->mVisible;
3623 case Dali::Actor::Property::COLOR:
3624 property = &mNode->mColor;
3627 case Dali::Actor::Property::COLOR_RED:
3628 property = &mNode->mColor;
3631 case Dali::Actor::Property::COLOR_GREEN:
3632 property = &mNode->mColor;
3635 case Dali::Actor::Property::COLOR_BLUE:
3636 property = &mNode->mColor;
3639 case Dali::Actor::Property::COLOR_ALPHA:
3640 case Dali::DevelActor::Property::OPACITY:
3642 property = &mNode->mColor;
3646 case Dali::Actor::Property::WORLD_COLOR:
3647 property = &mNode->mWorldColor;
3650 case Dali::Actor::Property::WORLD_MATRIX:
3651 property = &mNode->mWorldMatrix;
3662 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3664 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3666 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3668 // check whether the animatable property is registered already, if not then register one.
3669 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3670 if( animatableProperty )
3672 componentIndex = animatableProperty->componentIndex;
3679 case Dali::Actor::Property::PARENT_ORIGIN_X:
3680 case Dali::Actor::Property::ANCHOR_POINT_X:
3681 case Dali::Actor::Property::SIZE_WIDTH:
3682 case Dali::Actor::Property::POSITION_X:
3683 case Dali::Actor::Property::WORLD_POSITION_X:
3684 case Dali::Actor::Property::SCALE_X:
3685 case Dali::Actor::Property::COLOR_RED:
3691 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3692 case Dali::Actor::Property::ANCHOR_POINT_Y:
3693 case Dali::Actor::Property::SIZE_HEIGHT:
3694 case Dali::Actor::Property::POSITION_Y:
3695 case Dali::Actor::Property::WORLD_POSITION_Y:
3696 case Dali::Actor::Property::SCALE_Y:
3697 case Dali::Actor::Property::COLOR_GREEN:
3703 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3704 case Dali::Actor::Property::ANCHOR_POINT_Z:
3705 case Dali::Actor::Property::SIZE_DEPTH:
3706 case Dali::Actor::Property::POSITION_Z:
3707 case Dali::Actor::Property::WORLD_POSITION_Z:
3708 case Dali::Actor::Property::SCALE_Z:
3709 case Dali::Actor::Property::COLOR_BLUE:
3715 case Dali::Actor::Property::COLOR_ALPHA:
3716 case Dali::DevelActor::Property::OPACITY:
3730 return componentIndex;
3733 void Actor::SetParent( Actor* parent )
3737 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3741 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3744 // Instruct each actor to create a corresponding node in the scene graph
3745 ConnectToStage( parent->GetHierarchyDepth() );
3748 // Resolve the name and index for the child properties if any
3749 ResolveChildProperties();
3751 else // parent being set to NULL
3753 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3757 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3760 DALI_ASSERT_ALWAYS( mNode != NULL );
3764 // Disconnect the Node & its children from the scene-graph.
3765 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3768 // Instruct each actor to discard pointers to the scene-graph
3769 DisconnectFromStage();
3774 SceneGraph::Node* Actor::CreateNode() const
3779 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3782 Actor* actor = dynamic_cast< Actor* >( object );
3786 if( 0 == actionName.compare( ACTION_SHOW ) )
3788 actor->SetVisible( true );
3791 else if( 0 == actionName.compare( ACTION_HIDE ) )
3793 actor->SetVisible( false );
3801 void Actor::EnsureRelayoutData()
3803 // Assign relayout data.
3804 if( !mRelayoutData )
3806 mRelayoutData = new RelayoutData();
3810 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3812 // Check if actor is dependent on parent
3813 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3815 if( ( dimension & ( 1 << i ) ) )
3817 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3818 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3828 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3830 // Check if actor is dependent on children
3831 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3833 if( ( dimension & ( 1 << i ) ) )
3835 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3836 switch( resizePolicy )
3838 case ResizePolicy::FIT_TO_CHILDREN:
3839 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3855 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3857 return Actor::RelayoutDependentOnChildren( dimension );
3860 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3862 // Check each possible dimension and see if it is dependent on the input one
3863 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3865 if( dimension & ( 1 << i ) )
3867 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3874 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3876 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3878 if( dimension & ( 1 << i ) )
3880 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3885 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3887 // If more than one dimension is requested, just return the first one found
3888 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3890 if( ( dimension & ( 1 << i ) ) )
3892 return mRelayoutData->negotiatedDimensions[ i ];
3896 return 0.0f; // Default
3899 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3901 EnsureRelayoutData();
3903 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3905 if( dimension & ( 1 << i ) )
3907 mRelayoutData->dimensionPadding[ i ] = padding;
3912 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3914 if ( mRelayoutData )
3916 // If more than one dimension is requested, just return the first one found
3917 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3919 if( ( dimension & ( 1 << i ) ) )
3921 return mRelayoutData->dimensionPadding[ i ];
3926 return GetDefaultDimensionPadding();
3929 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3931 EnsureRelayoutData();
3933 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3935 if( dimension & ( 1 << i ) )
3937 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3942 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3944 if ( mRelayoutData )
3946 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3948 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3958 float Actor::GetHeightForWidthBase( float width )
3960 float height = 0.0f;
3962 const Vector3 naturalSize = GetNaturalSize();
3963 if( naturalSize.width > 0.0f )
3965 height = naturalSize.height * width / naturalSize.width;
3967 else // we treat 0 as 1:1 aspect ratio
3975 float Actor::GetWidthForHeightBase( float height )
3979 const Vector3 naturalSize = GetNaturalSize();
3980 if( naturalSize.height > 0.0f )
3982 width = naturalSize.width * height / naturalSize.height;
3984 else // we treat 0 as 1:1 aspect ratio
3992 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3994 // Fill to parent, taking size mode factor into account
3995 switch( child.GetResizePolicy( dimension ) )
3997 case ResizePolicy::FILL_TO_PARENT:
3999 return GetLatestSize( dimension );
4002 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4004 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4007 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4009 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4014 return GetLatestSize( dimension );
4019 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4021 // Can be overridden in derived class
4022 return CalculateChildSizeBase( child, dimension );
4025 float Actor::GetHeightForWidth( float width )
4027 // Can be overridden in derived class
4028 return GetHeightForWidthBase( width );
4031 float Actor::GetWidthForHeight( float height )
4033 // Can be overridden in derived class
4034 return GetWidthForHeightBase( height );
4037 float Actor::GetLatestSize( Dimension::Type dimension ) const
4039 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4042 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4044 Vector2 padding = GetPadding( dimension );
4046 return GetLatestSize( dimension ) + padding.x + padding.y;
4049 float Actor::NegotiateFromParent( Dimension::Type dimension )
4051 Actor* parent = GetParent();
4054 Vector2 padding( GetPadding( dimension ) );
4055 Vector2 parentPadding( parent->GetPadding( dimension ) );
4056 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4062 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4064 float maxDimensionPoint = 0.0f;
4066 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4068 ActorPtr child = GetChildAt( i );
4070 if( !child->RelayoutDependentOnParent( dimension ) )
4072 // Calculate the min and max points that the children range across
4073 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4074 float dimensionSize = child->GetRelayoutSize( dimension );
4075 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4079 return maxDimensionPoint;
4082 float Actor::GetSize( Dimension::Type dimension ) const
4084 return GetDimensionValue( GetTargetSize(), dimension );
4087 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4089 return GetDimensionValue( GetNaturalSize(), dimension );
4092 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4094 switch( GetResizePolicy( dimension ) )
4096 case ResizePolicy::USE_NATURAL_SIZE:
4098 return GetNaturalSize( dimension );
4101 case ResizePolicy::FIXED:
4103 return GetDimensionValue( GetPreferredSize(), dimension );
4106 case ResizePolicy::USE_ASSIGNED_SIZE:
4108 return GetDimensionValue( maximumSize, dimension );
4111 case ResizePolicy::FILL_TO_PARENT:
4112 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4113 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4115 return NegotiateFromParent( dimension );
4118 case ResizePolicy::FIT_TO_CHILDREN:
4120 return NegotiateFromChildren( dimension );
4123 case ResizePolicy::DIMENSION_DEPENDENCY:
4125 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4128 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4130 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4133 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4135 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4147 return 0.0f; // Default
4150 float Actor::ClampDimension( float size, Dimension::Type dimension )
4152 const float minSize = GetMinimumSize( dimension );
4153 const float maxSize = GetMaximumSize( dimension );
4155 return std::max( minSize, std::min( size, maxSize ) );
4158 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4160 // Check if it needs to be negotiated
4161 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4163 // Check that we havn't gotten into an infinite loop
4164 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4165 bool recursionFound = false;
4166 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4168 if( *it == searchActor )
4170 recursionFound = true;
4175 if( !recursionFound )
4177 // Record the path that we have taken
4178 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4180 // Dimension dependency check
4181 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4183 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4185 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4187 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4191 // Parent dependency check
4192 Actor* parent = GetParent();
4193 if( parent && RelayoutDependentOnParent( dimension ) )
4195 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4198 // Children dependency check
4199 if( RelayoutDependentOnChildren( dimension ) )
4201 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4203 ActorPtr child = GetChildAt( i );
4205 // Only relayout child first if it is not dependent on this actor
4206 if( !child->RelayoutDependentOnParent( dimension ) )
4208 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4213 // For deriving classes
4214 OnCalculateRelayoutSize( dimension );
4216 // All dependencies checked, calculate the size and set negotiated flag
4217 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4219 SetNegotiatedDimension( newSize, dimension );
4220 SetLayoutNegotiated( true, dimension );
4222 // For deriving classes
4223 OnLayoutNegotiated( newSize, dimension );
4225 // This actor has been successfully processed, pop it off the recursion stack
4226 recursionStack.pop_back();
4230 // TODO: Break infinite loop
4231 SetLayoutNegotiated( true, dimension );
4236 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4238 // Negotiate all dimensions that require it
4239 ActorDimensionStack recursionStack;
4241 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4243 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4246 NegotiateDimension( dimension, allocatedSize, recursionStack );
4250 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4252 switch( mRelayoutData->sizeSetPolicy )
4254 case SizeScalePolicy::USE_SIZE_SET:
4259 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4261 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4262 const Vector3 naturalSize = GetNaturalSize();
4263 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4265 const float sizeRatio = size.width / size.height;
4266 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4268 if( naturalSizeRatio < sizeRatio )
4270 return Vector2( naturalSizeRatio * size.height, size.height );
4272 else if( naturalSizeRatio > sizeRatio )
4274 return Vector2( size.width, size.width / naturalSizeRatio );
4285 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4287 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4288 const Vector3 naturalSize = GetNaturalSize();
4289 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4291 const float sizeRatio = size.width / size.height;
4292 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4294 if( naturalSizeRatio < sizeRatio )
4296 return Vector2( size.width, size.width / naturalSizeRatio );
4298 else if( naturalSizeRatio > sizeRatio )
4300 return Vector2( naturalSizeRatio * size.height, size.height );
4319 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4321 // Do the set actor size
4322 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4324 // Adjust for size set policy
4325 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4327 // Lock the flag to stop recursive relayouts on set size
4328 mRelayoutData->insideRelayout = true;
4329 SetSize( negotiatedSize );
4330 mRelayoutData->insideRelayout = false;
4332 // Clear flags for all dimensions
4333 SetLayoutDirty( false );
4335 // Give deriving classes a chance to respond
4336 OnRelayout( negotiatedSize, container );
4338 if( !mOnRelayoutSignal.Empty() )
4340 Dali::Actor handle( this );
4341 mOnRelayoutSignal.Emit( handle );
4345 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4347 // Force a size negotiation for actors that has assigned size during relayout
4348 // This is required as otherwise the flags that force a relayout will not
4349 // necessarilly be set. This will occur if the actor has already been laid out.
4350 // The dirty flags are then cleared. Then if the actor is added back into the
4351 // relayout container afterwards, the dirty flags would still be clear...
4352 // causing a relayout to be skipped. Here we force any actors added to the
4353 // container to be relayed out.
4354 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4356 SetLayoutNegotiated(false, Dimension::WIDTH);
4358 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4360 SetLayoutNegotiated(false, Dimension::HEIGHT);
4363 // Do the negotiation
4364 NegotiateDimensions( allocatedSize );
4366 // Set the actor size
4367 SetNegotiatedSize( container );
4369 // Negotiate down to children
4370 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4372 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4374 ActorPtr child = GetChildAt( i );
4376 // Forces children that have already been laid out to be relayed out
4377 // if they have assigned size during relayout.
4378 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4380 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4381 child->SetLayoutDirty(true, Dimension::WIDTH);
4383 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4385 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4386 child->SetLayoutDirty(true, Dimension::HEIGHT);
4389 // Only relayout if required
4390 if( child->RelayoutRequired() )
4392 container.Add( Dali::Actor( child.Get() ), newBounds );
4397 void Actor::RelayoutRequest( Dimension::Type dimension )
4399 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4400 if( relayoutController )
4402 Dali::Actor self( this );
4403 relayoutController->RequestRelayout( self, dimension );
4407 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4411 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4415 void Actor::SetPreferredSize( const Vector2& size )
4417 EnsureRelayoutData();
4419 if( size.width > 0.0f )
4421 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4424 if( size.height > 0.0f )
4426 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4429 mRelayoutData->preferredSize = size;
4434 Vector2 Actor::GetPreferredSize() const
4436 if ( mRelayoutData )
4438 return Vector2( mRelayoutData->preferredSize );
4441 return GetDefaultPreferredSize();
4444 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4446 EnsureRelayoutData();
4448 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4450 if( dimension & ( 1 << i ) )
4452 mRelayoutData->minimumSize[ i ] = size;
4459 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4461 if ( mRelayoutData )
4463 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4465 if( dimension & ( 1 << i ) )
4467 return mRelayoutData->minimumSize[ i ];
4472 return 0.0f; // Default
4475 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4477 EnsureRelayoutData();
4479 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4481 if( dimension & ( 1 << i ) )
4483 mRelayoutData->maximumSize[ i ] = size;
4490 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4492 if ( mRelayoutData )
4494 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4496 if( dimension & ( 1 << i ) )
4498 return mRelayoutData->maximumSize[ i ];
4503 return FLT_MAX; // Default
4506 Object* Actor::GetParentObject() const
4511 void Actor::SetSiblingOrder( unsigned int order )
4513 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4516 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4520 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4522 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4523 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4525 // Start at index 0, while index <= highest order
4526 // Find next index higher than 0
4527 // if nextHigher > index+1
4528 // set all nextHigher orders to index+1
4530 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4532 ActorIter end = siblings.end();
4533 int highestOrder = 0;
4534 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4536 ActorPtr sibling = (*iter);
4537 int siblingOrder = sibling->mSiblingOrder;
4538 highestOrder = std::max( highestOrder, siblingOrder );
4541 for ( int index = 0; index <= highestOrder; index++ )
4543 int nextHighest = -1;
4545 // Find Next highest
4546 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4548 ActorPtr sibling = (*iter);
4549 int siblingOrder = sibling->mSiblingOrder;
4551 if ( siblingOrder > index )
4553 if ( nextHighest == -1 )
4555 nextHighest = siblingOrder;
4557 nextHighest = std::min( nextHighest, siblingOrder );
4561 // Check if a gap exists between indexes, if so set next index to consecutive number
4562 if ( ( nextHighest - index ) > 1 )
4564 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4566 ActorPtr sibling = (*iter);
4567 int siblingOrder = sibling->mSiblingOrder;
4568 if ( siblingOrder == nextHighest )
4570 sibling->mSiblingOrder = index + 1;
4571 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4573 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4574 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4576 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4583 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4585 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4586 bool defragmentationRequired( false );
4587 ActorIter end = siblings.end();
4588 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4590 // Move actors at nearest order and above up by 1
4591 ActorPtr sibling = (*iter);
4592 if ( sibling != this )
4594 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4595 // be incremented by 1.
4596 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4598 sibling->mSiblingOrder++;
4599 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4601 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4602 // can re-order all sibling orders.
4603 defragmentationRequired = true;
4605 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4609 return defragmentationRequired;
4615 1) Check if already at top and nothing to be done.
4616 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4617 order can be positioned above it due to insertion order of actors.
4618 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4619 3) a) There may be other levels above this target level
4620 b) Increment all sibling levels at the level above nearest(target)
4621 c) Now have a vacant sibling level
4622 4) Set this actor's sibling level to nearest +1 as now vacated.
4624 Note May not just be sibling level + 1 as could be empty levels in-between
4629 ActorC ( sibling level 4 )
4630 ActorB ( sibling level 3 )
4631 ActorA ( sibling level 1 )
4633 2 ) ACTION: Raise A above B
4634 a) Find nearest level above A = Level 3
4635 b) Increment levels above Level 3
4637 ActorC ( sibling level 5 )
4638 ActorB ( sibling level 3 ) NEAREST
4639 ActorA ( sibling level 1 )
4641 3 ) Set Actor A sibling level to nearest +1 as vacant
4643 ActorC ( sibling level 5 )
4644 ActorA ( sibling level 4 )
4645 ActorB ( sibling level 3 )
4647 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4648 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4649 remove any empty sibling order gaps and start from sibling level 0 again.
4650 If the number of actors reaches this maximum and all using exclusive sibling order values then
4651 defragmention will stop and new sibling orders will be set to same max value.
4655 int nearestLevel = mSiblingOrder;
4656 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4657 bool defragmentationRequired( false );
4659 ActorContainer* siblings = mParent->mChildren;
4661 // Find Nearest sibling level above this actor
4662 ActorIter end = siblings->end();
4663 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4665 ActorPtr sibling = (*iter);
4666 if ( sibling != this )
4668 int order = GetSiblingOrder( sibling );
4670 if ( ( order >= mSiblingOrder ) )
4672 int distanceToNextLevel = order - mSiblingOrder;
4673 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4675 nearestLevel = order;
4676 shortestDistanceToNextLevel = distanceToNextLevel;
4682 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4684 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4685 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4686 // Move current actor to newly vacated order level
4687 SetSiblingOrder( mSiblingOrder );
4688 if ( defragmentationRequired )
4690 DefragmentSiblingIndexes( *siblings );
4693 SetSiblingOrder( mSiblingOrder );
4697 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4704 1) Check if actor already at bottom and if nothing needs to be done
4705 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4706 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4707 2) Find nearest sibling level below, this Actor needs to be below it
4708 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4709 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4710 c) Set this actor's sibling level to this newly vacated level.
4711 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4712 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4713 remove any empty sibling order gaps and start from sibling level 0 again.
4714 If the number of actors reaches this maximum and all using exclusive sibling order values then
4715 defragmention will stop and new sibling orders will be set to same max value.
4720 // 1) Find nearest level below
4721 int nearestLevel = mSiblingOrder;
4722 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4724 ActorContainer* siblings = mParent->mChildren;
4726 ActorIter end = siblings->end();
4727 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4729 ActorPtr sibling = (*iter);
4730 if ( sibling != this )
4732 int order = GetSiblingOrder( sibling );
4734 if ( order <= mSiblingOrder )
4736 int distanceToNextLevel = mSiblingOrder - order;
4737 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4739 nearestLevel = order;
4740 shortestDistanceToNextLevel = distanceToNextLevel;
4746 bool defragmentationRequired ( false );
4748 // 2) If actor already not at bottom, raise all actors at required level and above
4749 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4751 mSiblingOrder = nearestLevel;
4752 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4753 // Move current actor to newly vacated order
4754 SetSiblingOrder( mSiblingOrder );
4755 if ( defragmentationRequired )
4757 DefragmentSiblingIndexes( *siblings );
4763 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4767 void Actor::RaiseToTop()
4770 1 ) Find highest sibling order actor
4771 2 ) If highest sibling level not itself then set sibling order to that + 1
4772 3 ) highest sibling order can be same as itself so need to increment over that
4773 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4774 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4775 remove any empty sibling order gaps and start from sibling level 0 again.
4776 If the number of actors reaches this maximum and all using exclusive sibling order values then
4777 defragmention will stop and new sibling orders will be set to same max value.
4784 ActorContainer* siblings = mParent->mChildren;
4786 ActorIter end = siblings->end();
4787 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4789 ActorPtr sibling = (*iter);
4790 if ( sibling != this )
4792 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4796 bool defragmentationRequired( false );
4798 if ( maxOrder >= mSiblingOrder )
4800 mSiblingOrder = maxOrder + 1;
4801 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4803 defragmentationRequired = true;
4807 SetSiblingOrder( mSiblingOrder );
4809 if ( defragmentationRequired )
4811 DefragmentSiblingIndexes( *siblings );
4816 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4820 void Actor::LowerToBottom()
4823 See Actor::LowerToBottom()
4825 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4826 2 ) a ) Check if the bottom position 0 is vacant.
4827 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4828 c ) 0 sibling position is vacant.
4829 3 ) Set this actor to vacant sibling order 0;
4830 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4831 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4832 remove any empty sibling order gaps and start from sibling level 0 again.
4833 If the number of actors reaches this maximum and all using exclusive sibling order values then
4834 defragmention will stop and new sibling orders will be set to same max value.
4839 bool defragmentationRequired( false );
4840 bool orderZeroFree ( true );
4842 ActorContainer* siblings = mParent->mChildren;
4844 bool actorAtLowestOrder = true;
4845 ActorIter end = siblings->end();
4846 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4848 ActorPtr sibling = (*iter);
4849 if ( sibling != this )
4851 int siblingOrder = GetSiblingOrder( sibling );
4852 if ( siblingOrder <= mSiblingOrder )
4854 actorAtLowestOrder = false;
4857 if ( siblingOrder == 0 )
4859 orderZeroFree = false;
4864 if ( ! actorAtLowestOrder )
4866 if ( ! orderZeroFree )
4868 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4871 SetSiblingOrder( mSiblingOrder );
4873 if ( defragmentationRequired )
4875 DefragmentSiblingIndexes( *siblings );
4881 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4885 void Actor::RaiseAbove( Internal::Actor& target )
4888 1 ) a) Find target actor's sibling order
4889 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4890 needs to be above it or the insertion order will determine which is drawn on top.
4891 2 ) Shift up by 1 all sibling order greater than target sibling order
4892 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4893 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4894 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4895 remove any empty sibling order gaps and start from sibling level 0 again.
4896 If the number of actors reaches this maximum and all using exclusive sibling order values then
4897 defragmention will stop and new sibling orders will be set to same max value.
4902 if ( ValidateActors( *this, target ) )
4904 // Find target's sibling order
4905 // Set actor sibling order to this number +1
4906 int targetSiblingOrder = GetSiblingOrder( &target );
4907 ActorContainer* siblings = mParent->mChildren;
4908 mSiblingOrder = targetSiblingOrder + 1;
4909 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4911 SetSiblingOrder( mSiblingOrder );
4913 if ( defragmentationRequired )
4915 DefragmentSiblingIndexes( *(mParent->mChildren) );
4921 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4925 void Actor::LowerBelow( Internal::Actor& target )
4928 1 ) a) Find target actor's sibling order
4929 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4930 needs to be below it or the insertion order will determine which is drawn on top.
4931 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4932 3 ) Set this actor to the sibling order of the target before it changed.
4933 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4934 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4935 remove any empty sibling order gaps and start from sibling level 0 again.
4936 If the number of actors reaches this maximum and all using exclusive sibling order values then
4937 defragmention will stop and new sibling orders will be set to same max value.
4942 if ( ValidateActors( *this, target ) )
4944 bool defragmentationRequired ( false );
4945 // Find target's sibling order
4946 // Set actor sibling order to target sibling order - 1
4947 int targetSiblingOrder = GetSiblingOrder( &target);
4948 ActorContainer* siblings = mParent->mChildren;
4949 if ( targetSiblingOrder == 0 )
4952 ActorIter end = siblings->end();
4953 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4955 ActorPtr sibling = (*iter);
4956 if ( sibling != this )
4958 sibling->mSiblingOrder++;
4959 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4961 defragmentationRequired = true;
4963 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4970 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
4972 mSiblingOrder = targetSiblingOrder;
4974 SetSiblingOrder( mSiblingOrder );
4976 if ( defragmentationRequired )
4978 DefragmentSiblingIndexes( *(mParent->mChildren) );
4984 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4988 } // namespace Internal