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 // Anchor point offset first set to TOP_LEFT (0,0.5) then moved to required anchor point.
818 Vector3 anchorPointOffSet = halfActorSize - actorSize * GetCurrentAnchorPoint();
820 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
821 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
824 return Vector2::ZERO;
827 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
829 // this flag is not animatable so keep the value
830 mPositionInheritanceMode = mode;
833 // mNode is being used in a separate thread; queue a message to set the value
834 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
838 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
840 // Cached for event-thread access
841 return mPositionInheritanceMode;
844 void Actor::SetInheritPosition( bool inherit )
846 if( mInheritPosition != inherit && NULL != mNode )
848 // non animateable so keep local copy
849 mInheritPosition = inherit;
850 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
854 bool Actor::IsPositionInherited() const
856 return mInheritPosition;
859 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
861 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
862 normalizedAxis.Normalize();
864 Quaternion orientation( angle, normalizedAxis );
866 SetOrientation( orientation );
869 void Actor::SetOrientation( const Quaternion& orientation )
873 // mNode is being used in a separate thread; queue a message to set the value & base value
874 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
878 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
882 // mNode is being used in a separate thread; queue a message to set the value & base value
883 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
887 void Actor::RotateBy( const Quaternion& relativeRotation )
891 // mNode is being used in a separate thread; queue a message to set the value & base value
892 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
896 const Quaternion& Actor::GetCurrentOrientation() const
900 // mNode is being used in a separate thread; copy the value from the previous update
901 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
904 return Quaternion::IDENTITY;
907 const Quaternion& Actor::GetCurrentWorldOrientation() const
911 // mNode is being used in a separate thread; copy the value from the previous update
912 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
915 return Quaternion::IDENTITY;
918 void Actor::SetScale( float scale )
920 SetScale( Vector3( scale, scale, scale ) );
923 void Actor::SetScale( float x, float y, float z )
925 SetScale( Vector3( x, y, z ) );
928 void Actor::SetScale( const Vector3& scale )
932 // mNode is being used in a separate thread; queue a message to set the value & base value
933 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
937 void Actor::SetScaleX( float x )
941 // mNode is being used in a separate thread; queue a message to set the value & base value
942 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
946 void Actor::SetScaleY( float y )
950 // mNode is being used in a separate thread; queue a message to set the value & base value
951 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
955 void Actor::SetScaleZ( float z )
959 // mNode is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
964 void Actor::ScaleBy(const Vector3& relativeScale)
968 // mNode is being used in a separate thread; queue a message to set the value & base value
969 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
973 const Vector3& Actor::GetCurrentScale() const
977 // mNode is being used in a separate thread; copy the value from the previous update
978 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
984 const Vector3& Actor::GetCurrentWorldScale() const
988 // mNode is being used in a separate thread; copy the value from the previous update
989 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
995 void Actor::SetInheritScale( bool inherit )
998 if( mInheritScale != inherit && NULL != mNode )
1000 // non animateable so keep local copy
1001 mInheritScale = inherit;
1002 // mNode is being used in a separate thread; queue a message to set the value
1003 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1007 bool Actor::IsScaleInherited() const
1009 return mInheritScale;
1012 Matrix Actor::GetCurrentWorldMatrix() const
1016 return mNode->GetWorldMatrix(0);
1019 return Matrix::IDENTITY;
1022 void Actor::SetVisible( bool visible )
1026 // mNode is being used in a separate thread; queue a message to set the value & base value
1027 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1031 bool Actor::IsVisible() const
1035 // mNode is being used in a separate thread; copy the value from the previous update
1036 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1042 void Actor::SetOpacity( float opacity )
1046 // mNode is being used in a separate thread; queue a message to set the value & base value
1047 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1051 float Actor::GetCurrentOpacity() const
1055 // mNode is being used in a separate thread; copy the value from the previous update
1056 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1062 ClippingMode::Type Actor::GetClippingMode() const
1064 return mClippingMode;
1067 unsigned int Actor::GetSortingDepth()
1069 return GetDepthIndex( mDepth, mSiblingOrder );
1072 const Vector4& Actor::GetCurrentWorldColor() const
1076 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1079 return Color::WHITE;
1082 void Actor::SetColor( const Vector4& color )
1086 // mNode is being used in a separate thread; queue a message to set the value & base value
1087 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1091 void Actor::SetColorRed( float red )
1095 // mNode is being used in a separate thread; queue a message to set the value & base value
1096 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1100 void Actor::SetColorGreen( float green )
1104 // mNode is being used in a separate thread; queue a message to set the value & base value
1105 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1109 void Actor::SetColorBlue( float blue )
1113 // mNode is being used in a separate thread; queue a message to set the value & base value
1114 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1118 const Vector4& Actor::GetCurrentColor() const
1122 // mNode is being used in a separate thread; copy the value from the previous update
1123 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1126 return Color::WHITE;
1129 void Actor::SetInheritOrientation( bool inherit )
1131 if( mInheritOrientation != inherit && NULL != mNode)
1133 // non animateable so keep local copy
1134 mInheritOrientation = inherit;
1135 // mNode is being used in a separate thread; queue a message to set the value
1136 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1140 bool Actor::IsOrientationInherited() const
1142 return mInheritOrientation;
1145 void Actor::SetSizeModeFactor( const Vector3& factor )
1147 EnsureRelayoutData();
1149 mRelayoutData->sizeModeFactor = factor;
1152 const Vector3& Actor::GetSizeModeFactor() const
1154 if ( mRelayoutData )
1156 return mRelayoutData->sizeModeFactor;
1159 return GetDefaultSizeModeFactor();
1162 void Actor::SetColorMode( ColorMode colorMode )
1164 // non animateable so keep local copy
1165 mColorMode = colorMode;
1168 // mNode is being used in a separate thread; queue a message to set the value
1169 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1173 ColorMode Actor::GetColorMode() const
1175 // we have cached copy
1179 void Actor::SetSize( float width, float height )
1181 SetSize( Vector2( width, height ) );
1184 void Actor::SetSize( float width, float height, float depth )
1186 SetSize( Vector3( width, height, depth ) );
1189 void Actor::SetSize( const Vector2& size )
1191 SetSize( Vector3( size.width, size.height, 0.f ) );
1194 void Actor::SetSizeInternal( const Vector2& size )
1196 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1199 void Actor::SetSize( const Vector3& size )
1201 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1203 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1204 SetPreferredSize( size.GetVectorXY() );
1208 SetSizeInternal( size );
1212 void Actor::SetSizeInternal( const Vector3& size )
1214 // dont allow recursive loop
1215 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1216 // 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
1217 if( ( NULL != mNode )&&
1218 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1219 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1220 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1224 // mNode is being used in a separate thread; queue a message to set the value & base value
1225 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1227 // Notification for derived classes
1228 mInsideOnSizeSet = true;
1229 OnSizeSet( mTargetSize );
1230 mInsideOnSizeSet = false;
1232 // Raise a relayout request if the flag is not locked
1233 if( mRelayoutData && !mRelayoutData->insideRelayout )
1240 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1242 mTargetSize = targetSize;
1244 // Notify deriving classes
1245 OnSizeAnimation( animation, mTargetSize );
1248 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1250 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1252 mTargetSize.width = targetSize;
1254 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1256 mTargetSize.height = targetSize;
1258 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1260 mTargetSize.depth = targetSize;
1262 // Notify deriving classes
1263 OnSizeAnimation( animation, mTargetSize );
1266 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1268 mTargetPosition = targetPosition;
1271 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1273 if ( Dali::Actor::Property::POSITION_X == property )
1275 mTargetPosition.x = targetPosition;
1277 else if ( Dali::Actor::Property::POSITION_Y == property )
1279 mTargetPosition.y = targetPosition;
1281 else if ( Dali::Actor::Property::POSITION_Z == property )
1283 mTargetPosition.z = targetPosition;
1287 void Actor::SetWidth( float width )
1289 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1291 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1292 mRelayoutData->preferredSize.width = width;
1296 mTargetSize.width = width;
1300 // mNode is being used in a separate thread; queue a message to set the value & base value
1301 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1308 void Actor::SetHeight( float height )
1310 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1312 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1313 mRelayoutData->preferredSize.height = height;
1317 mTargetSize.height = height;
1321 // mNode is being used in a separate thread; queue a message to set the value & base value
1322 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1329 void Actor::SetDepth( float depth )
1331 mTargetSize.depth = depth;
1335 // mNode is being used in a separate thread; queue a message to set the value & base value
1336 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1340 const Vector3& Actor::GetTargetSize() const
1345 const Vector3& Actor::GetCurrentSize() const
1349 // mNode is being used in a separate thread; copy the value from the previous update
1350 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1353 return Vector3::ZERO;
1356 Vector3 Actor::GetNaturalSize() const
1358 // It is up to deriving classes to return the appropriate natural size
1359 return Vector3( 0.0f, 0.0f, 0.0f );
1362 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1364 EnsureRelayoutData();
1366 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1367 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1369 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1371 if( dimension & ( 1 << i ) )
1373 mRelayoutData->resizePolicies[ i ] = policy;
1377 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1379 if( dimension & Dimension::WIDTH )
1381 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1384 if( dimension & Dimension::HEIGHT )
1386 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1390 // If calling SetResizePolicy, assume we want relayout enabled
1391 SetRelayoutEnabled( true );
1393 // If the resize policy is set to be FIXED, the preferred size
1394 // should be overrided by the target size. Otherwise the target
1395 // size should be overrided by the preferred size.
1397 if( dimension & Dimension::WIDTH )
1399 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1401 mRelayoutData->preferredSize.width = mTargetSize.width;
1403 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1405 mTargetSize.width = mRelayoutData->preferredSize.width;
1409 if( dimension & Dimension::HEIGHT )
1411 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1413 mRelayoutData->preferredSize.height = mTargetSize.height;
1415 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1417 mTargetSize.height = mRelayoutData->preferredSize.height;
1421 OnSetResizePolicy( policy, dimension );
1423 // Trigger relayout on this control
1427 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1429 if ( mRelayoutData )
1431 // If more than one dimension is requested, just return the first one found
1432 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1434 if( ( dimension & ( 1 << i ) ) )
1436 return mRelayoutData->resizePolicies[ i ];
1441 return ResizePolicy::DEFAULT;
1444 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1446 EnsureRelayoutData();
1448 mRelayoutData->sizeSetPolicy = policy;
1451 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1453 if ( mRelayoutData )
1455 return mRelayoutData->sizeSetPolicy;
1458 return DEFAULT_SIZE_SCALE_POLICY;
1461 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1463 EnsureRelayoutData();
1465 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1467 if( dimension & ( 1 << i ) )
1469 mRelayoutData->dimensionDependencies[ i ] = dependency;
1474 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1476 if ( mRelayoutData )
1478 // If more than one dimension is requested, just return the first one found
1479 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1481 if( ( dimension & ( 1 << i ) ) )
1483 return mRelayoutData->dimensionDependencies[ i ];
1488 return Dimension::ALL_DIMENSIONS; // Default
1491 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1493 // If relayout data has not been allocated yet and the client is requesting
1494 // to disable it, do nothing
1495 if( mRelayoutData || relayoutEnabled )
1497 EnsureRelayoutData();
1499 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1501 mRelayoutData->relayoutEnabled = relayoutEnabled;
1505 bool Actor::IsRelayoutEnabled() const
1507 // Assume that if relayout data has not been allocated yet then
1508 // relayout is disabled
1509 return mRelayoutData && mRelayoutData->relayoutEnabled;
1512 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1514 EnsureRelayoutData();
1516 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1518 if( dimension & ( 1 << i ) )
1520 mRelayoutData->dimensionDirty[ i ] = dirty;
1525 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1527 if ( mRelayoutData )
1529 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1531 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1541 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1543 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1546 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1548 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1551 unsigned int Actor::AddRenderer( Renderer& renderer )
1555 mRenderers = new RendererContainer;
1558 unsigned int index = mRenderers->size();
1559 RendererPtr rendererPtr = RendererPtr( &renderer );
1560 mRenderers->push_back( rendererPtr );
1561 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1565 unsigned int Actor::GetRendererCount() const
1567 unsigned int rendererCount(0);
1570 rendererCount = mRenderers->size();
1573 return rendererCount;
1576 RendererPtr Actor::GetRendererAt( unsigned int index )
1578 RendererPtr renderer;
1579 if( index < GetRendererCount() )
1581 renderer = ( *mRenderers )[ index ];
1587 void Actor::RemoveRenderer( Renderer& renderer )
1591 RendererIter end = mRenderers->end();
1592 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1594 if( (*iter).Get() == &renderer )
1596 mRenderers->erase( iter );
1597 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1604 void Actor::RemoveRenderer( unsigned int index )
1606 if( index < GetRendererCount() )
1608 RendererPtr renderer = ( *mRenderers )[ index ];
1609 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1610 mRenderers->erase( mRenderers->begin()+index );
1614 bool Actor::IsOverlay() const
1616 return ( DrawMode::OVERLAY_2D == mDrawMode );
1619 void Actor::SetDrawMode( DrawMode::Type drawMode )
1621 // this flag is not animatable so keep the value
1622 mDrawMode = drawMode;
1623 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1625 // mNode is being used in a separate thread; queue a message to set the value
1626 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1630 DrawMode::Type Actor::GetDrawMode() const
1635 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1637 // only valid when on-stage
1638 StagePtr stage = Stage::GetCurrent();
1639 if( stage && OnStage() )
1641 const RenderTaskList& taskList = stage->GetRenderTaskList();
1643 Vector2 converted( screenX, screenY );
1645 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1646 const int taskCount = taskList.GetTaskCount();
1647 for( int i = taskCount - 1; i >= 0; --i )
1649 Dali::RenderTask task = taskList.GetTask( i );
1650 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1652 // found a task where this conversion was ok so return
1660 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1662 bool retval = false;
1663 // only valid when on-stage
1666 CameraActor* camera = renderTask.GetCameraActor();
1670 renderTask.GetViewport( viewport );
1672 // need to translate coordinates to render tasks coordinate space
1673 Vector2 converted( screenX, screenY );
1674 if( renderTask.TranslateCoordinates( converted ) )
1676 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1683 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1685 // Early-out if mNode is NULL
1691 // Get the ModelView matrix
1693 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1695 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1696 Matrix invertedMvp( false/*don't init*/);
1697 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1698 bool success = invertedMvp.Invert();
1700 // Convert to GL coordinates
1701 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1706 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1713 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1719 if( XyPlaneIntersect( nearPos, farPos, local ) )
1721 Vector3 size = GetCurrentSize();
1722 localX = local.x + size.x * 0.5f;
1723 localY = local.y + size.y * 0.5f;
1734 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1737 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1739 Mathematical Formulation
1741 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1743 ( p - c ) dot ( p - c ) = r^2
1745 Given a ray with a point of origin 'o', and a direction vector 'd':
1747 ray(t) = o + td, t >= 0
1749 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1751 (o + td - c ) dot ( o + td - c ) = r^2
1753 To solve for t we first expand the above into a more recognisable quadratic equation form
1755 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1764 B = 2( o - c ) dot d
1765 C = ( o - c ) dot ( o - c ) - r^2
1767 which can be solved using a standard quadratic formula.
1769 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1771 Practical Simplification
1773 In a renderer, we often differentiate between world space and object space. In the object space
1774 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1775 into object space, the mathematical solution presented above can be simplified significantly.
1777 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1781 and we can find the t at which the (transformed) ray intersects the sphere by
1783 ( o + td ) dot ( o + td ) = r^2
1785 According to the reasoning above, we expand the above quadratic equation into the general form
1789 which now has coefficients:
1796 // Early out if mNode is NULL
1802 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1804 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1805 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1806 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1808 // Compute the radius is not needed, square radius it's enough.
1809 const Vector3& size( mNode->GetSize( bufferIndex ) );
1811 // Scale the sphere.
1812 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1814 const float width = size.width * scale.width;
1815 const float height = size.height * scale.height;
1817 float squareSphereRadius = 0.5f * ( width * width + height * height );
1819 float a = rayDir.Dot( rayDir ); // a
1820 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1821 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1823 return ( b2 * b2 - a * c ) >= 0.f;
1826 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1830 if( OnStage() && NULL != mNode )
1832 // Transforms the ray to the local reference system.
1833 // Calculate the inverse of Model matrix
1834 Matrix invModelMatrix( false/*don't init*/);
1836 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1837 invModelMatrix = mNode->GetWorldMatrix(0);
1838 invModelMatrix.Invert();
1840 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1841 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1843 // Test with the actor's XY plane (Normal = 0 0 1 1).
1845 float a = -rayOriginLocal.z;
1846 float b = rayDirLocal.z;
1848 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1850 // Ray travels distance * rayDirLocal to intersect with plane.
1853 const Vector3& size = mNode->GetSize( bufferIndex );
1855 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1856 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1858 // Test with the actor's geometry.
1859 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1866 void Actor::SetLeaveRequired( bool required )
1868 mLeaveRequired = required;
1871 bool Actor::GetLeaveRequired() const
1873 return mLeaveRequired;
1876 void Actor::SetKeyboardFocusable( bool focusable )
1878 mKeyboardFocusable = focusable;
1881 bool Actor::IsKeyboardFocusable() const
1883 return mKeyboardFocusable;
1886 bool Actor::GetTouchRequired() const
1888 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1891 bool Actor::GetHoverRequired() const
1893 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1896 bool Actor::GetWheelEventRequired() const
1898 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1901 bool Actor::IsHittable() const
1903 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1906 ActorGestureData& Actor::GetGestureData()
1908 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1909 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1910 if( NULL == mGestureData )
1912 mGestureData = new ActorGestureData;
1914 return *mGestureData;
1917 bool Actor::IsGestureRequred( Gesture::Type type ) const
1919 return mGestureData && mGestureData->IsGestureRequred( type );
1922 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1924 bool consumed = false;
1926 if( !mTouchSignal.Empty() )
1928 Dali::Actor handle( this );
1929 consumed = mTouchSignal.Emit( handle, touch );
1932 if( !mTouchedSignal.Empty() )
1934 Dali::Actor handle( this );
1935 consumed |= mTouchedSignal.Emit( handle, event );
1940 // Notification for derived classes
1941 consumed = OnTouchEvent( event ); // TODO
1947 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1949 bool consumed = false;
1951 if( !mHoveredSignal.Empty() )
1953 Dali::Actor handle( this );
1954 consumed = mHoveredSignal.Emit( handle, event );
1959 // Notification for derived classes
1960 consumed = OnHoverEvent( event );
1966 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1968 bool consumed = false;
1970 if( !mWheelEventSignal.Empty() )
1972 Dali::Actor handle( this );
1973 consumed = mWheelEventSignal.Emit( handle, event );
1978 // Notification for derived classes
1979 consumed = OnWheelEvent( event );
1985 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1987 return mTouchedSignal;
1990 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1992 return mTouchSignal;
1995 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1997 return mHoveredSignal;
2000 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2002 return mWheelEventSignal;
2005 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2007 return mOnStageSignal;
2010 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2012 return mOffStageSignal;
2015 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2017 return mOnRelayoutSignal;
2020 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2022 bool connected( true );
2023 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2025 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2027 actor->TouchedSignal().Connect( tracker, functor );
2029 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2031 actor->HoveredSignal().Connect( tracker, functor );
2033 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2035 actor->WheelEventSignal().Connect( tracker, functor );
2037 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2039 actor->OnStageSignal().Connect( tracker, functor );
2041 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2043 actor->OffStageSignal().Connect( tracker, functor );
2045 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2047 actor->OnRelayoutSignal().Connect( tracker, functor );
2049 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2051 actor->TouchSignal().Connect( tracker, functor );
2055 // signalName does not match any signal
2062 Actor::Actor( DerivedType derivedType )
2067 mParentOrigin( NULL ),
2068 mAnchorPoint( NULL ),
2069 mRelayoutData( NULL ),
2070 mGestureData( NULL ),
2071 mTargetSize( 0.0f, 0.0f, 0.0f ),
2073 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2076 mIsRoot( ROOT_LAYER == derivedType ),
2077 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2078 mIsOnStage( false ),
2080 mLeaveRequired( false ),
2081 mKeyboardFocusable( false ),
2082 mDerivedRequiresTouch( false ),
2083 mDerivedRequiresHover( false ),
2084 mDerivedRequiresWheelEvent( false ),
2085 mOnStageSignalled( false ),
2086 mInsideOnSizeSet( false ),
2087 mInheritPosition( true ),
2088 mInheritOrientation( true ),
2089 mInheritScale( true ),
2090 mPositionUsesAnchorPoint( true ),
2091 mDrawMode( DrawMode::NORMAL ),
2092 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2093 mColorMode( Node::DEFAULT_COLOR_MODE ),
2094 mClippingMode( ClippingMode::DISABLED )
2098 void Actor::Initialize()
2101 SceneGraph::Node* node = CreateNode();
2103 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2104 mNode = node; // Keep raw-pointer to Node
2108 GetEventThreadServices().RegisterObject( this );
2113 // Remove mParent pointers from children even if we're destroying core,
2114 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2117 ActorConstIter endIter = mChildren->end();
2118 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2120 (*iter)->SetParent( NULL );
2126 // Guard to allow handle destruction after Core has been destroyed
2127 if( EventThreadServices::IsCoreRunning() )
2131 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2132 mNode = NULL; // Node is about to be destroyed
2135 GetEventThreadServices().UnregisterObject( this );
2138 // Cleanup optional gesture data
2139 delete mGestureData;
2141 // Cleanup optional parent origin and anchor
2142 delete mParentOrigin;
2143 delete mAnchorPoint;
2145 // Delete optional relayout data
2148 delete mRelayoutData;
2152 void Actor::ConnectToStage( unsigned int parentDepth )
2154 // This container is used instead of walking the Actor hierarchy.
2155 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2156 ActorContainer connectionList;
2158 // This stage is atomic i.e. not interrupted by user callbacks.
2159 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2161 // Notify applications about the newly connected actors.
2162 const ActorIter endIter = connectionList.end();
2163 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2165 (*iter)->NotifyStageConnection();
2171 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2173 DALI_ASSERT_ALWAYS( !OnStage() );
2177 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2179 ConnectToSceneGraph();
2181 // Notification for internal derived classes
2182 OnStageConnectionInternal();
2184 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2185 connectionList.push_back( ActorPtr( this ) );
2187 // Recursively connect children
2190 ActorConstIter endIter = mChildren->end();
2191 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2193 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2199 * This method is called when the Actor is connected to the Stage.
2200 * The parent must have added its Node to the scene-graph.
2201 * The child must connect its Node to the parent's Node.
2202 * This is recursive; the child calls ConnectToStage() for its children.
2204 void Actor::ConnectToSceneGraph()
2206 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2210 // Reparent Node in next Update
2211 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2214 // Request relayout on all actors that are added to the scenegraph
2217 // Notification for Object::Observers
2221 void Actor::NotifyStageConnection()
2223 // Actors can be removed (in a callback), before the on-stage stage is reported.
2224 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2225 if( OnStage() && !mOnStageSignalled )
2227 // Notification for external (CustomActor) derived classes
2228 OnStageConnectionExternal( mDepth );
2230 if( !mOnStageSignal.Empty() )
2232 Dali::Actor handle( this );
2233 mOnStageSignal.Emit( handle );
2236 // Guard against Remove during callbacks
2239 mOnStageSignalled = true; // signal required next time Actor is removed
2244 void Actor::DisconnectFromStage()
2246 // This container is used instead of walking the Actor hierachy.
2247 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2248 ActorContainer disconnectionList;
2250 // This stage is atomic i.e. not interrupted by user callbacks
2251 RecursiveDisconnectFromStage( disconnectionList );
2253 // Notify applications about the newly disconnected actors.
2254 const ActorIter endIter = disconnectionList.end();
2255 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2257 (*iter)->NotifyStageDisconnection();
2261 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2263 DALI_ASSERT_ALWAYS( OnStage() );
2265 // Recursively disconnect children
2268 ActorConstIter endIter = mChildren->end();
2269 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2271 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2275 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2276 disconnectionList.push_back( ActorPtr( this ) );
2278 // Notification for internal derived classes
2279 OnStageDisconnectionInternal();
2281 DisconnectFromSceneGraph();
2287 * This method is called by an actor or its parent, before a node removal message is sent.
2288 * This is recursive; the child calls DisconnectFromStage() for its children.
2290 void Actor::DisconnectFromSceneGraph()
2292 // Notification for Object::Observers
2293 OnSceneObjectRemove();
2296 void Actor::NotifyStageDisconnection()
2298 // Actors can be added (in a callback), before the off-stage state is reported.
2299 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2300 // only do this step if there is a stage, i.e. Core is not being shut down
2301 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2303 // Notification for external (CustomeActor) derived classes
2304 OnStageDisconnectionExternal();
2306 if( !mOffStageSignal.Empty() )
2308 Dali::Actor handle( this );
2309 mOffStageSignal.Emit( handle );
2312 // Guard against Add during callbacks
2315 mOnStageSignalled = false; // signal required next time Actor is added
2320 bool Actor::IsNodeConnected() const
2322 bool connected( false );
2324 if( OnStage() && ( NULL != mNode ) )
2326 if( IsRoot() || mNode->GetParent() )
2335 unsigned int Actor::GetDefaultPropertyCount() const
2337 return DEFAULT_PROPERTY_COUNT;
2340 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2342 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2344 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2346 indices.PushBack( i );
2350 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2352 if( index < DEFAULT_PROPERTY_COUNT )
2354 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2360 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2362 Property::Index index = Property::INVALID_INDEX;
2364 // Look for name in default properties
2365 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2367 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2368 if( 0 == name.compare( property->name ) )
2378 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2380 if( index < DEFAULT_PROPERTY_COUNT )
2382 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2388 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2390 if( index < DEFAULT_PROPERTY_COUNT )
2392 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2398 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2400 if( index < DEFAULT_PROPERTY_COUNT )
2402 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2408 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2410 if( index < DEFAULT_PROPERTY_COUNT )
2412 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2415 // index out of range...return Property::NONE
2416 return Property::NONE;
2419 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2423 case Dali::Actor::Property::PARENT_ORIGIN:
2425 Property::Type type = property.GetType();
2426 if( type == Property::VECTOR3 )
2428 SetParentOrigin( property.Get< Vector3 >() );
2430 else if ( type == Property::STRING )
2432 std::string parentOriginString;
2433 property.Get( parentOriginString );
2434 Vector3 parentOrigin;
2435 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2437 SetParentOrigin( parentOrigin );
2443 case Dali::Actor::Property::PARENT_ORIGIN_X:
2445 SetParentOriginX( property.Get< float >() );
2449 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2451 SetParentOriginY( property.Get< float >() );
2455 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2457 SetParentOriginZ( property.Get< float >() );
2461 case Dali::Actor::Property::ANCHOR_POINT:
2463 Property::Type type = property.GetType();
2464 if( type == Property::VECTOR3 )
2466 SetAnchorPoint( property.Get< Vector3 >() );
2468 else if ( type == Property::STRING )
2470 std::string anchorPointString;
2471 property.Get( anchorPointString );
2473 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2475 SetAnchorPoint( anchor );
2481 case Dali::Actor::Property::ANCHOR_POINT_X:
2483 SetAnchorPointX( property.Get< float >() );
2487 case Dali::Actor::Property::ANCHOR_POINT_Y:
2489 SetAnchorPointY( property.Get< float >() );
2493 case Dali::Actor::Property::ANCHOR_POINT_Z:
2495 SetAnchorPointZ( property.Get< float >() );
2499 case Dali::Actor::Property::SIZE:
2501 SetSize( property.Get< Vector3 >() );
2505 case Dali::Actor::Property::SIZE_WIDTH:
2507 SetWidth( property.Get< float >() );
2511 case Dali::Actor::Property::SIZE_HEIGHT:
2513 SetHeight( property.Get< float >() );
2517 case Dali::Actor::Property::SIZE_DEPTH:
2519 SetDepth( property.Get< float >() );
2523 case Dali::Actor::Property::POSITION:
2525 SetPosition( property.Get< Vector3 >() );
2529 case Dali::Actor::Property::POSITION_X:
2531 SetX( property.Get< float >() );
2535 case Dali::Actor::Property::POSITION_Y:
2537 SetY( property.Get< float >() );
2541 case Dali::Actor::Property::POSITION_Z:
2543 SetZ( property.Get< float >() );
2547 case Dali::Actor::Property::ORIENTATION:
2549 SetOrientation( property.Get< Quaternion >() );
2553 case Dali::Actor::Property::SCALE:
2555 SetScale( property.Get< Vector3 >() );
2559 case Dali::Actor::Property::SCALE_X:
2561 SetScaleX( property.Get< float >() );
2565 case Dali::Actor::Property::SCALE_Y:
2567 SetScaleY( property.Get< float >() );
2571 case Dali::Actor::Property::SCALE_Z:
2573 SetScaleZ( property.Get< float >() );
2577 case Dali::Actor::Property::VISIBLE:
2579 SetVisible( property.Get< bool >() );
2583 case Dali::Actor::Property::COLOR:
2585 SetColor( property.Get< Vector4 >() );
2589 case Dali::Actor::Property::COLOR_RED:
2591 SetColorRed( property.Get< float >() );
2595 case Dali::Actor::Property::COLOR_GREEN:
2597 SetColorGreen( property.Get< float >() );
2601 case Dali::Actor::Property::COLOR_BLUE:
2603 SetColorBlue( property.Get< float >() );
2607 case Dali::Actor::Property::COLOR_ALPHA:
2608 case Dali::DevelActor::Property::OPACITY:
2611 if( property.Get( value ) )
2613 SetOpacity( value );
2618 case Dali::Actor::Property::NAME:
2620 SetName( property.Get< std::string >() );
2624 case Dali::Actor::Property::SENSITIVE:
2626 SetSensitive( property.Get< bool >() );
2630 case Dali::Actor::Property::LEAVE_REQUIRED:
2632 SetLeaveRequired( property.Get< bool >() );
2636 case Dali::Actor::Property::INHERIT_POSITION:
2638 SetInheritPosition( property.Get< bool >() );
2642 case Dali::Actor::Property::INHERIT_ORIENTATION:
2644 SetInheritOrientation( property.Get< bool >() );
2648 case Dali::Actor::Property::INHERIT_SCALE:
2650 SetInheritScale( property.Get< bool >() );
2654 case Dali::Actor::Property::COLOR_MODE:
2656 ColorMode mode = mColorMode;
2657 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2659 SetColorMode( mode );
2664 case Dali::Actor::Property::POSITION_INHERITANCE:
2666 PositionInheritanceMode mode = mPositionInheritanceMode;
2667 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2669 SetPositionInheritanceMode( mode );
2674 case Dali::Actor::Property::DRAW_MODE:
2676 DrawMode::Type mode = mDrawMode;
2677 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2679 SetDrawMode( mode );
2684 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2686 SetSizeModeFactor( property.Get< Vector3 >() );
2690 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2692 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2693 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2695 SetResizePolicy( type, Dimension::WIDTH );
2700 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2702 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2703 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2705 SetResizePolicy( type, Dimension::HEIGHT );
2710 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2712 SizeScalePolicy::Type type;
2713 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2715 SetSizeScalePolicy( type );
2720 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2722 if( property.Get< bool >() )
2724 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2729 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2731 if( property.Get< bool >() )
2733 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2738 case Dali::Actor::Property::PADDING:
2740 Vector4 padding = property.Get< Vector4 >();
2741 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2742 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2746 case Dali::Actor::Property::MINIMUM_SIZE:
2748 Vector2 size = property.Get< Vector2 >();
2749 SetMinimumSize( size.x, Dimension::WIDTH );
2750 SetMinimumSize( size.y, Dimension::HEIGHT );
2754 case Dali::Actor::Property::MAXIMUM_SIZE:
2756 Vector2 size = property.Get< Vector2 >();
2757 SetMaximumSize( size.x, Dimension::WIDTH );
2758 SetMaximumSize( size.y, Dimension::HEIGHT );
2762 case Dali::DevelActor::Property::SIBLING_ORDER:
2766 if( property.Get( value ) )
2768 if( static_cast<unsigned int>(value) != mSiblingOrder )
2770 SetSiblingOrder( value );
2776 case Dali::Actor::Property::CLIPPING_MODE:
2778 ClippingMode::Type convertedValue = mClippingMode;
2779 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2781 mClippingMode = convertedValue;
2784 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2790 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2793 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2795 mPositionUsesAnchorPoint = value;
2798 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2806 // this can happen in the case of a non-animatable default property so just do nothing
2812 // TODO: This method needs to be removed
2813 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2815 switch( entry.GetType() )
2817 case Property::BOOLEAN:
2819 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2820 DALI_ASSERT_DEBUG( NULL != property );
2822 // property is being used in a separate thread; queue a message to set the property
2823 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2828 case Property::INTEGER:
2830 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2831 DALI_ASSERT_DEBUG( NULL != property );
2833 // property is being used in a separate thread; queue a message to set the property
2834 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2839 case Property::FLOAT:
2841 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2842 DALI_ASSERT_DEBUG( NULL != property );
2844 // property is being used in a separate thread; queue a message to set the property
2845 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2850 case Property::VECTOR2:
2852 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2853 DALI_ASSERT_DEBUG( NULL != property );
2855 // property is being used in a separate thread; queue a message to set the property
2856 if(entry.componentIndex == 0)
2858 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2860 else if(entry.componentIndex == 1)
2862 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2866 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2872 case Property::VECTOR3:
2874 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2875 DALI_ASSERT_DEBUG( NULL != property );
2877 // property is being used in a separate thread; queue a message to set the property
2878 if(entry.componentIndex == 0)
2880 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2882 else if(entry.componentIndex == 1)
2884 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2886 else if(entry.componentIndex == 2)
2888 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2892 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2898 case Property::VECTOR4:
2900 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2901 DALI_ASSERT_DEBUG( NULL != property );
2903 // property is being used in a separate thread; queue a message to set the property
2904 if(entry.componentIndex == 0)
2906 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2908 else if(entry.componentIndex == 1)
2910 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2912 else if(entry.componentIndex == 2)
2914 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2916 else if(entry.componentIndex == 3)
2918 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2922 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2928 case Property::ROTATION:
2930 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2931 DALI_ASSERT_DEBUG( NULL != property );
2933 // property is being used in a separate thread; queue a message to set the property
2934 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2939 case Property::MATRIX:
2941 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2942 DALI_ASSERT_DEBUG( NULL != property );
2944 // property is being used in a separate thread; queue a message to set the property
2945 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2950 case Property::MATRIX3:
2952 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2953 DALI_ASSERT_DEBUG( NULL != property );
2955 // property is being used in a separate thread; queue a message to set the property
2956 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2963 // nothing to do for other types
2968 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2970 Property::Value value;
2972 if( index >= DEFAULT_PROPERTY_COUNT )
2979 case Dali::Actor::Property::PARENT_ORIGIN:
2981 value = GetCurrentParentOrigin();
2985 case Dali::Actor::Property::PARENT_ORIGIN_X:
2987 value = GetCurrentParentOrigin().x;
2991 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2993 value = GetCurrentParentOrigin().y;
2997 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2999 value = GetCurrentParentOrigin().z;
3003 case Dali::Actor::Property::ANCHOR_POINT:
3005 value = GetCurrentAnchorPoint();
3009 case Dali::Actor::Property::ANCHOR_POINT_X:
3011 value = GetCurrentAnchorPoint().x;
3015 case Dali::Actor::Property::ANCHOR_POINT_Y:
3017 value = GetCurrentAnchorPoint().y;
3021 case Dali::Actor::Property::ANCHOR_POINT_Z:
3023 value = GetCurrentAnchorPoint().z;
3027 case Dali::Actor::Property::SIZE:
3029 Vector3 size = GetTargetSize();
3031 // Should return preferred size if size is fixed as set by SetSize
3032 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3034 size.width = GetPreferredSize().width;
3036 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3038 size.height = GetPreferredSize().height;
3046 case Dali::Actor::Property::SIZE_WIDTH:
3048 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3050 // Should return preferred size if size is fixed as set by SetSize
3051 value = GetPreferredSize().width;
3055 value = GetTargetSize().width;
3060 case Dali::Actor::Property::SIZE_HEIGHT:
3062 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3064 // Should return preferred size if size is fixed as set by SetSize
3065 value = GetPreferredSize().height;
3069 value = GetTargetSize().height;
3074 case Dali::Actor::Property::SIZE_DEPTH:
3076 value = GetTargetSize().depth;
3080 case Dali::Actor::Property::POSITION:
3082 value = GetTargetPosition();
3086 case Dali::Actor::Property::POSITION_X:
3088 value = GetTargetPosition().x;
3092 case Dali::Actor::Property::POSITION_Y:
3094 value = GetTargetPosition().y;
3098 case Dali::Actor::Property::POSITION_Z:
3100 value = GetTargetPosition().z;
3104 case Dali::Actor::Property::WORLD_POSITION:
3106 value = GetCurrentWorldPosition();
3110 case Dali::Actor::Property::WORLD_POSITION_X:
3112 value = GetCurrentWorldPosition().x;
3116 case Dali::Actor::Property::WORLD_POSITION_Y:
3118 value = GetCurrentWorldPosition().y;
3122 case Dali::Actor::Property::WORLD_POSITION_Z:
3124 value = GetCurrentWorldPosition().z;
3128 case Dali::Actor::Property::ORIENTATION:
3130 value = GetCurrentOrientation();
3134 case Dali::Actor::Property::WORLD_ORIENTATION:
3136 value = GetCurrentWorldOrientation();
3140 case Dali::Actor::Property::SCALE:
3142 value = GetCurrentScale();
3146 case Dali::Actor::Property::SCALE_X:
3148 value = GetCurrentScale().x;
3152 case Dali::Actor::Property::SCALE_Y:
3154 value = GetCurrentScale().y;
3158 case Dali::Actor::Property::SCALE_Z:
3160 value = GetCurrentScale().z;
3164 case Dali::Actor::Property::WORLD_SCALE:
3166 value = GetCurrentWorldScale();
3170 case Dali::Actor::Property::VISIBLE:
3172 value = IsVisible();
3176 case Dali::Actor::Property::COLOR:
3178 value = GetCurrentColor();
3182 case Dali::Actor::Property::COLOR_RED:
3184 value = GetCurrentColor().r;
3188 case Dali::Actor::Property::COLOR_GREEN:
3190 value = GetCurrentColor().g;
3194 case Dali::Actor::Property::COLOR_BLUE:
3196 value = GetCurrentColor().b;
3200 case Dali::Actor::Property::COLOR_ALPHA:
3201 case Dali::DevelActor::Property::OPACITY:
3203 value = GetCurrentColor().a;
3207 case Dali::Actor::Property::WORLD_COLOR:
3209 value = GetCurrentWorldColor();
3213 case Dali::Actor::Property::WORLD_MATRIX:
3215 value = GetCurrentWorldMatrix();
3219 case Dali::Actor::Property::NAME:
3225 case Dali::Actor::Property::SENSITIVE:
3227 value = IsSensitive();
3231 case Dali::Actor::Property::LEAVE_REQUIRED:
3233 value = GetLeaveRequired();
3237 case Dali::Actor::Property::INHERIT_POSITION:
3239 value = IsPositionInherited();
3243 case Dali::Actor::Property::INHERIT_ORIENTATION:
3245 value = IsOrientationInherited();
3249 case Dali::Actor::Property::INHERIT_SCALE:
3251 value = IsScaleInherited();
3255 case Dali::Actor::Property::COLOR_MODE:
3257 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3261 case Dali::Actor::Property::POSITION_INHERITANCE:
3263 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3267 case Dali::Actor::Property::DRAW_MODE:
3269 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3273 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3275 value = GetSizeModeFactor();
3279 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3281 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3285 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3287 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3291 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3293 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3297 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3299 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3303 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3305 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3309 case Dali::Actor::Property::PADDING:
3311 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3312 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3313 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3317 case Dali::Actor::Property::MINIMUM_SIZE:
3319 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3323 case Dali::Actor::Property::MAXIMUM_SIZE:
3325 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3329 case Dali::DevelActor::Property::SIBLING_ORDER:
3331 value = static_cast<int>(mSiblingOrder);
3335 case Dali::Actor::Property::CLIPPING_MODE:
3337 value = mClippingMode;
3341 case Dali::DevelActor::Property::SCREEN_POSITION:
3343 value = GetCurrentScreenPosition();
3347 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3349 value = mPositionUsesAnchorPoint;
3357 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3362 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3364 // This method should only return an object connected to the scene-graph
3365 return OnStage() ? mNode : NULL;
3368 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3370 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3372 const PropertyBase* property( NULL );
3374 // This method should only return a property of an object connected to the scene-graph
3380 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3382 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3383 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3385 property = animatable->GetSceneGraphProperty();
3387 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3388 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3390 CustomPropertyMetadata* custom = FindCustomProperty( index );
3391 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3393 property = custom->GetSceneGraphProperty();
3395 else if( NULL != mNode )
3399 case Dali::Actor::Property::SIZE:
3400 property = &mNode->mSize;
3403 case Dali::Actor::Property::SIZE_WIDTH:
3404 property = &mNode->mSize;
3407 case Dali::Actor::Property::SIZE_HEIGHT:
3408 property = &mNode->mSize;
3411 case Dali::Actor::Property::SIZE_DEPTH:
3412 property = &mNode->mSize;
3415 case Dali::Actor::Property::POSITION:
3416 property = &mNode->mPosition;
3419 case Dali::Actor::Property::POSITION_X:
3420 property = &mNode->mPosition;
3423 case Dali::Actor::Property::POSITION_Y:
3424 property = &mNode->mPosition;
3427 case Dali::Actor::Property::POSITION_Z:
3428 property = &mNode->mPosition;
3431 case Dali::Actor::Property::ORIENTATION:
3432 property = &mNode->mOrientation;
3435 case Dali::Actor::Property::SCALE:
3436 property = &mNode->mScale;
3439 case Dali::Actor::Property::SCALE_X:
3440 property = &mNode->mScale;
3443 case Dali::Actor::Property::SCALE_Y:
3444 property = &mNode->mScale;
3447 case Dali::Actor::Property::SCALE_Z:
3448 property = &mNode->mScale;
3451 case Dali::Actor::Property::VISIBLE:
3452 property = &mNode->mVisible;
3455 case Dali::Actor::Property::COLOR:
3456 property = &mNode->mColor;
3459 case Dali::Actor::Property::COLOR_RED:
3460 property = &mNode->mColor;
3463 case Dali::Actor::Property::COLOR_GREEN:
3464 property = &mNode->mColor;
3467 case Dali::Actor::Property::COLOR_BLUE:
3468 property = &mNode->mColor;
3471 case Dali::Actor::Property::COLOR_ALPHA:
3472 case Dali::DevelActor::Property::OPACITY:
3473 property = &mNode->mColor;
3484 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3486 const PropertyInputImpl* property( NULL );
3488 // This method should only return a property of an object connected to the scene-graph
3494 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3496 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3497 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3499 property = animatable->GetSceneGraphProperty();
3501 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3502 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3504 CustomPropertyMetadata* custom = FindCustomProperty( index );
3505 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3506 property = custom->GetSceneGraphProperty();
3508 else if( NULL != mNode )
3512 case Dali::Actor::Property::PARENT_ORIGIN:
3513 property = &mNode->mParentOrigin;
3516 case Dali::Actor::Property::PARENT_ORIGIN_X:
3517 property = &mNode->mParentOrigin;
3520 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3521 property = &mNode->mParentOrigin;
3524 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3525 property = &mNode->mParentOrigin;
3528 case Dali::Actor::Property::ANCHOR_POINT:
3529 property = &mNode->mAnchorPoint;
3532 case Dali::Actor::Property::ANCHOR_POINT_X:
3533 property = &mNode->mAnchorPoint;
3536 case Dali::Actor::Property::ANCHOR_POINT_Y:
3537 property = &mNode->mAnchorPoint;
3540 case Dali::Actor::Property::ANCHOR_POINT_Z:
3541 property = &mNode->mAnchorPoint;
3544 case Dali::Actor::Property::SIZE:
3545 property = &mNode->mSize;
3548 case Dali::Actor::Property::SIZE_WIDTH:
3549 property = &mNode->mSize;
3552 case Dali::Actor::Property::SIZE_HEIGHT:
3553 property = &mNode->mSize;
3556 case Dali::Actor::Property::SIZE_DEPTH:
3557 property = &mNode->mSize;
3560 case Dali::Actor::Property::POSITION:
3561 property = &mNode->mPosition;
3564 case Dali::Actor::Property::POSITION_X:
3565 property = &mNode->mPosition;
3568 case Dali::Actor::Property::POSITION_Y:
3569 property = &mNode->mPosition;
3572 case Dali::Actor::Property::POSITION_Z:
3573 property = &mNode->mPosition;
3576 case Dali::Actor::Property::WORLD_POSITION:
3577 property = &mNode->mWorldPosition;
3580 case Dali::Actor::Property::WORLD_POSITION_X:
3581 property = &mNode->mWorldPosition;
3584 case Dali::Actor::Property::WORLD_POSITION_Y:
3585 property = &mNode->mWorldPosition;
3588 case Dali::Actor::Property::WORLD_POSITION_Z:
3589 property = &mNode->mWorldPosition;
3592 case Dali::Actor::Property::ORIENTATION:
3593 property = &mNode->mOrientation;
3596 case Dali::Actor::Property::WORLD_ORIENTATION:
3597 property = &mNode->mWorldOrientation;
3600 case Dali::Actor::Property::SCALE:
3601 property = &mNode->mScale;
3604 case Dali::Actor::Property::SCALE_X:
3605 property = &mNode->mScale;
3608 case Dali::Actor::Property::SCALE_Y:
3609 property = &mNode->mScale;
3612 case Dali::Actor::Property::SCALE_Z:
3613 property = &mNode->mScale;
3616 case Dali::Actor::Property::WORLD_SCALE:
3617 property = &mNode->mWorldScale;
3620 case Dali::Actor::Property::VISIBLE:
3621 property = &mNode->mVisible;
3624 case Dali::Actor::Property::COLOR:
3625 property = &mNode->mColor;
3628 case Dali::Actor::Property::COLOR_RED:
3629 property = &mNode->mColor;
3632 case Dali::Actor::Property::COLOR_GREEN:
3633 property = &mNode->mColor;
3636 case Dali::Actor::Property::COLOR_BLUE:
3637 property = &mNode->mColor;
3640 case Dali::Actor::Property::COLOR_ALPHA:
3641 case Dali::DevelActor::Property::OPACITY:
3643 property = &mNode->mColor;
3647 case Dali::Actor::Property::WORLD_COLOR:
3648 property = &mNode->mWorldColor;
3651 case Dali::Actor::Property::WORLD_MATRIX:
3652 property = &mNode->mWorldMatrix;
3663 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3665 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3667 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3669 // check whether the animatable property is registered already, if not then register one.
3670 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3671 if( animatableProperty )
3673 componentIndex = animatableProperty->componentIndex;
3680 case Dali::Actor::Property::PARENT_ORIGIN_X:
3681 case Dali::Actor::Property::ANCHOR_POINT_X:
3682 case Dali::Actor::Property::SIZE_WIDTH:
3683 case Dali::Actor::Property::POSITION_X:
3684 case Dali::Actor::Property::WORLD_POSITION_X:
3685 case Dali::Actor::Property::SCALE_X:
3686 case Dali::Actor::Property::COLOR_RED:
3692 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3693 case Dali::Actor::Property::ANCHOR_POINT_Y:
3694 case Dali::Actor::Property::SIZE_HEIGHT:
3695 case Dali::Actor::Property::POSITION_Y:
3696 case Dali::Actor::Property::WORLD_POSITION_Y:
3697 case Dali::Actor::Property::SCALE_Y:
3698 case Dali::Actor::Property::COLOR_GREEN:
3704 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3705 case Dali::Actor::Property::ANCHOR_POINT_Z:
3706 case Dali::Actor::Property::SIZE_DEPTH:
3707 case Dali::Actor::Property::POSITION_Z:
3708 case Dali::Actor::Property::WORLD_POSITION_Z:
3709 case Dali::Actor::Property::SCALE_Z:
3710 case Dali::Actor::Property::COLOR_BLUE:
3716 case Dali::Actor::Property::COLOR_ALPHA:
3717 case Dali::DevelActor::Property::OPACITY:
3731 return componentIndex;
3734 void Actor::SetParent( Actor* parent )
3738 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3742 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3745 // Instruct each actor to create a corresponding node in the scene graph
3746 ConnectToStage( parent->GetHierarchyDepth() );
3749 // Resolve the name and index for the child properties if any
3750 ResolveChildProperties();
3752 else // parent being set to NULL
3754 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3758 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3761 DALI_ASSERT_ALWAYS( mNode != NULL );
3765 // Disconnect the Node & its children from the scene-graph.
3766 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3769 // Instruct each actor to discard pointers to the scene-graph
3770 DisconnectFromStage();
3775 SceneGraph::Node* Actor::CreateNode() const
3780 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3783 Actor* actor = dynamic_cast< Actor* >( object );
3787 if( 0 == actionName.compare( ACTION_SHOW ) )
3789 actor->SetVisible( true );
3792 else if( 0 == actionName.compare( ACTION_HIDE ) )
3794 actor->SetVisible( false );
3802 void Actor::EnsureRelayoutData()
3804 // Assign relayout data.
3805 if( !mRelayoutData )
3807 mRelayoutData = new RelayoutData();
3811 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3813 // Check if actor is dependent on parent
3814 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3816 if( ( dimension & ( 1 << i ) ) )
3818 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3819 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3829 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3831 // Check if actor is dependent on children
3832 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3834 if( ( dimension & ( 1 << i ) ) )
3836 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3837 switch( resizePolicy )
3839 case ResizePolicy::FIT_TO_CHILDREN:
3840 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3856 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3858 return Actor::RelayoutDependentOnChildren( dimension );
3861 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3863 // Check each possible dimension and see if it is dependent on the input one
3864 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3866 if( dimension & ( 1 << i ) )
3868 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3875 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3877 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3879 if( dimension & ( 1 << i ) )
3881 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3886 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3888 // If more than one dimension is requested, just return the first one found
3889 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3891 if( ( dimension & ( 1 << i ) ) )
3893 return mRelayoutData->negotiatedDimensions[ i ];
3897 return 0.0f; // Default
3900 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3902 EnsureRelayoutData();
3904 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3906 if( dimension & ( 1 << i ) )
3908 mRelayoutData->dimensionPadding[ i ] = padding;
3913 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3915 if ( mRelayoutData )
3917 // If more than one dimension is requested, just return the first one found
3918 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3920 if( ( dimension & ( 1 << i ) ) )
3922 return mRelayoutData->dimensionPadding[ i ];
3927 return GetDefaultDimensionPadding();
3930 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3932 EnsureRelayoutData();
3934 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3936 if( dimension & ( 1 << i ) )
3938 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3943 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3945 if ( mRelayoutData )
3947 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3949 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3959 float Actor::GetHeightForWidthBase( float width )
3961 float height = 0.0f;
3963 const Vector3 naturalSize = GetNaturalSize();
3964 if( naturalSize.width > 0.0f )
3966 height = naturalSize.height * width / naturalSize.width;
3968 else // we treat 0 as 1:1 aspect ratio
3976 float Actor::GetWidthForHeightBase( float height )
3980 const Vector3 naturalSize = GetNaturalSize();
3981 if( naturalSize.height > 0.0f )
3983 width = naturalSize.width * height / naturalSize.height;
3985 else // we treat 0 as 1:1 aspect ratio
3993 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3995 // Fill to parent, taking size mode factor into account
3996 switch( child.GetResizePolicy( dimension ) )
3998 case ResizePolicy::FILL_TO_PARENT:
4000 return GetLatestSize( dimension );
4003 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4005 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4008 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4010 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4015 return GetLatestSize( dimension );
4020 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4022 // Can be overridden in derived class
4023 return CalculateChildSizeBase( child, dimension );
4026 float Actor::GetHeightForWidth( float width )
4028 // Can be overridden in derived class
4029 return GetHeightForWidthBase( width );
4032 float Actor::GetWidthForHeight( float height )
4034 // Can be overridden in derived class
4035 return GetWidthForHeightBase( height );
4038 float Actor::GetLatestSize( Dimension::Type dimension ) const
4040 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4043 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4045 Vector2 padding = GetPadding( dimension );
4047 return GetLatestSize( dimension ) + padding.x + padding.y;
4050 float Actor::NegotiateFromParent( Dimension::Type dimension )
4052 Actor* parent = GetParent();
4055 Vector2 padding( GetPadding( dimension ) );
4056 Vector2 parentPadding( parent->GetPadding( dimension ) );
4057 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4063 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4065 float maxDimensionPoint = 0.0f;
4067 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4069 ActorPtr child = GetChildAt( i );
4071 if( !child->RelayoutDependentOnParent( dimension ) )
4073 // Calculate the min and max points that the children range across
4074 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4075 float dimensionSize = child->GetRelayoutSize( dimension );
4076 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4080 return maxDimensionPoint;
4083 float Actor::GetSize( Dimension::Type dimension ) const
4085 return GetDimensionValue( GetTargetSize(), dimension );
4088 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4090 return GetDimensionValue( GetNaturalSize(), dimension );
4093 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4095 switch( GetResizePolicy( dimension ) )
4097 case ResizePolicy::USE_NATURAL_SIZE:
4099 return GetNaturalSize( dimension );
4102 case ResizePolicy::FIXED:
4104 return GetDimensionValue( GetPreferredSize(), dimension );
4107 case ResizePolicy::USE_ASSIGNED_SIZE:
4109 return GetDimensionValue( maximumSize, dimension );
4112 case ResizePolicy::FILL_TO_PARENT:
4113 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4114 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4116 return NegotiateFromParent( dimension );
4119 case ResizePolicy::FIT_TO_CHILDREN:
4121 return NegotiateFromChildren( dimension );
4124 case ResizePolicy::DIMENSION_DEPENDENCY:
4126 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4129 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4131 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4134 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4136 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4148 return 0.0f; // Default
4151 float Actor::ClampDimension( float size, Dimension::Type dimension )
4153 const float minSize = GetMinimumSize( dimension );
4154 const float maxSize = GetMaximumSize( dimension );
4156 return std::max( minSize, std::min( size, maxSize ) );
4159 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4161 // Check if it needs to be negotiated
4162 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4164 // Check that we havn't gotten into an infinite loop
4165 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4166 bool recursionFound = false;
4167 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4169 if( *it == searchActor )
4171 recursionFound = true;
4176 if( !recursionFound )
4178 // Record the path that we have taken
4179 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4181 // Dimension dependency check
4182 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4184 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4186 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4188 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4192 // Parent dependency check
4193 Actor* parent = GetParent();
4194 if( parent && RelayoutDependentOnParent( dimension ) )
4196 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4199 // Children dependency check
4200 if( RelayoutDependentOnChildren( dimension ) )
4202 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4204 ActorPtr child = GetChildAt( i );
4206 // Only relayout child first if it is not dependent on this actor
4207 if( !child->RelayoutDependentOnParent( dimension ) )
4209 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4214 // For deriving classes
4215 OnCalculateRelayoutSize( dimension );
4217 // All dependencies checked, calculate the size and set negotiated flag
4218 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4220 SetNegotiatedDimension( newSize, dimension );
4221 SetLayoutNegotiated( true, dimension );
4223 // For deriving classes
4224 OnLayoutNegotiated( newSize, dimension );
4226 // This actor has been successfully processed, pop it off the recursion stack
4227 recursionStack.pop_back();
4231 // TODO: Break infinite loop
4232 SetLayoutNegotiated( true, dimension );
4237 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4239 // Negotiate all dimensions that require it
4240 ActorDimensionStack recursionStack;
4242 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4244 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4247 NegotiateDimension( dimension, allocatedSize, recursionStack );
4251 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4253 switch( mRelayoutData->sizeSetPolicy )
4255 case SizeScalePolicy::USE_SIZE_SET:
4260 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4262 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4263 const Vector3 naturalSize = GetNaturalSize();
4264 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4266 const float sizeRatio = size.width / size.height;
4267 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4269 if( naturalSizeRatio < sizeRatio )
4271 return Vector2( naturalSizeRatio * size.height, size.height );
4273 else if( naturalSizeRatio > sizeRatio )
4275 return Vector2( size.width, size.width / naturalSizeRatio );
4286 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4288 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4289 const Vector3 naturalSize = GetNaturalSize();
4290 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4292 const float sizeRatio = size.width / size.height;
4293 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4295 if( naturalSizeRatio < sizeRatio )
4297 return Vector2( size.width, size.width / naturalSizeRatio );
4299 else if( naturalSizeRatio > sizeRatio )
4301 return Vector2( naturalSizeRatio * size.height, size.height );
4320 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4322 // Do the set actor size
4323 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4325 // Adjust for size set policy
4326 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4328 // Lock the flag to stop recursive relayouts on set size
4329 mRelayoutData->insideRelayout = true;
4330 SetSize( negotiatedSize );
4331 mRelayoutData->insideRelayout = false;
4333 // Clear flags for all dimensions
4334 SetLayoutDirty( false );
4336 // Give deriving classes a chance to respond
4337 OnRelayout( negotiatedSize, container );
4339 if( !mOnRelayoutSignal.Empty() )
4341 Dali::Actor handle( this );
4342 mOnRelayoutSignal.Emit( handle );
4346 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4348 // Force a size negotiation for actors that has assigned size during relayout
4349 // This is required as otherwise the flags that force a relayout will not
4350 // necessarilly be set. This will occur if the actor has already been laid out.
4351 // The dirty flags are then cleared. Then if the actor is added back into the
4352 // relayout container afterwards, the dirty flags would still be clear...
4353 // causing a relayout to be skipped. Here we force any actors added to the
4354 // container to be relayed out.
4355 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4357 SetLayoutNegotiated(false, Dimension::WIDTH);
4359 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4361 SetLayoutNegotiated(false, Dimension::HEIGHT);
4364 // Do the negotiation
4365 NegotiateDimensions( allocatedSize );
4367 // Set the actor size
4368 SetNegotiatedSize( container );
4370 // Negotiate down to children
4371 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4373 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4375 ActorPtr child = GetChildAt( i );
4377 // Forces children that have already been laid out to be relayed out
4378 // if they have assigned size during relayout.
4379 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4381 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4382 child->SetLayoutDirty(true, Dimension::WIDTH);
4384 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4386 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4387 child->SetLayoutDirty(true, Dimension::HEIGHT);
4390 // Only relayout if required
4391 if( child->RelayoutRequired() )
4393 container.Add( Dali::Actor( child.Get() ), newBounds );
4398 void Actor::RelayoutRequest( Dimension::Type dimension )
4400 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4401 if( relayoutController )
4403 Dali::Actor self( this );
4404 relayoutController->RequestRelayout( self, dimension );
4408 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4412 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4416 void Actor::SetPreferredSize( const Vector2& size )
4418 EnsureRelayoutData();
4420 if( size.width > 0.0f )
4422 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4425 if( size.height > 0.0f )
4427 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4430 mRelayoutData->preferredSize = size;
4435 Vector2 Actor::GetPreferredSize() const
4437 if ( mRelayoutData )
4439 return Vector2( mRelayoutData->preferredSize );
4442 return GetDefaultPreferredSize();
4445 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4447 EnsureRelayoutData();
4449 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4451 if( dimension & ( 1 << i ) )
4453 mRelayoutData->minimumSize[ i ] = size;
4460 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4462 if ( mRelayoutData )
4464 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4466 if( dimension & ( 1 << i ) )
4468 return mRelayoutData->minimumSize[ i ];
4473 return 0.0f; // Default
4476 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4478 EnsureRelayoutData();
4480 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4482 if( dimension & ( 1 << i ) )
4484 mRelayoutData->maximumSize[ i ] = size;
4491 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4493 if ( mRelayoutData )
4495 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4497 if( dimension & ( 1 << i ) )
4499 return mRelayoutData->maximumSize[ i ];
4504 return FLT_MAX; // Default
4507 Object* Actor::GetParentObject() const
4512 void Actor::SetSiblingOrder( unsigned int order )
4514 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4517 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4521 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4523 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4524 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4526 // Start at index 0, while index <= highest order
4527 // Find next index higher than 0
4528 // if nextHigher > index+1
4529 // set all nextHigher orders to index+1
4531 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4533 ActorIter end = siblings.end();
4534 int highestOrder = 0;
4535 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4537 ActorPtr sibling = (*iter);
4538 int siblingOrder = sibling->mSiblingOrder;
4539 highestOrder = std::max( highestOrder, siblingOrder );
4542 for ( int index = 0; index <= highestOrder; index++ )
4544 int nextHighest = -1;
4546 // Find Next highest
4547 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4549 ActorPtr sibling = (*iter);
4550 int siblingOrder = sibling->mSiblingOrder;
4552 if ( siblingOrder > index )
4554 if ( nextHighest == -1 )
4556 nextHighest = siblingOrder;
4558 nextHighest = std::min( nextHighest, siblingOrder );
4562 // Check if a gap exists between indexes, if so set next index to consecutive number
4563 if ( ( nextHighest - index ) > 1 )
4565 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4567 ActorPtr sibling = (*iter);
4568 int siblingOrder = sibling->mSiblingOrder;
4569 if ( siblingOrder == nextHighest )
4571 sibling->mSiblingOrder = index + 1;
4572 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4574 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4575 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4577 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4584 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4586 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4587 bool defragmentationRequired( false );
4588 ActorIter end = siblings.end();
4589 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4591 // Move actors at nearest order and above up by 1
4592 ActorPtr sibling = (*iter);
4593 if ( sibling != this )
4595 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4596 // be incremented by 1.
4597 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4599 sibling->mSiblingOrder++;
4600 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4602 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4603 // can re-order all sibling orders.
4604 defragmentationRequired = true;
4606 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4610 return defragmentationRequired;
4616 1) Check if already at top and nothing to be done.
4617 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4618 order can be positioned above it due to insertion order of actors.
4619 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4620 3) a) There may be other levels above this target level
4621 b) Increment all sibling levels at the level above nearest(target)
4622 c) Now have a vacant sibling level
4623 4) Set this actor's sibling level to nearest +1 as now vacated.
4625 Note May not just be sibling level + 1 as could be empty levels in-between
4630 ActorC ( sibling level 4 )
4631 ActorB ( sibling level 3 )
4632 ActorA ( sibling level 1 )
4634 2 ) ACTION: Raise A above B
4635 a) Find nearest level above A = Level 3
4636 b) Increment levels above Level 3
4638 ActorC ( sibling level 5 )
4639 ActorB ( sibling level 3 ) NEAREST
4640 ActorA ( sibling level 1 )
4642 3 ) Set Actor A sibling level to nearest +1 as vacant
4644 ActorC ( sibling level 5 )
4645 ActorA ( sibling level 4 )
4646 ActorB ( sibling level 3 )
4648 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4649 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4650 remove any empty sibling order gaps and start from sibling level 0 again.
4651 If the number of actors reaches this maximum and all using exclusive sibling order values then
4652 defragmention will stop and new sibling orders will be set to same max value.
4656 int nearestLevel = mSiblingOrder;
4657 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4658 bool defragmentationRequired( false );
4660 ActorContainer* siblings = mParent->mChildren;
4662 // Find Nearest sibling level above this actor
4663 ActorIter end = siblings->end();
4664 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4666 ActorPtr sibling = (*iter);
4667 if ( sibling != this )
4669 int order = GetSiblingOrder( sibling );
4671 if ( ( order >= mSiblingOrder ) )
4673 int distanceToNextLevel = order - mSiblingOrder;
4674 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4676 nearestLevel = order;
4677 shortestDistanceToNextLevel = distanceToNextLevel;
4683 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4685 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4686 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4687 // Move current actor to newly vacated order level
4688 SetSiblingOrder( mSiblingOrder );
4689 if ( defragmentationRequired )
4691 DefragmentSiblingIndexes( *siblings );
4694 SetSiblingOrder( mSiblingOrder );
4698 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4705 1) Check if actor already at bottom and if nothing needs to be done
4706 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4707 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4708 2) Find nearest sibling level below, this Actor needs to be below it
4709 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4710 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4711 c) Set this actor's sibling level to this newly vacated level.
4712 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4713 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4714 remove any empty sibling order gaps and start from sibling level 0 again.
4715 If the number of actors reaches this maximum and all using exclusive sibling order values then
4716 defragmention will stop and new sibling orders will be set to same max value.
4721 // 1) Find nearest level below
4722 int nearestLevel = mSiblingOrder;
4723 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4725 ActorContainer* siblings = mParent->mChildren;
4727 ActorIter end = siblings->end();
4728 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4730 ActorPtr sibling = (*iter);
4731 if ( sibling != this )
4733 int order = GetSiblingOrder( sibling );
4735 if ( order <= mSiblingOrder )
4737 int distanceToNextLevel = mSiblingOrder - order;
4738 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4740 nearestLevel = order;
4741 shortestDistanceToNextLevel = distanceToNextLevel;
4747 bool defragmentationRequired ( false );
4749 // 2) If actor already not at bottom, raise all actors at required level and above
4750 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4752 mSiblingOrder = nearestLevel;
4753 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4754 // Move current actor to newly vacated order
4755 SetSiblingOrder( mSiblingOrder );
4756 if ( defragmentationRequired )
4758 DefragmentSiblingIndexes( *siblings );
4764 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4768 void Actor::RaiseToTop()
4771 1 ) Find highest sibling order actor
4772 2 ) If highest sibling level not itself then set sibling order to that + 1
4773 3 ) highest sibling order can be same as itself so need to increment over that
4774 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4775 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4776 remove any empty sibling order gaps and start from sibling level 0 again.
4777 If the number of actors reaches this maximum and all using exclusive sibling order values then
4778 defragmention will stop and new sibling orders will be set to same max value.
4785 ActorContainer* siblings = mParent->mChildren;
4787 ActorIter end = siblings->end();
4788 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4790 ActorPtr sibling = (*iter);
4791 if ( sibling != this )
4793 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4797 bool defragmentationRequired( false );
4799 if ( maxOrder >= mSiblingOrder )
4801 mSiblingOrder = maxOrder + 1;
4802 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4804 defragmentationRequired = true;
4808 SetSiblingOrder( mSiblingOrder );
4810 if ( defragmentationRequired )
4812 DefragmentSiblingIndexes( *siblings );
4817 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4821 void Actor::LowerToBottom()
4824 See Actor::LowerToBottom()
4826 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4827 2 ) a ) Check if the bottom position 0 is vacant.
4828 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4829 c ) 0 sibling position is vacant.
4830 3 ) Set this actor to vacant sibling order 0;
4831 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4832 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4833 remove any empty sibling order gaps and start from sibling level 0 again.
4834 If the number of actors reaches this maximum and all using exclusive sibling order values then
4835 defragmention will stop and new sibling orders will be set to same max value.
4840 bool defragmentationRequired( false );
4841 bool orderZeroFree ( true );
4843 ActorContainer* siblings = mParent->mChildren;
4845 bool actorAtLowestOrder = true;
4846 ActorIter end = siblings->end();
4847 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4849 ActorPtr sibling = (*iter);
4850 if ( sibling != this )
4852 int siblingOrder = GetSiblingOrder( sibling );
4853 if ( siblingOrder <= mSiblingOrder )
4855 actorAtLowestOrder = false;
4858 if ( siblingOrder == 0 )
4860 orderZeroFree = false;
4865 if ( ! actorAtLowestOrder )
4867 if ( ! orderZeroFree )
4869 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4872 SetSiblingOrder( mSiblingOrder );
4874 if ( defragmentationRequired )
4876 DefragmentSiblingIndexes( *siblings );
4882 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4886 void Actor::RaiseAbove( Internal::Actor& target )
4889 1 ) a) Find target actor's sibling order
4890 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4891 needs to be above it or the insertion order will determine which is drawn on top.
4892 2 ) Shift up by 1 all sibling order greater than target sibling order
4893 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4894 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4895 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4896 remove any empty sibling order gaps and start from sibling level 0 again.
4897 If the number of actors reaches this maximum and all using exclusive sibling order values then
4898 defragmention will stop and new sibling orders will be set to same max value.
4903 if ( ValidateActors( *this, target ) )
4905 // Find target's sibling order
4906 // Set actor sibling order to this number +1
4907 int targetSiblingOrder = GetSiblingOrder( &target );
4908 ActorContainer* siblings = mParent->mChildren;
4909 mSiblingOrder = targetSiblingOrder + 1;
4910 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4912 SetSiblingOrder( mSiblingOrder );
4914 if ( defragmentationRequired )
4916 DefragmentSiblingIndexes( *(mParent->mChildren) );
4922 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4926 void Actor::LowerBelow( Internal::Actor& target )
4929 1 ) a) Find target actor's sibling order
4930 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4931 needs to be below it or the insertion order will determine which is drawn on top.
4932 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4933 3 ) Set this actor to the sibling order of the target before it changed.
4934 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4935 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4936 remove any empty sibling order gaps and start from sibling level 0 again.
4937 If the number of actors reaches this maximum and all using exclusive sibling order values then
4938 defragmention will stop and new sibling orders will be set to same max value.
4943 if ( ValidateActors( *this, target ) )
4945 bool defragmentationRequired ( false );
4946 // Find target's sibling order
4947 // Set actor sibling order to target sibling order - 1
4948 int targetSiblingOrder = GetSiblingOrder( &target);
4949 ActorContainer* siblings = mParent->mChildren;
4950 if ( targetSiblingOrder == 0 )
4953 ActorIter end = siblings->end();
4954 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4956 ActorPtr sibling = (*iter);
4957 if ( sibling != this )
4959 sibling->mSiblingOrder++;
4960 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4962 defragmentationRequired = true;
4964 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4971 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
4973 mSiblingOrder = targetSiblingOrder;
4975 SetSiblingOrder( mSiblingOrder );
4977 if ( defragmentationRequired )
4979 DefragmentSiblingIndexes( *(mParent->mChildren) );
4985 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4989 } // namespace Internal