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;
394 * @brief Recursively emits the visibility-changed-signal on the actor tree.
395 * @param[in] actor The actor to emit the signal on
396 * @param[in] visible The new visibility of the actor
397 * @param[in] type Whether the actor's visible property has changed or a parent's
399 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
403 actor->EmitVisibilityChangedSignal( visible, type );
405 if( actor->GetChildCount() > 0 )
407 ActorContainer& children = actor->GetChildrenInternal();
408 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
410 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
416 } // unnamed namespace
418 ActorPtr Actor::New()
420 ActorPtr actor( new Actor( BASIC ) );
422 // Second-phase construction
428 const std::string& Actor::GetName() const
433 void Actor::SetName( const std::string& name )
439 // ATTENTION: string for debug purposes is not thread safe.
440 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
444 unsigned int Actor::GetId() const
449 bool Actor::OnStage() const
454 Dali::Layer Actor::GetLayer()
458 // Short-circuit for Layer derived actors
461 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
464 // Find the immediate Layer parent
465 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
467 if( parent->IsLayer() )
469 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
476 void Actor::Add( Actor& child )
478 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
479 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
483 mChildren = new ActorContainer;
486 Actor* const oldParent( child.mParent );
488 // child might already be ours
489 if( this != oldParent )
491 // if we already have parent, unparent us first
494 oldParent->Remove( child ); // This causes OnChildRemove callback
496 // Old parent may need to readjust to missing child
497 if( oldParent->RelayoutDependentOnChildren() )
499 oldParent->RelayoutRequest();
503 // Guard against Add() during previous OnChildRemove callback
506 // Do this first, since user callbacks from within SetParent() may need to remove child
507 mChildren->push_back( ActorPtr( &child ) );
509 // SetParent asserts that child can be added
510 child.SetParent( this );
512 // Notification for derived classes
515 // Only put in a relayout request if there is a suitable dependency
516 if( RelayoutDependentOnChildren() )
524 void Actor::Remove( Actor& child )
526 if( (this == &child) || (!mChildren) )
528 // no children or removing itself
534 // Find the child in mChildren, and unparent it
535 ActorIter end = mChildren->end();
536 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
538 ActorPtr actor = (*iter);
540 if( actor.Get() == &child )
542 // Keep handle for OnChildRemove notification
545 // Do this first, since user callbacks from within SetParent() may need to add the child
546 mChildren->erase( iter );
548 DALI_ASSERT_DEBUG( actor->GetParent() == this );
549 actor->SetParent( NULL );
557 // Only put in a relayout request if there is a suitable dependency
558 if( RelayoutDependentOnChildren() )
564 // Notification for derived classes
565 OnChildRemove( child );
568 void Actor::Unparent()
572 // Remove this actor from the parent. The remove will put a relayout request in for
573 // the parent if required
574 mParent->Remove( *this );
575 // mParent is now NULL!
579 unsigned int Actor::GetChildCount() const
581 return ( NULL != mChildren ) ? mChildren->size() : 0;
584 ActorPtr Actor::GetChildAt( unsigned int index ) const
586 DALI_ASSERT_ALWAYS( index < GetChildCount() );
588 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
591 ActorPtr Actor::FindChildByName( const std::string& actorName )
594 if( actorName == mName )
600 ActorIter end = mChildren->end();
601 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
603 child = (*iter)->FindChildByName( actorName );
614 ActorPtr Actor::FindChildById( const unsigned int id )
623 ActorIter end = mChildren->end();
624 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
626 child = (*iter)->FindChildById( id );
637 void Actor::SetParentOrigin( const Vector3& origin )
641 // mNode is being used in a separate thread; queue a message to set the value & base value
642 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
645 // Cache for event-thread access
648 // not allocated, check if different from default
649 if( ParentOrigin::DEFAULT != origin )
651 mParentOrigin = new Vector3( origin );
656 // check if different from current costs more than just set
657 *mParentOrigin = origin;
661 void Actor::SetParentOriginX( float x )
663 const Vector3& current = GetCurrentParentOrigin();
665 SetParentOrigin( Vector3( x, current.y, current.z ) );
668 void Actor::SetParentOriginY( float y )
670 const Vector3& current = GetCurrentParentOrigin();
672 SetParentOrigin( Vector3( current.x, y, current.z ) );
675 void Actor::SetParentOriginZ( float z )
677 const Vector3& current = GetCurrentParentOrigin();
679 SetParentOrigin( Vector3( current.x, current.y, z ) );
682 const Vector3& Actor::GetCurrentParentOrigin() const
684 // Cached for event-thread access
685 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
688 void Actor::SetAnchorPoint( const Vector3& anchor )
692 // mNode is being used in a separate thread; queue a message to set the value & base value
693 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
696 // Cache for event-thread access
699 // not allocated, check if different from default
700 if( AnchorPoint::DEFAULT != anchor )
702 mAnchorPoint = new Vector3( anchor );
707 // check if different from current costs more than just set
708 *mAnchorPoint = anchor;
712 void Actor::SetAnchorPointX( float x )
714 const Vector3& current = GetCurrentAnchorPoint();
716 SetAnchorPoint( Vector3( x, current.y, current.z ) );
719 void Actor::SetAnchorPointY( float y )
721 const Vector3& current = GetCurrentAnchorPoint();
723 SetAnchorPoint( Vector3( current.x, y, current.z ) );
726 void Actor::SetAnchorPointZ( float z )
728 const Vector3& current = GetCurrentAnchorPoint();
730 SetAnchorPoint( Vector3( current.x, current.y, z ) );
733 const Vector3& Actor::GetCurrentAnchorPoint() const
735 // Cached for event-thread access
736 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
739 void Actor::SetPosition( float x, float y )
741 SetPosition( Vector3( x, y, 0.0f ) );
744 void Actor::SetPosition( float x, float y, float z )
746 SetPosition( Vector3( x, y, z ) );
749 void Actor::SetPosition( const Vector3& position )
751 mTargetPosition = position;
755 // mNode is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
760 void Actor::SetX( float x )
762 mTargetPosition.x = x;
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
771 void Actor::SetY( float y )
773 mTargetPosition.y = y;
777 // mNode is being used in a separate thread; queue a message to set the value & base value
778 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
782 void Actor::SetZ( float z )
784 mTargetPosition.z = z;
788 // mNode is being used in a separate thread; queue a message to set the value & base value
789 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
793 void Actor::TranslateBy( const Vector3& distance )
795 mTargetPosition += distance;
799 // mNode is being used in a separate thread; queue a message to set the value & base value
800 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
804 const Vector3& Actor::GetCurrentPosition() const
808 // mNode is being used in a separate thread; copy the value from the previous update
809 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
812 return Vector3::ZERO;
815 const Vector3& Actor::GetTargetPosition() const
817 return mTargetPosition;
820 const Vector3& Actor::GetCurrentWorldPosition() const
824 // mNode is being used in a separate thread; copy the value from the previous update
825 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
828 return Vector3::ZERO;
831 const Vector2 Actor::GetCurrentScreenPosition() const
833 if( OnStage() && NULL != mNode )
835 StagePtr stage = Stage::GetCurrent();
836 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
837 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
838 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
839 Vector3 halfActorSize( actorSize * 0.5f );
840 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
842 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
843 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
846 return Vector2::ZERO;
849 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
851 // this flag is not animatable so keep the value
852 mPositionInheritanceMode = mode;
855 // mNode is being used in a separate thread; queue a message to set the value
856 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
860 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
862 // Cached for event-thread access
863 return mPositionInheritanceMode;
866 void Actor::SetInheritPosition( bool inherit )
868 if( mInheritPosition != inherit && NULL != mNode )
870 // non animateable so keep local copy
871 mInheritPosition = inherit;
872 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
876 bool Actor::IsPositionInherited() const
878 return mInheritPosition;
881 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
883 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
884 normalizedAxis.Normalize();
886 Quaternion orientation( angle, normalizedAxis );
888 SetOrientation( orientation );
891 void Actor::SetOrientation( const Quaternion& orientation )
895 // mNode is being used in a separate thread; queue a message to set the value & base value
896 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
900 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
904 // mNode is being used in a separate thread; queue a message to set the value & base value
905 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
909 void Actor::RotateBy( const Quaternion& relativeRotation )
913 // mNode is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
918 const Quaternion& Actor::GetCurrentOrientation() const
922 // mNode is being used in a separate thread; copy the value from the previous update
923 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
926 return Quaternion::IDENTITY;
929 const Quaternion& Actor::GetCurrentWorldOrientation() const
933 // mNode is being used in a separate thread; copy the value from the previous update
934 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
937 return Quaternion::IDENTITY;
940 void Actor::SetScale( float scale )
942 SetScale( Vector3( scale, scale, scale ) );
945 void Actor::SetScale( float x, float y, float z )
947 SetScale( Vector3( x, y, z ) );
950 void Actor::SetScale( const Vector3& scale )
954 // mNode is being used in a separate thread; queue a message to set the value & base value
955 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
959 void Actor::SetScaleX( float x )
963 // mNode is being used in a separate thread; queue a message to set the value & base value
964 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
968 void Actor::SetScaleY( float y )
972 // mNode is being used in a separate thread; queue a message to set the value & base value
973 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
977 void Actor::SetScaleZ( float z )
981 // mNode is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
986 void Actor::ScaleBy(const Vector3& relativeScale)
990 // mNode is being used in a separate thread; queue a message to set the value & base value
991 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
995 const Vector3& Actor::GetCurrentScale() const
999 // mNode is being used in a separate thread; copy the value from the previous update
1000 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1003 return Vector3::ONE;
1006 const Vector3& Actor::GetCurrentWorldScale() const
1010 // mNode is being used in a separate thread; copy the value from the previous update
1011 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1014 return Vector3::ONE;
1017 void Actor::SetInheritScale( bool inherit )
1020 if( mInheritScale != inherit && NULL != mNode )
1022 // non animateable so keep local copy
1023 mInheritScale = inherit;
1024 // mNode is being used in a separate thread; queue a message to set the value
1025 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1029 bool Actor::IsScaleInherited() const
1031 return mInheritScale;
1034 Matrix Actor::GetCurrentWorldMatrix() const
1038 return mNode->GetWorldMatrix(0);
1041 return Matrix::IDENTITY;
1044 void Actor::SetVisible( bool visible )
1046 if( mVisible != visible )
1050 // mNode is being used in a separate thread; queue a message to set the value & base value
1051 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1056 // Emit the signal on this actor and all its children
1057 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
1061 bool Actor::IsVisible() const
1065 // mNode is being used in a separate thread; copy the value from the previous update
1066 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1072 void Actor::SetOpacity( float opacity )
1076 // mNode is being used in a separate thread; queue a message to set the value & base value
1077 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1081 float Actor::GetCurrentOpacity() const
1085 // mNode is being used in a separate thread; copy the value from the previous update
1086 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1092 ClippingMode::Type Actor::GetClippingMode() const
1094 return mClippingMode;
1097 unsigned int Actor::GetSortingDepth()
1099 return GetDepthIndex( mDepth, mSiblingOrder );
1102 const Vector4& Actor::GetCurrentWorldColor() const
1106 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1109 return Color::WHITE;
1112 void Actor::SetColor( const Vector4& color )
1116 // mNode is being used in a separate thread; queue a message to set the value & base value
1117 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1121 void Actor::SetColorRed( float red )
1125 // mNode is being used in a separate thread; queue a message to set the value & base value
1126 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1130 void Actor::SetColorGreen( float green )
1134 // mNode is being used in a separate thread; queue a message to set the value & base value
1135 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1139 void Actor::SetColorBlue( float blue )
1143 // mNode is being used in a separate thread; queue a message to set the value & base value
1144 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1148 const Vector4& Actor::GetCurrentColor() const
1152 // mNode is being used in a separate thread; copy the value from the previous update
1153 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1156 return Color::WHITE;
1159 void Actor::SetInheritOrientation( bool inherit )
1161 if( mInheritOrientation != inherit && NULL != mNode)
1163 // non animateable so keep local copy
1164 mInheritOrientation = inherit;
1165 // mNode is being used in a separate thread; queue a message to set the value
1166 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1170 bool Actor::IsOrientationInherited() const
1172 return mInheritOrientation;
1175 void Actor::SetSizeModeFactor( const Vector3& factor )
1177 EnsureRelayoutData();
1179 mRelayoutData->sizeModeFactor = factor;
1182 const Vector3& Actor::GetSizeModeFactor() const
1184 if ( mRelayoutData )
1186 return mRelayoutData->sizeModeFactor;
1189 return GetDefaultSizeModeFactor();
1192 void Actor::SetColorMode( ColorMode colorMode )
1194 // non animateable so keep local copy
1195 mColorMode = colorMode;
1198 // mNode is being used in a separate thread; queue a message to set the value
1199 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1203 ColorMode Actor::GetColorMode() const
1205 // we have cached copy
1209 void Actor::SetSize( float width, float height )
1211 SetSize( Vector2( width, height ) );
1214 void Actor::SetSize( float width, float height, float depth )
1216 SetSize( Vector3( width, height, depth ) );
1219 void Actor::SetSize( const Vector2& size )
1221 SetSize( Vector3( size.width, size.height, 0.f ) );
1224 void Actor::SetSizeInternal( const Vector2& size )
1226 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1229 void Actor::SetSize( const Vector3& size )
1231 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1233 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1234 SetPreferredSize( size.GetVectorXY() );
1238 SetSizeInternal( size );
1242 void Actor::SetSizeInternal( const Vector3& size )
1244 // dont allow recursive loop
1245 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1246 // 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
1247 if( ( NULL != mNode )&&
1248 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1249 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1250 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1254 // mNode is being used in a separate thread; queue a message to set the value & base value
1255 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1257 // Notification for derived classes
1258 mInsideOnSizeSet = true;
1259 OnSizeSet( mTargetSize );
1260 mInsideOnSizeSet = false;
1262 // Raise a relayout request if the flag is not locked
1263 if( mRelayoutData && !mRelayoutData->insideRelayout )
1270 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1272 mTargetSize = targetSize;
1274 // Notify deriving classes
1275 OnSizeAnimation( animation, mTargetSize );
1278 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1280 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1282 mTargetSize.width = targetSize;
1284 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1286 mTargetSize.height = targetSize;
1288 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1290 mTargetSize.depth = targetSize;
1292 // Notify deriving classes
1293 OnSizeAnimation( animation, mTargetSize );
1296 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1298 mTargetPosition = targetPosition;
1301 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1303 if ( Dali::Actor::Property::POSITION_X == property )
1305 mTargetPosition.x = targetPosition;
1307 else if ( Dali::Actor::Property::POSITION_Y == property )
1309 mTargetPosition.y = targetPosition;
1311 else if ( Dali::Actor::Property::POSITION_Z == property )
1313 mTargetPosition.z = targetPosition;
1317 void Actor::SetWidth( float width )
1319 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1321 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1322 mRelayoutData->preferredSize.width = width;
1326 mTargetSize.width = width;
1330 // mNode is being used in a separate thread; queue a message to set the value & base value
1331 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1338 void Actor::SetHeight( float height )
1340 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1342 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1343 mRelayoutData->preferredSize.height = height;
1347 mTargetSize.height = height;
1351 // mNode is being used in a separate thread; queue a message to set the value & base value
1352 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1359 void Actor::SetDepth( float depth )
1361 mTargetSize.depth = depth;
1365 // mNode is being used in a separate thread; queue a message to set the value & base value
1366 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1370 const Vector3& Actor::GetTargetSize() const
1375 const Vector3& Actor::GetCurrentSize() const
1379 // mNode is being used in a separate thread; copy the value from the previous update
1380 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1383 return Vector3::ZERO;
1386 Vector3 Actor::GetNaturalSize() const
1388 // It is up to deriving classes to return the appropriate natural size
1389 return Vector3( 0.0f, 0.0f, 0.0f );
1392 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1394 EnsureRelayoutData();
1396 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1397 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1399 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1401 if( dimension & ( 1 << i ) )
1403 mRelayoutData->resizePolicies[ i ] = policy;
1407 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1409 if( dimension & Dimension::WIDTH )
1411 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1414 if( dimension & Dimension::HEIGHT )
1416 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1420 // If calling SetResizePolicy, assume we want relayout enabled
1421 SetRelayoutEnabled( true );
1423 // If the resize policy is set to be FIXED, the preferred size
1424 // should be overrided by the target size. Otherwise the target
1425 // size should be overrided by the preferred size.
1427 if( dimension & Dimension::WIDTH )
1429 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1431 mRelayoutData->preferredSize.width = mTargetSize.width;
1433 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1435 mTargetSize.width = mRelayoutData->preferredSize.width;
1439 if( dimension & Dimension::HEIGHT )
1441 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1443 mRelayoutData->preferredSize.height = mTargetSize.height;
1445 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1447 mTargetSize.height = mRelayoutData->preferredSize.height;
1451 OnSetResizePolicy( policy, dimension );
1453 // Trigger relayout on this control
1457 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1459 if ( mRelayoutData )
1461 // If more than one dimension is requested, just return the first one found
1462 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1464 if( ( dimension & ( 1 << i ) ) )
1466 return mRelayoutData->resizePolicies[ i ];
1471 return ResizePolicy::DEFAULT;
1474 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1476 EnsureRelayoutData();
1478 mRelayoutData->sizeSetPolicy = policy;
1481 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1483 if ( mRelayoutData )
1485 return mRelayoutData->sizeSetPolicy;
1488 return DEFAULT_SIZE_SCALE_POLICY;
1491 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1493 EnsureRelayoutData();
1495 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1497 if( dimension & ( 1 << i ) )
1499 mRelayoutData->dimensionDependencies[ i ] = dependency;
1504 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1506 if ( mRelayoutData )
1508 // If more than one dimension is requested, just return the first one found
1509 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1511 if( ( dimension & ( 1 << i ) ) )
1513 return mRelayoutData->dimensionDependencies[ i ];
1518 return Dimension::ALL_DIMENSIONS; // Default
1521 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1523 // If relayout data has not been allocated yet and the client is requesting
1524 // to disable it, do nothing
1525 if( mRelayoutData || relayoutEnabled )
1527 EnsureRelayoutData();
1529 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1531 mRelayoutData->relayoutEnabled = relayoutEnabled;
1535 bool Actor::IsRelayoutEnabled() const
1537 // Assume that if relayout data has not been allocated yet then
1538 // relayout is disabled
1539 return mRelayoutData && mRelayoutData->relayoutEnabled;
1542 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1544 EnsureRelayoutData();
1546 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1548 if( dimension & ( 1 << i ) )
1550 mRelayoutData->dimensionDirty[ i ] = dirty;
1555 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1557 if ( mRelayoutData )
1559 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1561 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1571 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1573 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1576 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1578 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1581 unsigned int Actor::AddRenderer( Renderer& renderer )
1585 mRenderers = new RendererContainer;
1588 unsigned int index = mRenderers->size();
1589 RendererPtr rendererPtr = RendererPtr( &renderer );
1590 mRenderers->push_back( rendererPtr );
1591 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1595 unsigned int Actor::GetRendererCount() const
1597 unsigned int rendererCount(0);
1600 rendererCount = mRenderers->size();
1603 return rendererCount;
1606 RendererPtr Actor::GetRendererAt( unsigned int index )
1608 RendererPtr renderer;
1609 if( index < GetRendererCount() )
1611 renderer = ( *mRenderers )[ index ];
1617 void Actor::RemoveRenderer( Renderer& renderer )
1621 RendererIter end = mRenderers->end();
1622 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1624 if( (*iter).Get() == &renderer )
1626 mRenderers->erase( iter );
1627 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1634 void Actor::RemoveRenderer( unsigned int index )
1636 if( index < GetRendererCount() )
1638 RendererPtr renderer = ( *mRenderers )[ index ];
1639 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1640 mRenderers->erase( mRenderers->begin()+index );
1644 bool Actor::IsOverlay() const
1646 return ( DrawMode::OVERLAY_2D == mDrawMode );
1649 void Actor::SetDrawMode( DrawMode::Type drawMode )
1651 // this flag is not animatable so keep the value
1652 mDrawMode = drawMode;
1653 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1655 // mNode is being used in a separate thread; queue a message to set the value
1656 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1660 DrawMode::Type Actor::GetDrawMode() const
1665 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1667 // only valid when on-stage
1668 StagePtr stage = Stage::GetCurrent();
1669 if( stage && OnStage() )
1671 const RenderTaskList& taskList = stage->GetRenderTaskList();
1673 Vector2 converted( screenX, screenY );
1675 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1676 const int taskCount = taskList.GetTaskCount();
1677 for( int i = taskCount - 1; i >= 0; --i )
1679 Dali::RenderTask task = taskList.GetTask( i );
1680 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1682 // found a task where this conversion was ok so return
1690 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1692 bool retval = false;
1693 // only valid when on-stage
1696 CameraActor* camera = renderTask.GetCameraActor();
1700 renderTask.GetViewport( viewport );
1702 // need to translate coordinates to render tasks coordinate space
1703 Vector2 converted( screenX, screenY );
1704 if( renderTask.TranslateCoordinates( converted ) )
1706 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1713 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1715 // Early-out if mNode is NULL
1721 // Get the ModelView matrix
1723 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1725 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1726 Matrix invertedMvp( false/*don't init*/);
1727 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1728 bool success = invertedMvp.Invert();
1730 // Convert to GL coordinates
1731 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1736 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1743 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1749 if( XyPlaneIntersect( nearPos, farPos, local ) )
1751 Vector3 size = GetCurrentSize();
1752 localX = local.x + size.x * 0.5f;
1753 localY = local.y + size.y * 0.5f;
1764 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1767 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1769 Mathematical Formulation
1771 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1773 ( p - c ) dot ( p - c ) = r^2
1775 Given a ray with a point of origin 'o', and a direction vector 'd':
1777 ray(t) = o + td, t >= 0
1779 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1781 (o + td - c ) dot ( o + td - c ) = r^2
1783 To solve for t we first expand the above into a more recognisable quadratic equation form
1785 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1794 B = 2( o - c ) dot d
1795 C = ( o - c ) dot ( o - c ) - r^2
1797 which can be solved using a standard quadratic formula.
1799 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1801 Practical Simplification
1803 In a renderer, we often differentiate between world space and object space. In the object space
1804 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1805 into object space, the mathematical solution presented above can be simplified significantly.
1807 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1811 and we can find the t at which the (transformed) ray intersects the sphere by
1813 ( o + td ) dot ( o + td ) = r^2
1815 According to the reasoning above, we expand the above quadratic equation into the general form
1819 which now has coefficients:
1826 // Early out if mNode is NULL
1832 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1834 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1835 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1836 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1838 // Compute the radius is not needed, square radius it's enough.
1839 const Vector3& size( mNode->GetSize( bufferIndex ) );
1841 // Scale the sphere.
1842 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1844 const float width = size.width * scale.width;
1845 const float height = size.height * scale.height;
1847 float squareSphereRadius = 0.5f * ( width * width + height * height );
1849 float a = rayDir.Dot( rayDir ); // a
1850 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1851 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1853 return ( b2 * b2 - a * c ) >= 0.f;
1856 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1860 if( OnStage() && NULL != mNode )
1862 // Transforms the ray to the local reference system.
1863 // Calculate the inverse of Model matrix
1864 Matrix invModelMatrix( false/*don't init*/);
1866 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1867 invModelMatrix = mNode->GetWorldMatrix(0);
1868 invModelMatrix.Invert();
1870 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1871 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1873 // Test with the actor's XY plane (Normal = 0 0 1 1).
1875 float a = -rayOriginLocal.z;
1876 float b = rayDirLocal.z;
1878 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1880 // Ray travels distance * rayDirLocal to intersect with plane.
1883 const Vector3& size = mNode->GetSize( bufferIndex );
1885 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1886 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1888 // Test with the actor's geometry.
1889 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1896 void Actor::SetLeaveRequired( bool required )
1898 mLeaveRequired = required;
1901 bool Actor::GetLeaveRequired() const
1903 return mLeaveRequired;
1906 void Actor::SetKeyboardFocusable( bool focusable )
1908 mKeyboardFocusable = focusable;
1911 bool Actor::IsKeyboardFocusable() const
1913 return mKeyboardFocusable;
1916 bool Actor::GetTouchRequired() const
1918 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1921 bool Actor::GetHoverRequired() const
1923 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1926 bool Actor::GetWheelEventRequired() const
1928 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1931 bool Actor::IsHittable() const
1933 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1936 ActorGestureData& Actor::GetGestureData()
1938 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1939 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1940 if( NULL == mGestureData )
1942 mGestureData = new ActorGestureData;
1944 return *mGestureData;
1947 bool Actor::IsGestureRequred( Gesture::Type type ) const
1949 return mGestureData && mGestureData->IsGestureRequred( type );
1952 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1954 bool consumed = false;
1956 if( !mTouchSignal.Empty() )
1958 Dali::Actor handle( this );
1959 consumed = mTouchSignal.Emit( handle, touch );
1962 if( !mTouchedSignal.Empty() )
1964 Dali::Actor handle( this );
1965 consumed |= mTouchedSignal.Emit( handle, event );
1970 // Notification for derived classes
1971 consumed = OnTouchEvent( event ); // TODO
1977 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1979 bool consumed = false;
1981 if( !mHoveredSignal.Empty() )
1983 Dali::Actor handle( this );
1984 consumed = mHoveredSignal.Emit( handle, event );
1989 // Notification for derived classes
1990 consumed = OnHoverEvent( event );
1996 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1998 bool consumed = false;
2000 if( !mWheelEventSignal.Empty() )
2002 Dali::Actor handle( this );
2003 consumed = mWheelEventSignal.Emit( handle, event );
2008 // Notification for derived classes
2009 consumed = OnWheelEvent( event );
2015 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2017 if( ! mVisibilityChangedSignal.Empty() )
2019 Dali::Actor handle( this );
2020 mVisibilityChangedSignal.Emit( handle, visible, type );
2024 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2026 return mTouchedSignal;
2029 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2031 return mTouchSignal;
2034 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2036 return mHoveredSignal;
2039 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2041 return mWheelEventSignal;
2044 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2046 return mOnStageSignal;
2049 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2051 return mOffStageSignal;
2054 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2056 return mOnRelayoutSignal;
2059 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2061 return mVisibilityChangedSignal;
2064 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2066 bool connected( true );
2067 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2069 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2071 actor->TouchedSignal().Connect( tracker, functor );
2073 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2075 actor->HoveredSignal().Connect( tracker, functor );
2077 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2079 actor->WheelEventSignal().Connect( tracker, functor );
2081 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2083 actor->OnStageSignal().Connect( tracker, functor );
2085 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2087 actor->OffStageSignal().Connect( tracker, functor );
2089 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2091 actor->OnRelayoutSignal().Connect( tracker, functor );
2093 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2095 actor->TouchSignal().Connect( tracker, functor );
2099 // signalName does not match any signal
2106 Actor::Actor( DerivedType derivedType )
2111 mParentOrigin( NULL ),
2112 mAnchorPoint( NULL ),
2113 mRelayoutData( NULL ),
2114 mGestureData( NULL ),
2115 mTargetSize( 0.0f, 0.0f, 0.0f ),
2117 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2120 mIsRoot( ROOT_LAYER == derivedType ),
2121 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2122 mIsOnStage( false ),
2124 mLeaveRequired( false ),
2125 mKeyboardFocusable( false ),
2126 mDerivedRequiresTouch( false ),
2127 mDerivedRequiresHover( false ),
2128 mDerivedRequiresWheelEvent( false ),
2129 mOnStageSignalled( false ),
2130 mInsideOnSizeSet( false ),
2131 mInheritPosition( true ),
2132 mInheritOrientation( true ),
2133 mInheritScale( true ),
2134 mPositionUsesAnchorPoint( true ),
2136 mDrawMode( DrawMode::NORMAL ),
2137 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2138 mColorMode( Node::DEFAULT_COLOR_MODE ),
2139 mClippingMode( ClippingMode::DISABLED )
2143 void Actor::Initialize()
2146 SceneGraph::Node* node = CreateNode();
2148 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2149 mNode = node; // Keep raw-pointer to Node
2153 GetEventThreadServices().RegisterObject( this );
2158 // Remove mParent pointers from children even if we're destroying core,
2159 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2162 ActorConstIter endIter = mChildren->end();
2163 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2165 (*iter)->SetParent( NULL );
2171 // Guard to allow handle destruction after Core has been destroyed
2172 if( EventThreadServices::IsCoreRunning() )
2176 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2177 mNode = NULL; // Node is about to be destroyed
2180 GetEventThreadServices().UnregisterObject( this );
2183 // Cleanup optional gesture data
2184 delete mGestureData;
2186 // Cleanup optional parent origin and anchor
2187 delete mParentOrigin;
2188 delete mAnchorPoint;
2190 // Delete optional relayout data
2193 delete mRelayoutData;
2197 void Actor::ConnectToStage( unsigned int parentDepth )
2199 // This container is used instead of walking the Actor hierarchy.
2200 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2201 ActorContainer connectionList;
2203 // This stage is atomic i.e. not interrupted by user callbacks.
2204 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2206 // Notify applications about the newly connected actors.
2207 const ActorIter endIter = connectionList.end();
2208 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2210 (*iter)->NotifyStageConnection();
2216 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2218 DALI_ASSERT_ALWAYS( !OnStage() );
2222 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2224 ConnectToSceneGraph();
2226 // Notification for internal derived classes
2227 OnStageConnectionInternal();
2229 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2230 connectionList.push_back( ActorPtr( this ) );
2232 // Recursively connect children
2235 ActorConstIter endIter = mChildren->end();
2236 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2238 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2244 * This method is called when the Actor is connected to the Stage.
2245 * The parent must have added its Node to the scene-graph.
2246 * The child must connect its Node to the parent's Node.
2247 * This is recursive; the child calls ConnectToStage() for its children.
2249 void Actor::ConnectToSceneGraph()
2251 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2255 // Reparent Node in next Update
2256 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2259 // Request relayout on all actors that are added to the scenegraph
2262 // Notification for Object::Observers
2266 void Actor::NotifyStageConnection()
2268 // Actors can be removed (in a callback), before the on-stage stage is reported.
2269 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2270 if( OnStage() && !mOnStageSignalled )
2272 // Notification for external (CustomActor) derived classes
2273 OnStageConnectionExternal( mDepth );
2275 if( !mOnStageSignal.Empty() )
2277 Dali::Actor handle( this );
2278 mOnStageSignal.Emit( handle );
2281 // Guard against Remove during callbacks
2284 mOnStageSignalled = true; // signal required next time Actor is removed
2289 void Actor::DisconnectFromStage()
2291 // This container is used instead of walking the Actor hierachy.
2292 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2293 ActorContainer disconnectionList;
2295 // This stage is atomic i.e. not interrupted by user callbacks
2296 RecursiveDisconnectFromStage( disconnectionList );
2298 // Notify applications about the newly disconnected actors.
2299 const ActorIter endIter = disconnectionList.end();
2300 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2302 (*iter)->NotifyStageDisconnection();
2306 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2308 DALI_ASSERT_ALWAYS( OnStage() );
2310 // Recursively disconnect children
2313 ActorConstIter endIter = mChildren->end();
2314 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2316 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2320 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2321 disconnectionList.push_back( ActorPtr( this ) );
2323 // Notification for internal derived classes
2324 OnStageDisconnectionInternal();
2326 DisconnectFromSceneGraph();
2332 * This method is called by an actor or its parent, before a node removal message is sent.
2333 * This is recursive; the child calls DisconnectFromStage() for its children.
2335 void Actor::DisconnectFromSceneGraph()
2337 // Notification for Object::Observers
2338 OnSceneObjectRemove();
2341 void Actor::NotifyStageDisconnection()
2343 // Actors can be added (in a callback), before the off-stage state is reported.
2344 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2345 // only do this step if there is a stage, i.e. Core is not being shut down
2346 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2348 // Notification for external (CustomeActor) derived classes
2349 OnStageDisconnectionExternal();
2351 if( !mOffStageSignal.Empty() )
2353 Dali::Actor handle( this );
2354 mOffStageSignal.Emit( handle );
2357 // Guard against Add during callbacks
2360 mOnStageSignalled = false; // signal required next time Actor is added
2365 bool Actor::IsNodeConnected() const
2367 bool connected( false );
2369 if( OnStage() && ( NULL != mNode ) )
2371 if( IsRoot() || mNode->GetParent() )
2380 unsigned int Actor::GetDefaultPropertyCount() const
2382 return DEFAULT_PROPERTY_COUNT;
2385 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2387 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2389 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2391 indices.PushBack( i );
2395 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2397 if( index < DEFAULT_PROPERTY_COUNT )
2399 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2405 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2407 Property::Index index = Property::INVALID_INDEX;
2409 // Look for name in default properties
2410 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2412 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2413 if( 0 == name.compare( property->name ) )
2423 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2425 if( index < DEFAULT_PROPERTY_COUNT )
2427 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2433 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2435 if( index < DEFAULT_PROPERTY_COUNT )
2437 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2443 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2445 if( index < DEFAULT_PROPERTY_COUNT )
2447 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2453 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2455 if( index < DEFAULT_PROPERTY_COUNT )
2457 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2460 // index out of range...return Property::NONE
2461 return Property::NONE;
2464 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2468 case Dali::Actor::Property::PARENT_ORIGIN:
2470 Property::Type type = property.GetType();
2471 if( type == Property::VECTOR3 )
2473 SetParentOrigin( property.Get< Vector3 >() );
2475 else if ( type == Property::STRING )
2477 std::string parentOriginString;
2478 property.Get( parentOriginString );
2479 Vector3 parentOrigin;
2480 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2482 SetParentOrigin( parentOrigin );
2488 case Dali::Actor::Property::PARENT_ORIGIN_X:
2490 SetParentOriginX( property.Get< float >() );
2494 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2496 SetParentOriginY( property.Get< float >() );
2500 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2502 SetParentOriginZ( property.Get< float >() );
2506 case Dali::Actor::Property::ANCHOR_POINT:
2508 Property::Type type = property.GetType();
2509 if( type == Property::VECTOR3 )
2511 SetAnchorPoint( property.Get< Vector3 >() );
2513 else if ( type == Property::STRING )
2515 std::string anchorPointString;
2516 property.Get( anchorPointString );
2518 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2520 SetAnchorPoint( anchor );
2526 case Dali::Actor::Property::ANCHOR_POINT_X:
2528 SetAnchorPointX( property.Get< float >() );
2532 case Dali::Actor::Property::ANCHOR_POINT_Y:
2534 SetAnchorPointY( property.Get< float >() );
2538 case Dali::Actor::Property::ANCHOR_POINT_Z:
2540 SetAnchorPointZ( property.Get< float >() );
2544 case Dali::Actor::Property::SIZE:
2546 SetSize( property.Get< Vector3 >() );
2550 case Dali::Actor::Property::SIZE_WIDTH:
2552 SetWidth( property.Get< float >() );
2556 case Dali::Actor::Property::SIZE_HEIGHT:
2558 SetHeight( property.Get< float >() );
2562 case Dali::Actor::Property::SIZE_DEPTH:
2564 SetDepth( property.Get< float >() );
2568 case Dali::Actor::Property::POSITION:
2570 SetPosition( property.Get< Vector3 >() );
2574 case Dali::Actor::Property::POSITION_X:
2576 SetX( property.Get< float >() );
2580 case Dali::Actor::Property::POSITION_Y:
2582 SetY( property.Get< float >() );
2586 case Dali::Actor::Property::POSITION_Z:
2588 SetZ( property.Get< float >() );
2592 case Dali::Actor::Property::ORIENTATION:
2594 SetOrientation( property.Get< Quaternion >() );
2598 case Dali::Actor::Property::SCALE:
2600 SetScale( property.Get< Vector3 >() );
2604 case Dali::Actor::Property::SCALE_X:
2606 SetScaleX( property.Get< float >() );
2610 case Dali::Actor::Property::SCALE_Y:
2612 SetScaleY( property.Get< float >() );
2616 case Dali::Actor::Property::SCALE_Z:
2618 SetScaleZ( property.Get< float >() );
2622 case Dali::Actor::Property::VISIBLE:
2624 SetVisible( property.Get< bool >() );
2628 case Dali::Actor::Property::COLOR:
2630 SetColor( property.Get< Vector4 >() );
2634 case Dali::Actor::Property::COLOR_RED:
2636 SetColorRed( property.Get< float >() );
2640 case Dali::Actor::Property::COLOR_GREEN:
2642 SetColorGreen( property.Get< float >() );
2646 case Dali::Actor::Property::COLOR_BLUE:
2648 SetColorBlue( property.Get< float >() );
2652 case Dali::Actor::Property::COLOR_ALPHA:
2653 case Dali::DevelActor::Property::OPACITY:
2656 if( property.Get( value ) )
2658 SetOpacity( value );
2663 case Dali::Actor::Property::NAME:
2665 SetName( property.Get< std::string >() );
2669 case Dali::Actor::Property::SENSITIVE:
2671 SetSensitive( property.Get< bool >() );
2675 case Dali::Actor::Property::LEAVE_REQUIRED:
2677 SetLeaveRequired( property.Get< bool >() );
2681 case Dali::Actor::Property::INHERIT_POSITION:
2683 SetInheritPosition( property.Get< bool >() );
2687 case Dali::Actor::Property::INHERIT_ORIENTATION:
2689 SetInheritOrientation( property.Get< bool >() );
2693 case Dali::Actor::Property::INHERIT_SCALE:
2695 SetInheritScale( property.Get< bool >() );
2699 case Dali::Actor::Property::COLOR_MODE:
2701 ColorMode mode = mColorMode;
2702 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2704 SetColorMode( mode );
2709 case Dali::Actor::Property::POSITION_INHERITANCE:
2711 PositionInheritanceMode mode = mPositionInheritanceMode;
2712 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2714 SetPositionInheritanceMode( mode );
2719 case Dali::Actor::Property::DRAW_MODE:
2721 DrawMode::Type mode = mDrawMode;
2722 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2724 SetDrawMode( mode );
2729 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2731 SetSizeModeFactor( property.Get< Vector3 >() );
2735 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2737 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2738 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2740 SetResizePolicy( type, Dimension::WIDTH );
2745 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2747 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2748 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2750 SetResizePolicy( type, Dimension::HEIGHT );
2755 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2757 SizeScalePolicy::Type type;
2758 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2760 SetSizeScalePolicy( type );
2765 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2767 if( property.Get< bool >() )
2769 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2774 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2776 if( property.Get< bool >() )
2778 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2783 case Dali::Actor::Property::PADDING:
2785 Vector4 padding = property.Get< Vector4 >();
2786 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2787 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2791 case Dali::Actor::Property::MINIMUM_SIZE:
2793 Vector2 size = property.Get< Vector2 >();
2794 SetMinimumSize( size.x, Dimension::WIDTH );
2795 SetMinimumSize( size.y, Dimension::HEIGHT );
2799 case Dali::Actor::Property::MAXIMUM_SIZE:
2801 Vector2 size = property.Get< Vector2 >();
2802 SetMaximumSize( size.x, Dimension::WIDTH );
2803 SetMaximumSize( size.y, Dimension::HEIGHT );
2807 case Dali::DevelActor::Property::SIBLING_ORDER:
2811 if( property.Get( value ) )
2813 if( static_cast<unsigned int>(value) != mSiblingOrder )
2815 SetSiblingOrder( value );
2821 case Dali::Actor::Property::CLIPPING_MODE:
2823 ClippingMode::Type convertedValue = mClippingMode;
2824 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2826 mClippingMode = convertedValue;
2829 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2835 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2838 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2840 mPositionUsesAnchorPoint = value;
2843 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2851 // this can happen in the case of a non-animatable default property so just do nothing
2857 // TODO: This method needs to be removed
2858 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2860 switch( entry.GetType() )
2862 case Property::BOOLEAN:
2864 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2865 DALI_ASSERT_DEBUG( NULL != property );
2867 // property is being used in a separate thread; queue a message to set the property
2868 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2873 case Property::INTEGER:
2875 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2876 DALI_ASSERT_DEBUG( NULL != property );
2878 // property is being used in a separate thread; queue a message to set the property
2879 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2884 case Property::FLOAT:
2886 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2887 DALI_ASSERT_DEBUG( NULL != property );
2889 // property is being used in a separate thread; queue a message to set the property
2890 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2895 case Property::VECTOR2:
2897 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2898 DALI_ASSERT_DEBUG( NULL != property );
2900 // property is being used in a separate thread; queue a message to set the property
2901 if(entry.componentIndex == 0)
2903 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2905 else if(entry.componentIndex == 1)
2907 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2911 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2917 case Property::VECTOR3:
2919 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2920 DALI_ASSERT_DEBUG( NULL != property );
2922 // property is being used in a separate thread; queue a message to set the property
2923 if(entry.componentIndex == 0)
2925 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2927 else if(entry.componentIndex == 1)
2929 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2931 else if(entry.componentIndex == 2)
2933 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2937 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2943 case Property::VECTOR4:
2945 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2946 DALI_ASSERT_DEBUG( NULL != property );
2948 // property is being used in a separate thread; queue a message to set the property
2949 if(entry.componentIndex == 0)
2951 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2953 else if(entry.componentIndex == 1)
2955 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2957 else if(entry.componentIndex == 2)
2959 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2961 else if(entry.componentIndex == 3)
2963 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2967 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2973 case Property::ROTATION:
2975 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2976 DALI_ASSERT_DEBUG( NULL != property );
2978 // property is being used in a separate thread; queue a message to set the property
2979 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2984 case Property::MATRIX:
2986 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2987 DALI_ASSERT_DEBUG( NULL != property );
2989 // property is being used in a separate thread; queue a message to set the property
2990 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2995 case Property::MATRIX3:
2997 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2998 DALI_ASSERT_DEBUG( NULL != property );
3000 // property is being used in a separate thread; queue a message to set the property
3001 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3008 // nothing to do for other types
3013 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3015 Property::Value value;
3017 if( index >= DEFAULT_PROPERTY_COUNT )
3024 case Dali::Actor::Property::PARENT_ORIGIN:
3026 value = GetCurrentParentOrigin();
3030 case Dali::Actor::Property::PARENT_ORIGIN_X:
3032 value = GetCurrentParentOrigin().x;
3036 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3038 value = GetCurrentParentOrigin().y;
3042 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3044 value = GetCurrentParentOrigin().z;
3048 case Dali::Actor::Property::ANCHOR_POINT:
3050 value = GetCurrentAnchorPoint();
3054 case Dali::Actor::Property::ANCHOR_POINT_X:
3056 value = GetCurrentAnchorPoint().x;
3060 case Dali::Actor::Property::ANCHOR_POINT_Y:
3062 value = GetCurrentAnchorPoint().y;
3066 case Dali::Actor::Property::ANCHOR_POINT_Z:
3068 value = GetCurrentAnchorPoint().z;
3072 case Dali::Actor::Property::SIZE:
3074 Vector3 size = GetTargetSize();
3076 // Should return preferred size if size is fixed as set by SetSize
3077 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3079 size.width = GetPreferredSize().width;
3081 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3083 size.height = GetPreferredSize().height;
3091 case Dali::Actor::Property::SIZE_WIDTH:
3093 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3095 // Should return preferred size if size is fixed as set by SetSize
3096 value = GetPreferredSize().width;
3100 value = GetTargetSize().width;
3105 case Dali::Actor::Property::SIZE_HEIGHT:
3107 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3109 // Should return preferred size if size is fixed as set by SetSize
3110 value = GetPreferredSize().height;
3114 value = GetTargetSize().height;
3119 case Dali::Actor::Property::SIZE_DEPTH:
3121 value = GetTargetSize().depth;
3125 case Dali::Actor::Property::POSITION:
3127 value = GetTargetPosition();
3131 case Dali::Actor::Property::POSITION_X:
3133 value = GetTargetPosition().x;
3137 case Dali::Actor::Property::POSITION_Y:
3139 value = GetTargetPosition().y;
3143 case Dali::Actor::Property::POSITION_Z:
3145 value = GetTargetPosition().z;
3149 case Dali::Actor::Property::WORLD_POSITION:
3151 value = GetCurrentWorldPosition();
3155 case Dali::Actor::Property::WORLD_POSITION_X:
3157 value = GetCurrentWorldPosition().x;
3161 case Dali::Actor::Property::WORLD_POSITION_Y:
3163 value = GetCurrentWorldPosition().y;
3167 case Dali::Actor::Property::WORLD_POSITION_Z:
3169 value = GetCurrentWorldPosition().z;
3173 case Dali::Actor::Property::ORIENTATION:
3175 value = GetCurrentOrientation();
3179 case Dali::Actor::Property::WORLD_ORIENTATION:
3181 value = GetCurrentWorldOrientation();
3185 case Dali::Actor::Property::SCALE:
3187 value = GetCurrentScale();
3191 case Dali::Actor::Property::SCALE_X:
3193 value = GetCurrentScale().x;
3197 case Dali::Actor::Property::SCALE_Y:
3199 value = GetCurrentScale().y;
3203 case Dali::Actor::Property::SCALE_Z:
3205 value = GetCurrentScale().z;
3209 case Dali::Actor::Property::WORLD_SCALE:
3211 value = GetCurrentWorldScale();
3215 case Dali::Actor::Property::VISIBLE:
3217 value = IsVisible();
3221 case Dali::Actor::Property::COLOR:
3223 value = GetCurrentColor();
3227 case Dali::Actor::Property::COLOR_RED:
3229 value = GetCurrentColor().r;
3233 case Dali::Actor::Property::COLOR_GREEN:
3235 value = GetCurrentColor().g;
3239 case Dali::Actor::Property::COLOR_BLUE:
3241 value = GetCurrentColor().b;
3245 case Dali::Actor::Property::COLOR_ALPHA:
3246 case Dali::DevelActor::Property::OPACITY:
3248 value = GetCurrentColor().a;
3252 case Dali::Actor::Property::WORLD_COLOR:
3254 value = GetCurrentWorldColor();
3258 case Dali::Actor::Property::WORLD_MATRIX:
3260 value = GetCurrentWorldMatrix();
3264 case Dali::Actor::Property::NAME:
3270 case Dali::Actor::Property::SENSITIVE:
3272 value = IsSensitive();
3276 case Dali::Actor::Property::LEAVE_REQUIRED:
3278 value = GetLeaveRequired();
3282 case Dali::Actor::Property::INHERIT_POSITION:
3284 value = IsPositionInherited();
3288 case Dali::Actor::Property::INHERIT_ORIENTATION:
3290 value = IsOrientationInherited();
3294 case Dali::Actor::Property::INHERIT_SCALE:
3296 value = IsScaleInherited();
3300 case Dali::Actor::Property::COLOR_MODE:
3302 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3306 case Dali::Actor::Property::POSITION_INHERITANCE:
3308 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3312 case Dali::Actor::Property::DRAW_MODE:
3314 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3318 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3320 value = GetSizeModeFactor();
3324 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3326 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3330 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3332 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3336 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3338 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3342 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3344 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3348 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3350 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3354 case Dali::Actor::Property::PADDING:
3356 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3357 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3358 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3362 case Dali::Actor::Property::MINIMUM_SIZE:
3364 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3368 case Dali::Actor::Property::MAXIMUM_SIZE:
3370 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3374 case Dali::DevelActor::Property::SIBLING_ORDER:
3376 value = static_cast<int>(mSiblingOrder);
3380 case Dali::Actor::Property::CLIPPING_MODE:
3382 value = mClippingMode;
3386 case Dali::DevelActor::Property::SCREEN_POSITION:
3388 value = GetCurrentScreenPosition();
3392 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3394 value = mPositionUsesAnchorPoint;
3402 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3407 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3409 // This method should only return an object connected to the scene-graph
3410 return OnStage() ? mNode : NULL;
3413 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3415 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3417 const PropertyBase* property( NULL );
3419 // This method should only return a property of an object connected to the scene-graph
3425 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3427 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3428 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3430 property = animatable->GetSceneGraphProperty();
3432 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3433 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3435 CustomPropertyMetadata* custom = FindCustomProperty( index );
3436 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3438 property = custom->GetSceneGraphProperty();
3440 else if( NULL != mNode )
3444 case Dali::Actor::Property::SIZE:
3445 property = &mNode->mSize;
3448 case Dali::Actor::Property::SIZE_WIDTH:
3449 property = &mNode->mSize;
3452 case Dali::Actor::Property::SIZE_HEIGHT:
3453 property = &mNode->mSize;
3456 case Dali::Actor::Property::SIZE_DEPTH:
3457 property = &mNode->mSize;
3460 case Dali::Actor::Property::POSITION:
3461 property = &mNode->mPosition;
3464 case Dali::Actor::Property::POSITION_X:
3465 property = &mNode->mPosition;
3468 case Dali::Actor::Property::POSITION_Y:
3469 property = &mNode->mPosition;
3472 case Dali::Actor::Property::POSITION_Z:
3473 property = &mNode->mPosition;
3476 case Dali::Actor::Property::ORIENTATION:
3477 property = &mNode->mOrientation;
3480 case Dali::Actor::Property::SCALE:
3481 property = &mNode->mScale;
3484 case Dali::Actor::Property::SCALE_X:
3485 property = &mNode->mScale;
3488 case Dali::Actor::Property::SCALE_Y:
3489 property = &mNode->mScale;
3492 case Dali::Actor::Property::SCALE_Z:
3493 property = &mNode->mScale;
3496 case Dali::Actor::Property::VISIBLE:
3497 property = &mNode->mVisible;
3500 case Dali::Actor::Property::COLOR:
3501 property = &mNode->mColor;
3504 case Dali::Actor::Property::COLOR_RED:
3505 property = &mNode->mColor;
3508 case Dali::Actor::Property::COLOR_GREEN:
3509 property = &mNode->mColor;
3512 case Dali::Actor::Property::COLOR_BLUE:
3513 property = &mNode->mColor;
3516 case Dali::Actor::Property::COLOR_ALPHA:
3517 case Dali::DevelActor::Property::OPACITY:
3518 property = &mNode->mColor;
3529 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3531 const PropertyInputImpl* property( NULL );
3533 // This method should only return a property of an object connected to the scene-graph
3539 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3541 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3542 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3544 property = animatable->GetSceneGraphProperty();
3546 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3547 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3549 CustomPropertyMetadata* custom = FindCustomProperty( index );
3550 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3551 property = custom->GetSceneGraphProperty();
3553 else if( NULL != mNode )
3557 case Dali::Actor::Property::PARENT_ORIGIN:
3558 property = &mNode->mParentOrigin;
3561 case Dali::Actor::Property::PARENT_ORIGIN_X:
3562 property = &mNode->mParentOrigin;
3565 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3566 property = &mNode->mParentOrigin;
3569 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3570 property = &mNode->mParentOrigin;
3573 case Dali::Actor::Property::ANCHOR_POINT:
3574 property = &mNode->mAnchorPoint;
3577 case Dali::Actor::Property::ANCHOR_POINT_X:
3578 property = &mNode->mAnchorPoint;
3581 case Dali::Actor::Property::ANCHOR_POINT_Y:
3582 property = &mNode->mAnchorPoint;
3585 case Dali::Actor::Property::ANCHOR_POINT_Z:
3586 property = &mNode->mAnchorPoint;
3589 case Dali::Actor::Property::SIZE:
3590 property = &mNode->mSize;
3593 case Dali::Actor::Property::SIZE_WIDTH:
3594 property = &mNode->mSize;
3597 case Dali::Actor::Property::SIZE_HEIGHT:
3598 property = &mNode->mSize;
3601 case Dali::Actor::Property::SIZE_DEPTH:
3602 property = &mNode->mSize;
3605 case Dali::Actor::Property::POSITION:
3606 property = &mNode->mPosition;
3609 case Dali::Actor::Property::POSITION_X:
3610 property = &mNode->mPosition;
3613 case Dali::Actor::Property::POSITION_Y:
3614 property = &mNode->mPosition;
3617 case Dali::Actor::Property::POSITION_Z:
3618 property = &mNode->mPosition;
3621 case Dali::Actor::Property::WORLD_POSITION:
3622 property = &mNode->mWorldPosition;
3625 case Dali::Actor::Property::WORLD_POSITION_X:
3626 property = &mNode->mWorldPosition;
3629 case Dali::Actor::Property::WORLD_POSITION_Y:
3630 property = &mNode->mWorldPosition;
3633 case Dali::Actor::Property::WORLD_POSITION_Z:
3634 property = &mNode->mWorldPosition;
3637 case Dali::Actor::Property::ORIENTATION:
3638 property = &mNode->mOrientation;
3641 case Dali::Actor::Property::WORLD_ORIENTATION:
3642 property = &mNode->mWorldOrientation;
3645 case Dali::Actor::Property::SCALE:
3646 property = &mNode->mScale;
3649 case Dali::Actor::Property::SCALE_X:
3650 property = &mNode->mScale;
3653 case Dali::Actor::Property::SCALE_Y:
3654 property = &mNode->mScale;
3657 case Dali::Actor::Property::SCALE_Z:
3658 property = &mNode->mScale;
3661 case Dali::Actor::Property::WORLD_SCALE:
3662 property = &mNode->mWorldScale;
3665 case Dali::Actor::Property::VISIBLE:
3666 property = &mNode->mVisible;
3669 case Dali::Actor::Property::COLOR:
3670 property = &mNode->mColor;
3673 case Dali::Actor::Property::COLOR_RED:
3674 property = &mNode->mColor;
3677 case Dali::Actor::Property::COLOR_GREEN:
3678 property = &mNode->mColor;
3681 case Dali::Actor::Property::COLOR_BLUE:
3682 property = &mNode->mColor;
3685 case Dali::Actor::Property::COLOR_ALPHA:
3686 case Dali::DevelActor::Property::OPACITY:
3688 property = &mNode->mColor;
3692 case Dali::Actor::Property::WORLD_COLOR:
3693 property = &mNode->mWorldColor;
3696 case Dali::Actor::Property::WORLD_MATRIX:
3697 property = &mNode->mWorldMatrix;
3708 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3710 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3712 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3714 // check whether the animatable property is registered already, if not then register one.
3715 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3716 if( animatableProperty )
3718 componentIndex = animatableProperty->componentIndex;
3725 case Dali::Actor::Property::PARENT_ORIGIN_X:
3726 case Dali::Actor::Property::ANCHOR_POINT_X:
3727 case Dali::Actor::Property::SIZE_WIDTH:
3728 case Dali::Actor::Property::POSITION_X:
3729 case Dali::Actor::Property::WORLD_POSITION_X:
3730 case Dali::Actor::Property::SCALE_X:
3731 case Dali::Actor::Property::COLOR_RED:
3737 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3738 case Dali::Actor::Property::ANCHOR_POINT_Y:
3739 case Dali::Actor::Property::SIZE_HEIGHT:
3740 case Dali::Actor::Property::POSITION_Y:
3741 case Dali::Actor::Property::WORLD_POSITION_Y:
3742 case Dali::Actor::Property::SCALE_Y:
3743 case Dali::Actor::Property::COLOR_GREEN:
3749 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3750 case Dali::Actor::Property::ANCHOR_POINT_Z:
3751 case Dali::Actor::Property::SIZE_DEPTH:
3752 case Dali::Actor::Property::POSITION_Z:
3753 case Dali::Actor::Property::WORLD_POSITION_Z:
3754 case Dali::Actor::Property::SCALE_Z:
3755 case Dali::Actor::Property::COLOR_BLUE:
3761 case Dali::Actor::Property::COLOR_ALPHA:
3762 case Dali::DevelActor::Property::OPACITY:
3776 return componentIndex;
3779 void Actor::SetParent( Actor* parent )
3783 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3787 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3790 // Instruct each actor to create a corresponding node in the scene graph
3791 ConnectToStage( parent->GetHierarchyDepth() );
3794 // Resolve the name and index for the child properties if any
3795 ResolveChildProperties();
3797 else // parent being set to NULL
3799 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3803 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3806 DALI_ASSERT_ALWAYS( mNode != NULL );
3810 // Disconnect the Node & its children from the scene-graph.
3811 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3814 // Instruct each actor to discard pointers to the scene-graph
3815 DisconnectFromStage();
3820 SceneGraph::Node* Actor::CreateNode() const
3825 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3828 Actor* actor = dynamic_cast< Actor* >( object );
3832 if( 0 == actionName.compare( ACTION_SHOW ) )
3834 actor->SetVisible( true );
3837 else if( 0 == actionName.compare( ACTION_HIDE ) )
3839 actor->SetVisible( false );
3847 void Actor::EnsureRelayoutData()
3849 // Assign relayout data.
3850 if( !mRelayoutData )
3852 mRelayoutData = new RelayoutData();
3856 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3858 // Check if actor is dependent on parent
3859 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3861 if( ( dimension & ( 1 << i ) ) )
3863 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3864 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3874 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3876 // Check if actor is dependent on children
3877 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3879 if( ( dimension & ( 1 << i ) ) )
3881 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3882 switch( resizePolicy )
3884 case ResizePolicy::FIT_TO_CHILDREN:
3885 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3901 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3903 return Actor::RelayoutDependentOnChildren( dimension );
3906 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3908 // Check each possible dimension and see if it is dependent on the input one
3909 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3911 if( dimension & ( 1 << i ) )
3913 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3920 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3922 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3924 if( dimension & ( 1 << i ) )
3926 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3931 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3933 // If more than one dimension is requested, just return the first one found
3934 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3936 if( ( dimension & ( 1 << i ) ) )
3938 return mRelayoutData->negotiatedDimensions[ i ];
3942 return 0.0f; // Default
3945 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3947 EnsureRelayoutData();
3949 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3951 if( dimension & ( 1 << i ) )
3953 mRelayoutData->dimensionPadding[ i ] = padding;
3958 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3960 if ( mRelayoutData )
3962 // If more than one dimension is requested, just return the first one found
3963 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3965 if( ( dimension & ( 1 << i ) ) )
3967 return mRelayoutData->dimensionPadding[ i ];
3972 return GetDefaultDimensionPadding();
3975 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3977 EnsureRelayoutData();
3979 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3981 if( dimension & ( 1 << i ) )
3983 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3988 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3990 if ( mRelayoutData )
3992 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3994 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4004 float Actor::GetHeightForWidthBase( float width )
4006 float height = 0.0f;
4008 const Vector3 naturalSize = GetNaturalSize();
4009 if( naturalSize.width > 0.0f )
4011 height = naturalSize.height * width / naturalSize.width;
4013 else // we treat 0 as 1:1 aspect ratio
4021 float Actor::GetWidthForHeightBase( float height )
4025 const Vector3 naturalSize = GetNaturalSize();
4026 if( naturalSize.height > 0.0f )
4028 width = naturalSize.width * height / naturalSize.height;
4030 else // we treat 0 as 1:1 aspect ratio
4038 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4040 // Fill to parent, taking size mode factor into account
4041 switch( child.GetResizePolicy( dimension ) )
4043 case ResizePolicy::FILL_TO_PARENT:
4045 return GetLatestSize( dimension );
4048 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4050 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4053 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4055 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4060 return GetLatestSize( dimension );
4065 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4067 // Can be overridden in derived class
4068 return CalculateChildSizeBase( child, dimension );
4071 float Actor::GetHeightForWidth( float width )
4073 // Can be overridden in derived class
4074 return GetHeightForWidthBase( width );
4077 float Actor::GetWidthForHeight( float height )
4079 // Can be overridden in derived class
4080 return GetWidthForHeightBase( height );
4083 float Actor::GetLatestSize( Dimension::Type dimension ) const
4085 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4088 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4090 Vector2 padding = GetPadding( dimension );
4092 return GetLatestSize( dimension ) + padding.x + padding.y;
4095 float Actor::NegotiateFromParent( Dimension::Type dimension )
4097 Actor* parent = GetParent();
4100 Vector2 padding( GetPadding( dimension ) );
4101 Vector2 parentPadding( parent->GetPadding( dimension ) );
4102 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4108 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4110 float maxDimensionPoint = 0.0f;
4112 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4114 ActorPtr child = GetChildAt( i );
4116 if( !child->RelayoutDependentOnParent( dimension ) )
4118 // Calculate the min and max points that the children range across
4119 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4120 float dimensionSize = child->GetRelayoutSize( dimension );
4121 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4125 return maxDimensionPoint;
4128 float Actor::GetSize( Dimension::Type dimension ) const
4130 return GetDimensionValue( GetTargetSize(), dimension );
4133 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4135 return GetDimensionValue( GetNaturalSize(), dimension );
4138 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4140 switch( GetResizePolicy( dimension ) )
4142 case ResizePolicy::USE_NATURAL_SIZE:
4144 return GetNaturalSize( dimension );
4147 case ResizePolicy::FIXED:
4149 return GetDimensionValue( GetPreferredSize(), dimension );
4152 case ResizePolicy::USE_ASSIGNED_SIZE:
4154 return GetDimensionValue( maximumSize, dimension );
4157 case ResizePolicy::FILL_TO_PARENT:
4158 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4159 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4161 return NegotiateFromParent( dimension );
4164 case ResizePolicy::FIT_TO_CHILDREN:
4166 return NegotiateFromChildren( dimension );
4169 case ResizePolicy::DIMENSION_DEPENDENCY:
4171 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4174 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4176 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4179 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4181 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4193 return 0.0f; // Default
4196 float Actor::ClampDimension( float size, Dimension::Type dimension )
4198 const float minSize = GetMinimumSize( dimension );
4199 const float maxSize = GetMaximumSize( dimension );
4201 return std::max( minSize, std::min( size, maxSize ) );
4204 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4206 // Check if it needs to be negotiated
4207 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4209 // Check that we havn't gotten into an infinite loop
4210 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4211 bool recursionFound = false;
4212 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4214 if( *it == searchActor )
4216 recursionFound = true;
4221 if( !recursionFound )
4223 // Record the path that we have taken
4224 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4226 // Dimension dependency check
4227 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4229 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4231 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4233 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4237 // Parent dependency check
4238 Actor* parent = GetParent();
4239 if( parent && RelayoutDependentOnParent( dimension ) )
4241 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4244 // Children dependency check
4245 if( RelayoutDependentOnChildren( dimension ) )
4247 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4249 ActorPtr child = GetChildAt( i );
4251 // Only relayout child first if it is not dependent on this actor
4252 if( !child->RelayoutDependentOnParent( dimension ) )
4254 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4259 // For deriving classes
4260 OnCalculateRelayoutSize( dimension );
4262 // All dependencies checked, calculate the size and set negotiated flag
4263 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4265 SetNegotiatedDimension( newSize, dimension );
4266 SetLayoutNegotiated( true, dimension );
4268 // For deriving classes
4269 OnLayoutNegotiated( newSize, dimension );
4271 // This actor has been successfully processed, pop it off the recursion stack
4272 recursionStack.pop_back();
4276 // TODO: Break infinite loop
4277 SetLayoutNegotiated( true, dimension );
4282 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4284 // Negotiate all dimensions that require it
4285 ActorDimensionStack recursionStack;
4287 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4289 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4292 NegotiateDimension( dimension, allocatedSize, recursionStack );
4296 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4298 switch( mRelayoutData->sizeSetPolicy )
4300 case SizeScalePolicy::USE_SIZE_SET:
4305 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4307 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4308 const Vector3 naturalSize = GetNaturalSize();
4309 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4311 const float sizeRatio = size.width / size.height;
4312 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4314 if( naturalSizeRatio < sizeRatio )
4316 return Vector2( naturalSizeRatio * size.height, size.height );
4318 else if( naturalSizeRatio > sizeRatio )
4320 return Vector2( size.width, size.width / naturalSizeRatio );
4331 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4333 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4334 const Vector3 naturalSize = GetNaturalSize();
4335 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4337 const float sizeRatio = size.width / size.height;
4338 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4340 if( naturalSizeRatio < sizeRatio )
4342 return Vector2( size.width, size.width / naturalSizeRatio );
4344 else if( naturalSizeRatio > sizeRatio )
4346 return Vector2( naturalSizeRatio * size.height, size.height );
4365 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4367 // Do the set actor size
4368 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4370 // Adjust for size set policy
4371 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4373 // Lock the flag to stop recursive relayouts on set size
4374 mRelayoutData->insideRelayout = true;
4375 SetSize( negotiatedSize );
4376 mRelayoutData->insideRelayout = false;
4378 // Clear flags for all dimensions
4379 SetLayoutDirty( false );
4381 // Give deriving classes a chance to respond
4382 OnRelayout( negotiatedSize, container );
4384 if( !mOnRelayoutSignal.Empty() )
4386 Dali::Actor handle( this );
4387 mOnRelayoutSignal.Emit( handle );
4391 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4393 // Force a size negotiation for actors that has assigned size during relayout
4394 // This is required as otherwise the flags that force a relayout will not
4395 // necessarilly be set. This will occur if the actor has already been laid out.
4396 // The dirty flags are then cleared. Then if the actor is added back into the
4397 // relayout container afterwards, the dirty flags would still be clear...
4398 // causing a relayout to be skipped. Here we force any actors added to the
4399 // container to be relayed out.
4400 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4402 SetLayoutNegotiated(false, Dimension::WIDTH);
4404 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4406 SetLayoutNegotiated(false, Dimension::HEIGHT);
4409 // Do the negotiation
4410 NegotiateDimensions( allocatedSize );
4412 // Set the actor size
4413 SetNegotiatedSize( container );
4415 // Negotiate down to children
4416 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4418 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4420 ActorPtr child = GetChildAt( i );
4422 // Forces children that have already been laid out to be relayed out
4423 // if they have assigned size during relayout.
4424 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4426 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4427 child->SetLayoutDirty(true, Dimension::WIDTH);
4429 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4431 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4432 child->SetLayoutDirty(true, Dimension::HEIGHT);
4435 // Only relayout if required
4436 if( child->RelayoutRequired() )
4438 container.Add( Dali::Actor( child.Get() ), newBounds );
4443 void Actor::RelayoutRequest( Dimension::Type dimension )
4445 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4446 if( relayoutController )
4448 Dali::Actor self( this );
4449 relayoutController->RequestRelayout( self, dimension );
4453 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4457 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4461 void Actor::SetPreferredSize( const Vector2& size )
4463 EnsureRelayoutData();
4465 if( size.width > 0.0f )
4467 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4470 if( size.height > 0.0f )
4472 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4475 mRelayoutData->preferredSize = size;
4480 Vector2 Actor::GetPreferredSize() const
4482 if ( mRelayoutData )
4484 return Vector2( mRelayoutData->preferredSize );
4487 return GetDefaultPreferredSize();
4490 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4492 EnsureRelayoutData();
4494 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4496 if( dimension & ( 1 << i ) )
4498 mRelayoutData->minimumSize[ i ] = size;
4505 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4507 if ( mRelayoutData )
4509 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4511 if( dimension & ( 1 << i ) )
4513 return mRelayoutData->minimumSize[ i ];
4518 return 0.0f; // Default
4521 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4523 EnsureRelayoutData();
4525 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4527 if( dimension & ( 1 << i ) )
4529 mRelayoutData->maximumSize[ i ] = size;
4536 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4538 if ( mRelayoutData )
4540 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4542 if( dimension & ( 1 << i ) )
4544 return mRelayoutData->maximumSize[ i ];
4549 return FLT_MAX; // Default
4552 Object* Actor::GetParentObject() const
4557 void Actor::SetSiblingOrder( unsigned int order )
4559 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4562 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4566 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4568 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4569 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4571 // Start at index 0, while index <= highest order
4572 // Find next index higher than 0
4573 // if nextHigher > index+1
4574 // set all nextHigher orders to index+1
4576 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4578 ActorIter end = siblings.end();
4579 int highestOrder = 0;
4580 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4582 ActorPtr sibling = (*iter);
4583 int siblingOrder = sibling->mSiblingOrder;
4584 highestOrder = std::max( highestOrder, siblingOrder );
4587 for ( int index = 0; index <= highestOrder; index++ )
4589 int nextHighest = -1;
4591 // Find Next highest
4592 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4594 ActorPtr sibling = (*iter);
4595 int siblingOrder = sibling->mSiblingOrder;
4597 if ( siblingOrder > index )
4599 if ( nextHighest == -1 )
4601 nextHighest = siblingOrder;
4603 nextHighest = std::min( nextHighest, siblingOrder );
4607 // Check if a gap exists between indexes, if so set next index to consecutive number
4608 if ( ( nextHighest - index ) > 1 )
4610 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4612 ActorPtr sibling = (*iter);
4613 int siblingOrder = sibling->mSiblingOrder;
4614 if ( siblingOrder == nextHighest )
4616 sibling->mSiblingOrder = index + 1;
4617 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4619 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4620 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4622 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4629 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4631 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4632 bool defragmentationRequired( false );
4633 ActorIter end = siblings.end();
4634 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4636 // Move actors at nearest order and above up by 1
4637 ActorPtr sibling = (*iter);
4638 if ( sibling != this )
4640 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4641 // be incremented by 1.
4642 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4644 sibling->mSiblingOrder++;
4645 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4647 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4648 // can re-order all sibling orders.
4649 defragmentationRequired = true;
4651 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4655 return defragmentationRequired;
4661 1) Check if already at top and nothing to be done.
4662 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4663 order can be positioned above it due to insertion order of actors.
4664 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4665 3) a) There may be other levels above this target level
4666 b) Increment all sibling levels at the level above nearest(target)
4667 c) Now have a vacant sibling level
4668 4) Set this actor's sibling level to nearest +1 as now vacated.
4670 Note May not just be sibling level + 1 as could be empty levels in-between
4675 ActorC ( sibling level 4 )
4676 ActorB ( sibling level 3 )
4677 ActorA ( sibling level 1 )
4679 2 ) ACTION: Raise A above B
4680 a) Find nearest level above A = Level 3
4681 b) Increment levels above Level 3
4683 ActorC ( sibling level 5 )
4684 ActorB ( sibling level 3 ) NEAREST
4685 ActorA ( sibling level 1 )
4687 3 ) Set Actor A sibling level to nearest +1 as vacant
4689 ActorC ( sibling level 5 )
4690 ActorA ( sibling level 4 )
4691 ActorB ( sibling level 3 )
4693 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4694 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4695 remove any empty sibling order gaps and start from sibling level 0 again.
4696 If the number of actors reaches this maximum and all using exclusive sibling order values then
4697 defragmention will stop and new sibling orders will be set to same max value.
4701 int nearestLevel = mSiblingOrder;
4702 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4703 bool defragmentationRequired( false );
4705 ActorContainer* siblings = mParent->mChildren;
4707 // Find Nearest sibling level above this actor
4708 ActorIter end = siblings->end();
4709 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4711 ActorPtr sibling = (*iter);
4712 if ( sibling != this )
4714 int order = GetSiblingOrder( sibling );
4716 if ( ( order >= mSiblingOrder ) )
4718 int distanceToNextLevel = order - mSiblingOrder;
4719 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4721 nearestLevel = order;
4722 shortestDistanceToNextLevel = distanceToNextLevel;
4728 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4730 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4731 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4732 // Move current actor to newly vacated order level
4733 SetSiblingOrder( mSiblingOrder );
4734 if ( defragmentationRequired )
4736 DefragmentSiblingIndexes( *siblings );
4739 SetSiblingOrder( mSiblingOrder );
4743 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4750 1) Check if actor already at bottom and if nothing needs to be done
4751 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4752 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4753 2) Find nearest sibling level below, this Actor needs to be below it
4754 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4755 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4756 c) Set this actor's sibling level to this newly vacated level.
4757 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4758 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4759 remove any empty sibling order gaps and start from sibling level 0 again.
4760 If the number of actors reaches this maximum and all using exclusive sibling order values then
4761 defragmention will stop and new sibling orders will be set to same max value.
4766 // 1) Find nearest level below
4767 int nearestLevel = mSiblingOrder;
4768 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4770 ActorContainer* siblings = mParent->mChildren;
4772 ActorIter end = siblings->end();
4773 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4775 ActorPtr sibling = (*iter);
4776 if ( sibling != this )
4778 int order = GetSiblingOrder( sibling );
4780 if ( order <= mSiblingOrder )
4782 int distanceToNextLevel = mSiblingOrder - order;
4783 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4785 nearestLevel = order;
4786 shortestDistanceToNextLevel = distanceToNextLevel;
4792 bool defragmentationRequired ( false );
4794 // 2) If actor already not at bottom, raise all actors at required level and above
4795 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4797 mSiblingOrder = nearestLevel;
4798 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4799 // Move current actor to newly vacated order
4800 SetSiblingOrder( mSiblingOrder );
4801 if ( defragmentationRequired )
4803 DefragmentSiblingIndexes( *siblings );
4809 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4813 void Actor::RaiseToTop()
4816 1 ) Find highest sibling order actor
4817 2 ) If highest sibling level not itself then set sibling order to that + 1
4818 3 ) highest sibling order can be same as itself so need to increment over that
4819 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4820 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4821 remove any empty sibling order gaps and start from sibling level 0 again.
4822 If the number of actors reaches this maximum and all using exclusive sibling order values then
4823 defragmention will stop and new sibling orders will be set to same max value.
4830 ActorContainer* siblings = mParent->mChildren;
4832 ActorIter end = siblings->end();
4833 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4835 ActorPtr sibling = (*iter);
4836 if ( sibling != this )
4838 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4842 bool defragmentationRequired( false );
4844 if ( maxOrder >= mSiblingOrder )
4846 mSiblingOrder = maxOrder + 1;
4847 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4849 defragmentationRequired = true;
4853 SetSiblingOrder( mSiblingOrder );
4855 if ( defragmentationRequired )
4857 DefragmentSiblingIndexes( *siblings );
4862 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4866 void Actor::LowerToBottom()
4869 See Actor::LowerToBottom()
4871 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4872 2 ) a ) Check if the bottom position 0 is vacant.
4873 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4874 c ) 0 sibling position is vacant.
4875 3 ) Set this actor to vacant sibling order 0;
4876 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4877 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4878 remove any empty sibling order gaps and start from sibling level 0 again.
4879 If the number of actors reaches this maximum and all using exclusive sibling order values then
4880 defragmention will stop and new sibling orders will be set to same max value.
4885 bool defragmentationRequired( false );
4886 bool orderZeroFree ( true );
4888 ActorContainer* siblings = mParent->mChildren;
4890 bool actorAtLowestOrder = true;
4891 ActorIter end = siblings->end();
4892 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4894 ActorPtr sibling = (*iter);
4895 if ( sibling != this )
4897 int siblingOrder = GetSiblingOrder( sibling );
4898 if ( siblingOrder <= mSiblingOrder )
4900 actorAtLowestOrder = false;
4903 if ( siblingOrder == 0 )
4905 orderZeroFree = false;
4910 if ( ! actorAtLowestOrder )
4912 if ( ! orderZeroFree )
4914 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4917 SetSiblingOrder( mSiblingOrder );
4919 if ( defragmentationRequired )
4921 DefragmentSiblingIndexes( *siblings );
4927 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4931 void Actor::RaiseAbove( Internal::Actor& target )
4934 1 ) a) Find target actor's sibling order
4935 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4936 needs to be above it or the insertion order will determine which is drawn on top.
4937 2 ) Shift up by 1 all sibling order greater than target sibling order
4938 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4939 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4940 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4941 remove any empty sibling order gaps and start from sibling level 0 again.
4942 If the number of actors reaches this maximum and all using exclusive sibling order values then
4943 defragmention will stop and new sibling orders will be set to same max value.
4948 if ( ValidateActors( *this, target ) )
4950 // Find target's sibling order
4951 // Set actor sibling order to this number +1
4952 int targetSiblingOrder = GetSiblingOrder( &target );
4953 ActorContainer* siblings = mParent->mChildren;
4954 mSiblingOrder = targetSiblingOrder + 1;
4955 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4957 SetSiblingOrder( mSiblingOrder );
4959 if ( defragmentationRequired )
4961 DefragmentSiblingIndexes( *(mParent->mChildren) );
4967 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4971 void Actor::LowerBelow( Internal::Actor& target )
4974 1 ) a) Find target actor's sibling order
4975 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4976 needs to be below it or the insertion order will determine which is drawn on top.
4977 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4978 3 ) Set this actor to the sibling order of the target before it changed.
4979 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4980 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4981 remove any empty sibling order gaps and start from sibling level 0 again.
4982 If the number of actors reaches this maximum and all using exclusive sibling order values then
4983 defragmention will stop and new sibling orders will be set to same max value.
4988 if ( ValidateActors( *this, target ) )
4990 bool defragmentationRequired ( false );
4991 // Find target's sibling order
4992 // Set actor sibling order to target sibling order - 1
4993 int targetSiblingOrder = GetSiblingOrder( &target);
4994 ActorContainer* siblings = mParent->mChildren;
4995 if ( targetSiblingOrder == 0 )
4998 ActorIter end = siblings->end();
4999 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5001 ActorPtr sibling = (*iter);
5002 if ( sibling != this )
5004 sibling->mSiblingOrder++;
5005 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5007 defragmentationRequired = true;
5009 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5016 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5018 mSiblingOrder = targetSiblingOrder;
5020 SetSiblingOrder( mSiblingOrder );
5022 if ( defragmentationRequired )
5024 DefragmentSiblingIndexes( *(mParent->mChildren) );
5030 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5034 } // namespace Internal