2 * Copyright (c) 2015 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>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-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 #ifdef DALI_DYNAMICS_SUPPORT
57 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
58 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
63 using Dali::Internal::SceneGraph::Node;
64 using Dali::Internal::SceneGraph::AnimatableProperty;
65 using Dali::Internal::SceneGraph::PropertyBase;
69 namespace ResizePolicy
74 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
75 DALI_ENUM_TO_STRING( FIXED )
76 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
77 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
80 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
81 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
82 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
83 DALI_ENUM_TO_STRING_TABLE_END( Type )
85 } // unnamed namespace
88 namespace SizeScalePolicy
92 // Enumeration to / from string conversion tables
93 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
94 DALI_ENUM_TO_STRING( USE_SIZE_SET )
95 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
97 DALI_ENUM_TO_STRING_TABLE_END( Type )
98 } // unnamed namespace
104 unsigned int Actor::mActorCounter = 0;
108 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
109 inline const Vector3& GetDefaultSizeModeFactor()
114 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
115 inline const Vector2& GetDefaultPreferredSize()
117 return Vector2::ZERO;
120 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
121 inline const Vector2& GetDefaultDimensionPadding()
123 return Vector2::ZERO;
126 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
128 } // unnamed namespace
131 * Struct to collect relayout variables
133 struct Actor::RelayoutData
136 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
138 // Set size negotiation defaults
139 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
141 resizePolicies[ i ] = ResizePolicy::DEFAULT;
142 negotiatedDimensions[ i ] = 0.0f;
143 dimensionNegotiated[ i ] = false;
144 dimensionDirty[ i ] = false;
145 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
146 dimensionPadding[ i ] = GetDefaultDimensionPadding();
147 minimumSize[ i ] = 0.0f;
148 maximumSize[ i ] = FLT_MAX;
152 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
154 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
156 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
158 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
160 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
161 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
163 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
164 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
166 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
168 Vector2 preferredSize; ///< The preferred size of the actor
170 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
172 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
173 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
176 #ifdef DALI_DYNAMICS_SUPPORT
178 // Encapsulate actor related dynamics data
181 DynamicsData( Actor* slotOwner )
182 : slotDelegate( slotOwner )
186 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
187 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
189 DynamicsBodyPtr body;
190 JointContainer joints;
191 ReferencedJointContainer referencedJoints;
193 SlotDelegate< Actor > slotDelegate;
196 #endif // DALI_DYNAMICS_SUPPORT
198 namespace // unnamed namespace
204 * We want to discourage the use of property strings (minimize string comparisons),
205 * particularly for the default properties.
206 * Name Type writable animatable constraint-input enum for index-checking
208 DALI_PROPERTY_TABLE_BEGIN
209 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
210 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
211 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
212 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
213 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
214 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
215 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
216 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
217 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
218 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
219 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
220 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
221 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
222 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
223 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
224 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
225 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
226 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
227 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
228 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
229 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
230 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
231 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
232 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
233 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
234 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
235 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
236 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
237 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
238 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
239 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
240 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
241 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
242 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
243 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
244 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
245 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
246 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
247 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
248 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
249 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
250 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
251 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
252 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
253 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
254 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
255 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
256 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
257 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
258 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
259 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
260 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
261 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
265 const char* const SIGNAL_TOUCHED = "touched";
266 const char* const SIGNAL_HOVERED = "hovered";
267 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
268 const char* const SIGNAL_ON_STAGE = "on-stage";
269 const char* const SIGNAL_OFF_STAGE = "off-stage";
273 const char* const ACTION_SHOW = "show";
274 const char* const ACTION_HIDE = "hide";
276 BaseHandle CreateActor()
278 return Dali::Actor::New();
281 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
283 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
284 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
285 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
286 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
288 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
289 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
292 * @brief Extract a given dimension from a Vector2
294 * @param[in] values The values to extract from
295 * @param[in] dimension The dimension to extract
296 * @return Return the value for the dimension
298 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
302 case Dimension::WIDTH:
306 case Dimension::HEIGHT:
308 return values.height;
319 * @brief Extract a given dimension from a Vector3
321 * @param[in] values The values to extract from
322 * @param[in] dimension The dimension to extract
323 * @return Return the value for the dimension
325 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
327 return GetDimensionValue( values.GetVectorXY(), dimension );
331 } // unnamed namespace
333 ActorPtr Actor::New()
335 ActorPtr actor( new Actor( BASIC ) );
337 // Second-phase construction
343 const std::string& Actor::GetName() const
348 void Actor::SetName( const std::string& name )
354 // ATTENTION: string for debug purposes is not thread safe.
355 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
359 unsigned int Actor::GetId() const
364 void Actor::Attach( ActorAttachment& attachment )
366 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
370 attachment.Connect();
373 mAttachment = ActorAttachmentPtr( &attachment );
376 ActorAttachmentPtr Actor::GetAttachment()
381 bool Actor::OnStage() const
386 Dali::Layer Actor::GetLayer()
390 // Short-circuit for Layer derived actors
393 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
396 // Find the immediate Layer parent
397 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
399 if( parent->IsLayer() )
401 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
408 void Actor::Add( Actor& child )
410 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
411 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
415 mChildren = new ActorContainer;
418 Actor* const oldParent( child.mParent );
420 // child might already be ours
421 if( this != oldParent )
423 // if we already have parent, unparent us first
426 oldParent->Remove( child ); // This causes OnChildRemove callback
428 // Old parent may need to readjust to missing child
429 if( oldParent->RelayoutDependentOnChildren() )
431 oldParent->RelayoutRequest();
435 // Guard against Add() during previous OnChildRemove callback
438 // Do this first, since user callbacks from within SetParent() may need to remove child
439 mChildren->push_back( Dali::Actor( &child ) );
441 // SetParent asserts that child can be added
442 child.SetParent( this );
444 // Notification for derived classes
447 // Only put in a relayout request if there is a suitable dependency
448 if( RelayoutDependentOnChildren() )
456 void Actor::Insert( unsigned int index, Actor& child )
458 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
459 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
463 mChildren = new ActorContainer;
466 Actor* const oldParent( child.mParent );
468 // since an explicit position has been given, always insert, even if already a child
471 oldParent->Remove( child ); // This causes OnChildRemove callback
473 // Old parent may need to readjust to missing child
474 if( oldParent->RelayoutDependentOnChildren() )
476 oldParent->RelayoutRequest();
480 // Guard against Add() during previous OnChildRemove callback
483 // Do this first, since user callbacks from within SetParent() may need to remove child
484 if( index < GetChildCount() )
486 ActorIter it = mChildren->begin();
487 std::advance( it, index );
488 mChildren->insert( it, Dali::Actor( &child ) );
492 mChildren->push_back( Dali::Actor( &child ) );
494 // SetParent asserts that child can be added
495 child.SetParent( this, index );
497 // Notification for derived classes
500 // Only put in a relayout request if there is a suitable dependency
501 if( RelayoutDependentOnChildren() )
506 if( child.RelayoutDependentOnParent() )
508 child.RelayoutRequest();
513 void Actor::Remove( Actor& child )
515 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
525 // Find the child in mChildren, and unparent it
526 ActorIter end = mChildren->end();
527 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
529 Actor& actor = GetImplementation( *iter );
531 if( &actor == &child )
533 // Keep handle for OnChildRemove notification
534 removed = Dali::Actor( &actor );
536 // Do this first, since user callbacks from within SetParent() may need to add the child
537 mChildren->erase( iter );
539 DALI_ASSERT_DEBUG( actor.GetParent() == this );
540 actor.SetParent( NULL );
548 // Notification for derived classes
549 OnChildRemove( GetImplementation( removed ) );
551 // Only put in a relayout request if there is a suitable dependency
552 if( RelayoutDependentOnChildren() )
559 void Actor::Unparent()
563 // Remove this actor from the parent. The remove will put a relayout request in for
564 // the parent if required
565 mParent->Remove( *this );
566 // mParent is now NULL!
570 unsigned int Actor::GetChildCount() const
572 return ( NULL != mChildren ) ? mChildren->size() : 0;
575 Dali::Actor Actor::GetChildAt( unsigned int index ) const
577 DALI_ASSERT_ALWAYS( index < GetChildCount() );
579 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
582 ActorPtr Actor::FindChildByName( const std::string& actorName )
585 if( actorName == mName )
591 ActorIter end = mChildren->end();
592 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
594 child = GetImplementation( *iter ).FindChildByName( actorName );
605 ActorPtr Actor::FindChildById( const unsigned int id )
614 ActorIter end = mChildren->end();
615 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
617 child = GetImplementation( *iter ).FindChildById( id );
628 void Actor::SetParentOrigin( const Vector3& origin )
632 // mNode is being used in a separate thread; queue a message to set the value & base value
633 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
636 // Cache for event-thread access
639 // not allocated, check if different from default
640 if( ParentOrigin::DEFAULT != origin )
642 mParentOrigin = new Vector3( origin );
647 // check if different from current costs more than just set
648 *mParentOrigin = origin;
652 void Actor::SetParentOriginX( float x )
654 const Vector3& current = GetCurrentParentOrigin();
656 SetParentOrigin( Vector3( x, current.y, current.z ) );
659 void Actor::SetParentOriginY( float y )
661 const Vector3& current = GetCurrentParentOrigin();
663 SetParentOrigin( Vector3( current.x, y, current.z ) );
666 void Actor::SetParentOriginZ( float z )
668 const Vector3& current = GetCurrentParentOrigin();
670 SetParentOrigin( Vector3( current.x, current.y, z ) );
673 const Vector3& Actor::GetCurrentParentOrigin() const
675 // Cached for event-thread access
676 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
679 void Actor::SetAnchorPoint( const Vector3& anchor )
683 // mNode is being used in a separate thread; queue a message to set the value & base value
684 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
687 // Cache for event-thread access
690 // not allocated, check if different from default
691 if( AnchorPoint::DEFAULT != anchor )
693 mAnchorPoint = new Vector3( anchor );
698 // check if different from current costs more than just set
699 *mAnchorPoint = anchor;
703 void Actor::SetAnchorPointX( float x )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( x, current.y, current.z ) );
710 void Actor::SetAnchorPointY( float y )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( current.x, y, current.z ) );
717 void Actor::SetAnchorPointZ( float z )
719 const Vector3& current = GetCurrentAnchorPoint();
721 SetAnchorPoint( Vector3( current.x, current.y, z ) );
724 const Vector3& Actor::GetCurrentAnchorPoint() const
726 // Cached for event-thread access
727 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
730 void Actor::SetPosition( float x, float y )
732 SetPosition( Vector3( x, y, 0.0f ) );
735 void Actor::SetPosition( float x, float y, float z )
737 SetPosition( Vector3( x, y, z ) );
740 void Actor::SetPosition( const Vector3& position )
742 mTargetPosition = position;
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
751 void Actor::SetX( float x )
753 mTargetPosition.x = x;
757 // mNode is being used in a separate thread; queue a message to set the value & base value
758 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
762 void Actor::SetY( float y )
764 mTargetPosition.y = y;
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
773 void Actor::SetZ( float z )
775 mTargetPosition.z = z;
779 // mNode is being used in a separate thread; queue a message to set the value & base value
780 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
784 void Actor::TranslateBy( const Vector3& distance )
786 mTargetPosition += distance;
790 // mNode is being used in a separate thread; queue a message to set the value & base value
791 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
795 const Vector3& Actor::GetCurrentPosition() const
799 // mNode is being used in a separate thread; copy the value from the previous update
800 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
803 return Vector3::ZERO;
806 const Vector3& Actor::GetTargetPosition() const
808 return mTargetPosition;
811 const Vector3& Actor::GetCurrentWorldPosition() const
815 // mNode is being used in a separate thread; copy the value from the previous update
816 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
819 return Vector3::ZERO;
822 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
824 // this flag is not animatable so keep the value
825 mPositionInheritanceMode = mode;
828 // mNode is being used in a separate thread; queue a message to set the value
829 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
833 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
835 // Cached for event-thread access
836 return mPositionInheritanceMode;
839 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
841 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
842 normalizedAxis.Normalize();
844 Quaternion orientation( angle, normalizedAxis );
846 SetOrientation( orientation );
849 void Actor::SetOrientation( const Quaternion& orientation )
853 // mNode is being used in a separate thread; queue a message to set the value & base value
854 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
858 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
862 // mNode is being used in a separate thread; queue a message to set the value & base value
863 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
867 void Actor::RotateBy( const Quaternion& relativeRotation )
871 // mNode is being used in a separate thread; queue a message to set the value & base value
872 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
876 const Quaternion& Actor::GetCurrentOrientation() const
880 // mNode is being used in a separate thread; copy the value from the previous update
881 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
884 return Quaternion::IDENTITY;
887 const Quaternion& Actor::GetCurrentWorldOrientation() const
891 // mNode is being used in a separate thread; copy the value from the previous update
892 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
895 return Quaternion::IDENTITY;
898 void Actor::SetScale( float scale )
900 SetScale( Vector3( scale, scale, scale ) );
903 void Actor::SetScale( float x, float y, float z )
905 SetScale( Vector3( x, y, z ) );
908 void Actor::SetScale( const Vector3& scale )
912 // mNode is being used in a separate thread; queue a message to set the value & base value
913 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
917 void Actor::SetScaleX( float x )
921 // mNode is being used in a separate thread; queue a message to set the value & base value
922 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
926 void Actor::SetScaleY( float y )
930 // mNode is being used in a separate thread; queue a message to set the value & base value
931 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
935 void Actor::SetScaleZ( float z )
939 // mNode is being used in a separate thread; queue a message to set the value & base value
940 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
944 void Actor::SetInitialVolume( const Vector3& volume )
948 // mNode is being used in a separate thread; queue a message to set the value
949 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
953 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
957 // mNode is being used in a separate thread; queue a message to set the value
958 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
962 bool Actor::GetTransmitGeometryScaling() const
966 // mNode is being used in a separate thread; copy the value from the previous update
967 return mNode->GetTransmitGeometryScaling();
973 void Actor::ScaleBy( const Vector3& relativeScale )
977 // mNode is being used in a separate thread; queue a message to set the value & base value
978 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
982 const Vector3& Actor::GetCurrentScale() const
986 // mNode is being used in a separate thread; copy the value from the previous update
987 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
993 const Vector3& Actor::GetCurrentWorldScale() const
997 // mNode is being used in a separate thread; copy the value from the previous update
998 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1001 return Vector3::ONE;
1004 void Actor::SetInheritScale( bool inherit )
1006 // non animateable so keep local copy
1007 mInheritScale = inherit;
1010 // mNode is being used in a separate thread; queue a message to set the value
1011 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1015 bool Actor::IsScaleInherited() const
1017 return mInheritScale;
1020 Matrix Actor::GetCurrentWorldMatrix() const
1024 // World matrix is no longer updated unless there is something observing the node.
1025 // Need to calculate it from node's world position, orientation and scale:
1026 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1027 Matrix worldMatrix(false);
1028 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1029 mNode->GetWorldOrientation( updateBufferIndex ),
1030 mNode->GetWorldPosition( updateBufferIndex ) );
1034 return Matrix::IDENTITY;
1037 void Actor::SetVisible( bool visible )
1041 // mNode is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1046 bool Actor::IsVisible() const
1050 // mNode is being used in a separate thread; copy the value from the previous update
1051 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1057 void Actor::SetOpacity( float opacity )
1061 // mNode is being used in a separate thread; queue a message to set the value & base value
1062 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1066 float Actor::GetCurrentOpacity() const
1070 // mNode is being used in a separate thread; copy the value from the previous update
1071 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1077 const Vector4& Actor::GetCurrentWorldColor() const
1081 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1084 return Color::WHITE;
1087 void Actor::SetColor( const Vector4& color )
1091 // mNode is being used in a separate thread; queue a message to set the value & base value
1092 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1096 void Actor::SetColorRed( float red )
1100 // mNode is being used in a separate thread; queue a message to set the value & base value
1101 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1105 void Actor::SetColorGreen( float green )
1109 // mNode is being used in a separate thread; queue a message to set the value & base value
1110 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1114 void Actor::SetColorBlue( float blue )
1118 // mNode is being used in a separate thread; queue a message to set the value & base value
1119 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1123 const Vector4& Actor::GetCurrentColor() const
1127 // mNode is being used in a separate thread; copy the value from the previous update
1128 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1131 return Color::WHITE;
1134 void Actor::SetInheritOrientation( bool inherit )
1136 // non animateable so keep local copy
1137 mInheritOrientation = inherit;
1140 // mNode is being used in a separate thread; queue a message to set the value
1141 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1145 bool Actor::IsOrientationInherited() const
1147 return mInheritOrientation;
1150 void Actor::SetSizeModeFactor( const Vector3& factor )
1152 EnsureRelayoutData();
1154 mRelayoutData->sizeModeFactor = factor;
1157 const Vector3& Actor::GetSizeModeFactor() const
1159 if ( mRelayoutData )
1161 return mRelayoutData->sizeModeFactor;
1164 return GetDefaultSizeModeFactor();
1167 void Actor::SetColorMode( ColorMode colorMode )
1169 // non animateable so keep local copy
1170 mColorMode = colorMode;
1173 // mNode is being used in a separate thread; queue a message to set the value
1174 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1178 ColorMode Actor::GetColorMode() const
1180 // we have cached copy
1184 void Actor::SetSize( float width, float height )
1186 SetSize( Vector2( width, height ) );
1189 void Actor::SetSize( float width, float height, float depth )
1191 SetSize( Vector3( width, height, depth ) );
1194 void Actor::SetSize( const Vector2& size )
1196 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1199 void Actor::SetSizeInternal( const Vector2& size )
1201 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1204 float Actor::CalculateSizeZ( const Vector2& size ) const
1206 return std::min( size.width, size.height );
1209 void Actor::SetSize( const Vector3& size )
1211 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1213 SetPreferredSize( size.GetVectorXY() );
1217 SetSizeInternal( size );
1221 void Actor::SetSizeInternal( const Vector3& size )
1223 // dont allow recursive loop
1224 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1225 // 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
1226 if( ( NULL != mNode )&&
1227 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1228 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1229 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1233 // mNode is being used in a separate thread; queue a message to set the value & base value
1234 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1236 // Notification for derived classes
1237 mInsideOnSizeSet = true;
1238 OnSizeSet( mTargetSize );
1239 mInsideOnSizeSet = false;
1241 // Raise a relayout request if the flag is not locked
1242 if( mRelayoutData && !mRelayoutData->insideRelayout )
1249 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1251 mTargetSize = targetSize;
1253 // Notify deriving classes
1254 OnSizeAnimation( animation, mTargetSize );
1257 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1259 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1261 mTargetSize.width = targetSize;
1263 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1265 mTargetSize.height = targetSize;
1267 // Notify deriving classes
1268 OnSizeAnimation( animation, mTargetSize );
1271 void Actor::SetWidth( float width )
1275 // mNode is being used in a separate thread; queue a message to set the value & base value
1276 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1280 void Actor::SetHeight( float height )
1284 // mNode is being used in a separate thread; queue a message to set the value & base value
1285 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1289 void Actor::SetDepth( float depth )
1293 // mNode is being used in a separate thread; queue a message to set the value & base value
1294 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1298 const Vector3& Actor::GetTargetSize() const
1303 const Vector3& Actor::GetCurrentSize() const
1307 // mNode is being used in a separate thread; copy the value from the previous update
1308 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1311 return Vector3::ZERO;
1314 Vector3 Actor::GetNaturalSize() const
1316 // It is up to deriving classes to return the appropriate natural size
1317 return Vector3( 0.0f, 0.0f, 0.0f );
1320 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1322 EnsureRelayoutData();
1324 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1326 if( dimension & ( 1 << i ) )
1328 mRelayoutData->resizePolicies[ i ] = policy;
1332 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1334 if( dimension & Dimension::WIDTH )
1336 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1339 if( dimension & Dimension::HEIGHT )
1341 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1345 // If calling SetResizePolicy, assume we want relayout enabled
1346 SetRelayoutEnabled( true );
1348 OnSetResizePolicy( policy, dimension );
1350 // Trigger relayout on this control
1354 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1356 if ( mRelayoutData )
1358 // If more than one dimension is requested, just return the first one found
1359 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1361 if( ( dimension & ( 1 << i ) ) )
1363 return mRelayoutData->resizePolicies[ i ];
1368 return ResizePolicy::DEFAULT;
1371 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1373 EnsureRelayoutData();
1375 mRelayoutData->sizeSetPolicy = policy;
1378 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1380 if ( mRelayoutData )
1382 return mRelayoutData->sizeSetPolicy;
1385 return DEFAULT_SIZE_SCALE_POLICY;
1388 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1390 EnsureRelayoutData();
1392 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1394 if( dimension & ( 1 << i ) )
1396 mRelayoutData->dimensionDependencies[ i ] = dependency;
1401 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1403 if ( mRelayoutData )
1405 // If more than one dimension is requested, just return the first one found
1406 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1408 if( ( dimension & ( 1 << i ) ) )
1410 return mRelayoutData->dimensionDependencies[ i ];
1415 return Dimension::ALL_DIMENSIONS; // Default
1418 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1420 // If relayout data has not been allocated yet and the client is requesting
1421 // to disable it, do nothing
1422 if( mRelayoutData || relayoutEnabled )
1424 EnsureRelayoutData();
1426 mRelayoutData->relayoutEnabled = relayoutEnabled;
1430 bool Actor::IsRelayoutEnabled() const
1432 // Assume that if relayout data has not been allocated yet then
1433 // relayout is disabled
1434 return mRelayoutData && mRelayoutData->relayoutEnabled;
1437 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1439 EnsureRelayoutData();
1441 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1443 if( dimension & ( 1 << i ) )
1445 mRelayoutData->dimensionDirty[ i ] = dirty;
1450 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1452 if ( mRelayoutData )
1454 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1456 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1466 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1468 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1471 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1473 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1476 #ifdef DALI_DYNAMICS_SUPPORT
1478 //--------------- Dynamics ---------------
1480 void Actor::DisableDynamics()
1482 if( NULL != mDynamicsData )
1484 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1486 // ensure dynamics object are disconnected from scene
1487 DisconnectDynamics();
1489 // delete joint owned by this actor
1490 while( !mDynamicsData->joints.empty() )
1492 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1495 // delete other joints referencing this actor
1496 while( !mDynamicsData->referencedJoints.empty() )
1498 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1499 ActorPtr jointOwner( joint->GetActor( true ) );
1502 jointOwner->RemoveDynamicsJoint( joint );
1506 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1509 // delete the DynamicsBody object
1510 mDynamicsData->body.Reset();
1512 // Discard Dynamics data structure
1513 delete mDynamicsData;
1514 mDynamicsData = NULL;
1518 DynamicsBodyPtr Actor::GetDynamicsBody() const
1520 DynamicsBodyPtr body;
1522 if( NULL != mDynamicsData )
1524 body = mDynamicsData->body;
1530 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1532 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1534 if( NULL == mDynamicsData )
1536 mDynamicsData = new DynamicsData( this );
1539 if( !mDynamicsData->body )
1541 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1545 DynamicsWorldPtr world( DynamicsWorld::Get() );
1548 if( mParent == world->GetRootActor().Get() )
1550 mDynamicsData->body->Connect( GetEventThreadServices() );
1556 return mDynamicsData->body;
1559 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1561 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1562 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1565 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1567 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1568 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1570 DynamicsJointPtr joint;
1572 DynamicsWorldPtr world( DynamicsWorld::Get() );
1576 if( NULL != mDynamicsData )
1578 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1580 if( mDynamicsData->joints.end() != it )
1582 // use existing joint
1588 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1589 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1593 bodyA = EnableDynamics( new DynamicsBodyConfig );
1598 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1601 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1602 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1604 if( OnStage() && attachedActor->OnStage() )
1606 joint->Connect( GetEventThreadServices() );
1609 attachedActor->ReferenceJoint( joint );
1611 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1612 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1619 const int Actor::GetNumberOfJoints() const
1621 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1624 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1626 DynamicsJointPtr joint;
1628 if( NULL != mDynamicsData )
1630 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1632 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1634 for( int i = 0; i < index; ++i )
1646 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1648 DynamicsJointPtr joint;
1650 if( NULL != mDynamicsData )
1652 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1654 if( mDynamicsData->joints.end() != it )
1656 // use existing joint
1664 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1666 if( NULL != mDynamicsData )
1668 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1669 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1671 for(; it != endIt; ++it )
1673 if( it->second == joint.Get() )
1675 ActorPtr attachedActor( it->first );
1677 if( OnStage() && attachedActor && attachedActor->OnStage() )
1679 joint->Disconnect( GetEventThreadServices() );
1684 attachedActor->ReleaseJoint( joint );
1685 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1686 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1689 mDynamicsData->joints.erase(it);
1696 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1698 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1700 if( NULL != mDynamicsData )
1702 mDynamicsData->referencedJoints.push_back(joint);
1706 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1708 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1710 if( NULL != mDynamicsData )
1712 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1714 if( it != mDynamicsData->referencedJoints.end() )
1716 mDynamicsData->referencedJoints.erase( it );
1721 void Actor::SetDynamicsRoot(bool flag)
1723 if( mIsDynamicsRoot != flag )
1725 mIsDynamicsRoot = flag;
1727 if( OnStage() && mChildren )
1729 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1730 ActorIter end = mChildren->end();
1731 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1733 Actor& child = GetImplementation(*iter);
1735 if( child.GetDynamicsBody() )
1737 if( mIsDynamicsRoot )
1739 child.ConnectDynamics();
1743 child.DisconnectDynamics();
1751 bool Actor::IsDynamicsRoot() const
1753 return mIsDynamicsRoot;
1756 void Actor::AttachedActorOnStage( Dali::Actor actor )
1758 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1762 ActorPtr attachedActor( &GetImplementation(actor) );
1764 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1765 if( NULL != mDynamicsData )
1767 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1768 if( mDynamicsData->joints.end() != it )
1770 DynamicsJointPtr joint( it->second );
1771 joint->Connect( GetEventThreadServices() );
1777 void Actor::AttachedActorOffStage( Dali::Actor actor )
1779 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1783 ActorPtr attachedActor( &GetImplementation(actor) );
1785 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1786 if( NULL != mDynamicsData )
1788 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1789 if( mDynamicsData->joints.end() != it )
1791 DynamicsJointPtr joint( it->second );
1792 joint->Disconnect( GetEventThreadServices() );
1798 void Actor::ConnectDynamics()
1800 if( NULL != mDynamicsData && mDynamicsData->body )
1802 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1804 mDynamicsData->body->Connect( GetEventThreadServices() );
1806 // Connect all joints where attachedActor is also on stage
1807 if( !mDynamicsData->joints.empty() )
1809 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1810 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1812 for(; it != endIt; ++it )
1814 Actor* attachedActor( it->first );
1815 if( NULL != attachedActor && attachedActor->OnStage() )
1817 DynamicsJointPtr joint( it->second );
1819 joint->Connect( GetEventThreadServices() );
1827 void Actor::DisconnectDynamics()
1829 if( NULL != mDynamicsData && mDynamicsData->body )
1833 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1835 // Disconnect all joints
1836 if( !mDynamicsData->joints.empty() )
1838 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1839 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1841 for(; it != endIt; ++it )
1843 DynamicsJointPtr joint( it->second );
1845 joint->Disconnect( GetEventThreadServices() );
1852 #endif // DALI_DYNAMICS_SUPPORT
1854 void Actor::SetOverlay( bool enable )
1856 // Setting STENCIL will override OVERLAY
1857 if( DrawMode::STENCIL != mDrawMode )
1859 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1863 bool Actor::IsOverlay() const
1865 return ( DrawMode::OVERLAY == mDrawMode );
1868 void Actor::SetDrawMode( DrawMode::Type drawMode )
1870 // this flag is not animatable so keep the value
1871 mDrawMode = drawMode;
1874 // mNode is being used in a separate thread; queue a message to set the value
1875 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1879 DrawMode::Type Actor::GetDrawMode() const
1884 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1886 // only valid when on-stage
1887 StagePtr stage = Stage::GetCurrent();
1888 if( stage && OnStage() )
1890 const RenderTaskList& taskList = stage->GetRenderTaskList();
1892 Vector2 converted( screenX, screenY );
1894 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1895 const int taskCount = taskList.GetTaskCount();
1896 for( int i = taskCount - 1; i >= 0; --i )
1898 Dali::RenderTask task = taskList.GetTask( i );
1899 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1901 // found a task where this conversion was ok so return
1909 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1911 bool retval = false;
1912 // only valid when on-stage
1915 CameraActor* camera = renderTask.GetCameraActor();
1919 renderTask.GetViewport( viewport );
1921 // need to translate coordinates to render tasks coordinate space
1922 Vector2 converted( screenX, screenY );
1923 if( renderTask.TranslateCoordinates( converted ) )
1925 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1932 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1934 // Early-out if mNode is NULL
1940 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1942 // Calculate the ModelView matrix
1943 Matrix modelView( false/*don't init*/);
1944 // need to use the components as world matrix is only updated for actors that need it
1945 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1946 Matrix::Multiply( modelView, modelView, viewMatrix );
1948 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1949 Matrix invertedMvp( false/*don't init*/);
1950 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1951 bool success = invertedMvp.Invert();
1953 // Convert to GL coordinates
1954 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1959 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1966 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1972 if( XyPlaneIntersect( nearPos, farPos, local ) )
1974 Vector3 size = GetCurrentSize();
1975 localX = local.x + size.x * 0.5f;
1976 localY = local.y + size.y * 0.5f;
1987 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1990 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1992 Mathematical Formulation
1994 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1996 ( p - c ) dot ( p - c ) = r^2
1998 Given a ray with a point of origin 'o', and a direction vector 'd':
2000 ray(t) = o + td, t >= 0
2002 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
2004 (o + td - c ) dot ( o + td - c ) = r^2
2006 To solve for t we first expand the above into a more recognisable quadratic equation form
2008 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
2017 B = 2( o - c ) dot d
2018 C = ( o - c ) dot ( o - c ) - r^2
2020 which can be solved using a standard quadratic formula.
2022 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
2024 Practical Simplification
2026 In a renderer, we often differentiate between world space and object space. In the object space
2027 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2028 into object space, the mathematical solution presented above can be simplified significantly.
2030 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2034 and we can find the t at which the (transformed) ray intersects the sphere by
2036 ( o + td ) dot ( o + td ) = r^2
2038 According to the reasoning above, we expand the above quadratic equation into the general form
2042 which now has coefficients:
2049 // Early out if mNode is NULL
2055 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2057 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2058 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2059 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2061 // Compute the radius is not needed, square radius it's enough.
2062 const Vector3& size( mNode->GetSize( bufferIndex ) );
2064 // Scale the sphere.
2065 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2067 const float width = size.width * scale.width;
2068 const float height = size.height * scale.height;
2070 float squareSphereRadius = 0.5f * ( width * width + height * height );
2072 float a = rayDir.Dot( rayDir ); // a
2073 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2074 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2076 return ( b2 * b2 - a * c ) >= 0.f;
2079 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2086 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2088 // Transforms the ray to the local reference system.
2090 // Calculate the inverse of Model matrix
2091 Matrix invModelMatrix( false/*don't init*/);
2092 // need to use the components as world matrix is only updated for actors that need it
2093 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2095 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2096 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2098 // Test with the actor's XY plane (Normal = 0 0 1 1).
2100 float a = -rayOriginLocal.z;
2101 float b = rayDirLocal.z;
2103 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2105 // Ray travels distance * rayDirLocal to intersect with plane.
2108 const Vector3& size = mNode->GetSize( bufferIndex );
2110 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2111 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2113 // Test with the actor's geometry.
2114 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2121 void Actor::SetLeaveRequired( bool required )
2123 mLeaveRequired = required;
2126 bool Actor::GetLeaveRequired() const
2128 return mLeaveRequired;
2131 void Actor::SetKeyboardFocusable( bool focusable )
2133 mKeyboardFocusable = focusable;
2136 bool Actor::IsKeyboardFocusable() const
2138 return mKeyboardFocusable;
2141 bool Actor::GetTouchRequired() const
2143 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2146 bool Actor::GetHoverRequired() const
2148 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2151 bool Actor::GetWheelEventRequired() const
2153 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2156 bool Actor::IsHittable() const
2158 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2161 ActorGestureData& Actor::GetGestureData()
2163 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2164 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2165 if( NULL == mGestureData )
2167 mGestureData = new ActorGestureData;
2169 return *mGestureData;
2172 bool Actor::IsGestureRequred( Gesture::Type type ) const
2174 return mGestureData && mGestureData->IsGestureRequred( type );
2177 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2179 bool consumed = false;
2181 if( !mTouchedSignal.Empty() )
2183 Dali::Actor handle( this );
2184 consumed = mTouchedSignal.Emit( handle, event );
2189 // Notification for derived classes
2190 consumed = OnTouchEvent( event );
2196 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2198 bool consumed = false;
2200 if( !mHoveredSignal.Empty() )
2202 Dali::Actor handle( this );
2203 consumed = mHoveredSignal.Emit( handle, event );
2208 // Notification for derived classes
2209 consumed = OnHoverEvent( event );
2215 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2217 bool consumed = false;
2219 if( !mWheelEventSignal.Empty() )
2221 Dali::Actor handle( this );
2222 consumed = mWheelEventSignal.Emit( handle, event );
2227 // Notification for derived classes
2228 consumed = OnWheelEvent( event );
2234 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2236 return mTouchedSignal;
2239 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2241 return mHoveredSignal;
2244 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2246 return mWheelEventSignal;
2249 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2251 return mOnStageSignal;
2254 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2256 return mOffStageSignal;
2259 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2261 return mOnRelayoutSignal;
2264 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2266 bool connected( true );
2267 Actor* actor = dynamic_cast< Actor* >( object );
2269 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2271 actor->TouchedSignal().Connect( tracker, functor );
2273 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2275 actor->HoveredSignal().Connect( tracker, functor );
2277 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2279 actor->WheelEventSignal().Connect( tracker, functor );
2281 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2283 actor->OnStageSignal().Connect( tracker, functor );
2285 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2287 actor->OffStageSignal().Connect( tracker, functor );
2291 // signalName does not match any signal
2298 Actor::Actor( DerivedType derivedType )
2303 mParentOrigin( NULL ),
2304 mAnchorPoint( NULL ),
2305 mRelayoutData( NULL ),
2306 #ifdef DALI_DYNAMICS_SUPPORT
2307 mDynamicsData( NULL ),
2309 mGestureData( NULL ),
2311 mTargetSize( 0.0f, 0.0f, 0.0f ),
2313 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2314 mIsRoot( ROOT_LAYER == derivedType ),
2315 mIsRenderable( RENDERABLE == derivedType ),
2316 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2317 mIsOnStage( false ),
2318 mIsDynamicsRoot( false ),
2320 mLeaveRequired( false ),
2321 mKeyboardFocusable( false ),
2322 mDerivedRequiresTouch( false ),
2323 mDerivedRequiresHover( false ),
2324 mDerivedRequiresWheelEvent( false ),
2325 mOnStageSignalled( false ),
2326 mInsideOnSizeSet( false ),
2327 mInheritOrientation( true ),
2328 mInheritScale( true ),
2329 mDrawMode( DrawMode::NORMAL ),
2330 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2331 mColorMode( Node::DEFAULT_COLOR_MODE )
2335 void Actor::Initialize()
2338 SceneGraph::Node* node = CreateNode();
2340 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2341 mNode = node; // Keep raw-pointer to Node
2345 GetEventThreadServices().RegisterObject( this );
2350 // Remove mParent pointers from children even if we're destroying core,
2351 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2354 ActorConstIter endIter = mChildren->end();
2355 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2357 Actor& actor = GetImplementation( *iter );
2358 actor.SetParent( NULL );
2363 // Guard to allow handle destruction after Core has been destroyed
2364 if( EventThreadServices::IsCoreRunning() )
2368 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2369 mNode = NULL; // Node is about to be destroyed
2372 GetEventThreadServices().UnregisterObject( this );
2375 #ifdef DALI_DYNAMICS_SUPPORT
2377 delete mDynamicsData;
2380 // Cleanup optional gesture data
2381 delete mGestureData;
2383 // Cleanup optional parent origin and anchor
2384 delete mParentOrigin;
2385 delete mAnchorPoint;
2387 // Delete optional relayout data
2390 delete mRelayoutData;
2394 void Actor::ConnectToStage( int index )
2396 // This container is used instead of walking the Actor hierachy.
2397 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2398 ActorContainer connectionList;
2400 // This stage is atomic i.e. not interrupted by user callbacks
2401 RecursiveConnectToStage( connectionList, index );
2403 // Notify applications about the newly connected actors.
2404 const ActorIter endIter = connectionList.end();
2405 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2407 Actor& actor = GetImplementation( *iter );
2408 actor.NotifyStageConnection();
2414 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2416 DALI_ASSERT_ALWAYS( !OnStage() );
2420 ConnectToSceneGraph( index );
2422 // Notification for internal derived classes
2423 OnStageConnectionInternal();
2425 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2426 connectionList.push_back( Dali::Actor( this ) );
2428 // Recursively connect children
2431 ActorConstIter endIter = mChildren->end();
2432 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2434 Actor& actor = GetImplementation( *iter );
2435 actor.RecursiveConnectToStage( connectionList );
2441 * This method is called when the Actor is connected to the Stage.
2442 * The parent must have added its Node to the scene-graph.
2443 * The child must connect its Node to the parent's Node.
2444 * This is resursive; the child calls ConnectToStage() for its children.
2446 void Actor::ConnectToSceneGraph( int index )
2448 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2452 // Reparent Node in next Update
2453 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2456 // Notify attachment
2459 mAttachment->Connect();
2462 #ifdef DALI_DYNAMICS_SUPPORT
2464 if( NULL != mDynamicsData )
2470 // Request relayout on all actors that are added to the scenegraph
2473 // Notification for Object::Observers
2477 void Actor::NotifyStageConnection()
2479 // Actors can be removed (in a callback), before the on-stage stage is reported.
2480 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2481 if( OnStage() && !mOnStageSignalled )
2483 // Notification for external (CustomActor) derived classes
2484 OnStageConnectionExternal();
2486 if( !mOnStageSignal.Empty() )
2488 Dali::Actor handle( this );
2489 mOnStageSignal.Emit( handle );
2492 // Guard against Remove during callbacks
2495 mOnStageSignalled = true; // signal required next time Actor is removed
2500 void Actor::DisconnectFromStage()
2502 // This container is used instead of walking the Actor hierachy.
2503 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2504 ActorContainer disconnectionList;
2506 // This stage is atomic i.e. not interrupted by user callbacks
2507 RecursiveDisconnectFromStage( disconnectionList );
2509 // Notify applications about the newly disconnected actors.
2510 const ActorIter endIter = disconnectionList.end();
2511 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2513 Actor& actor = GetImplementation( *iter );
2514 actor.NotifyStageDisconnection();
2518 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2520 DALI_ASSERT_ALWAYS( OnStage() );
2522 // Recursively disconnect children
2525 ActorConstIter endIter = mChildren->end();
2526 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2528 Actor& actor = GetImplementation( *iter );
2529 actor.RecursiveDisconnectFromStage( disconnectionList );
2533 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2534 disconnectionList.push_back( Dali::Actor( this ) );
2536 // Notification for internal derived classes
2537 OnStageDisconnectionInternal();
2539 DisconnectFromSceneGraph();
2545 * This method is called by an actor or its parent, before a node removal message is sent.
2546 * This is recursive; the child calls DisconnectFromStage() for its children.
2548 void Actor::DisconnectFromSceneGraph()
2550 // Notification for Object::Observers
2551 OnSceneObjectRemove();
2553 // Notify attachment
2556 mAttachment->Disconnect();
2559 #ifdef DALI_DYNAMICS_SUPPORT
2561 if( NULL != mDynamicsData )
2563 DisconnectDynamics();
2568 void Actor::NotifyStageDisconnection()
2570 // Actors can be added (in a callback), before the off-stage state is reported.
2571 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2572 // only do this step if there is a stage, i.e. Core is not being shut down
2573 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2575 // Notification for external (CustomeActor) derived classes
2576 OnStageDisconnectionExternal();
2578 if( !mOffStageSignal.Empty() )
2580 Dali::Actor handle( this );
2581 mOffStageSignal.Emit( handle );
2584 // Guard against Add during callbacks
2587 mOnStageSignalled = false; // signal required next time Actor is added
2592 bool Actor::IsNodeConnected() const
2594 bool connected( false );
2599 if( mNode->IsRoot() || mNode->GetParent() )
2608 unsigned int Actor::GetDefaultPropertyCount() const
2610 return DEFAULT_PROPERTY_COUNT;
2613 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2615 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2617 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2619 indices.PushBack( i );
2623 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2625 if( index < DEFAULT_PROPERTY_COUNT )
2627 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2633 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2635 Property::Index index = Property::INVALID_INDEX;
2637 // Look for name in default properties
2638 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2640 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2641 if( 0 == name.compare( property->name ) )
2651 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2653 if( index < DEFAULT_PROPERTY_COUNT )
2655 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2661 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2663 if( index < DEFAULT_PROPERTY_COUNT )
2665 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2671 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2673 if( index < DEFAULT_PROPERTY_COUNT )
2675 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2681 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2683 if( index < DEFAULT_PROPERTY_COUNT )
2685 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2688 // index out of range...return Property::NONE
2689 return Property::NONE;
2692 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2696 case Dali::Actor::Property::PARENT_ORIGIN:
2698 SetParentOrigin( property.Get< Vector3 >() );
2702 case Dali::Actor::Property::PARENT_ORIGIN_X:
2704 SetParentOriginX( property.Get< float >() );
2708 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2710 SetParentOriginY( property.Get< float >() );
2714 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2716 SetParentOriginZ( property.Get< float >() );
2720 case Dali::Actor::Property::ANCHOR_POINT:
2722 SetAnchorPoint( property.Get< Vector3 >() );
2726 case Dali::Actor::Property::ANCHOR_POINT_X:
2728 SetAnchorPointX( property.Get< float >() );
2732 case Dali::Actor::Property::ANCHOR_POINT_Y:
2734 SetAnchorPointY( property.Get< float >() );
2738 case Dali::Actor::Property::ANCHOR_POINT_Z:
2740 SetAnchorPointZ( property.Get< float >() );
2744 case Dali::Actor::Property::SIZE:
2746 SetSize( property.Get< Vector3 >() );
2750 case Dali::Actor::Property::SIZE_WIDTH:
2752 SetWidth( property.Get< float >() );
2756 case Dali::Actor::Property::SIZE_HEIGHT:
2758 SetHeight( property.Get< float >() );
2762 case Dali::Actor::Property::SIZE_DEPTH:
2764 SetDepth( property.Get< float >() );
2768 case Dali::Actor::Property::POSITION:
2770 SetPosition( property.Get< Vector3 >() );
2774 case Dali::Actor::Property::POSITION_X:
2776 SetX( property.Get< float >() );
2780 case Dali::Actor::Property::POSITION_Y:
2782 SetY( property.Get< float >() );
2786 case Dali::Actor::Property::POSITION_Z:
2788 SetZ( property.Get< float >() );
2792 case Dali::Actor::Property::ORIENTATION:
2794 SetOrientation( property.Get< Quaternion >() );
2798 case Dali::Actor::Property::SCALE:
2800 SetScale( property.Get< Vector3 >() );
2804 case Dali::Actor::Property::SCALE_X:
2806 SetScaleX( property.Get< float >() );
2810 case Dali::Actor::Property::SCALE_Y:
2812 SetScaleY( property.Get< float >() );
2816 case Dali::Actor::Property::SCALE_Z:
2818 SetScaleZ( property.Get< float >() );
2822 case Dali::Actor::Property::VISIBLE:
2824 SetVisible( property.Get< bool >() );
2828 case Dali::Actor::Property::COLOR:
2830 SetColor( property.Get< Vector4 >() );
2834 case Dali::Actor::Property::COLOR_RED:
2836 SetColorRed( property.Get< float >() );
2840 case Dali::Actor::Property::COLOR_GREEN:
2842 SetColorGreen( property.Get< float >() );
2846 case Dali::Actor::Property::COLOR_BLUE:
2848 SetColorBlue( property.Get< float >() );
2852 case Dali::Actor::Property::COLOR_ALPHA:
2854 SetOpacity( property.Get< float >() );
2858 case Dali::Actor::Property::NAME:
2860 SetName( property.Get< std::string >() );
2864 case Dali::Actor::Property::SENSITIVE:
2866 SetSensitive( property.Get< bool >() );
2870 case Dali::Actor::Property::LEAVE_REQUIRED:
2872 SetLeaveRequired( property.Get< bool >() );
2876 case Dali::Actor::Property::INHERIT_ORIENTATION:
2878 SetInheritOrientation( property.Get< bool >() );
2882 case Dali::Actor::Property::INHERIT_SCALE:
2884 SetInheritScale( property.Get< bool >() );
2888 case Dali::Actor::Property::COLOR_MODE:
2890 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2894 case Dali::Actor::Property::POSITION_INHERITANCE:
2896 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2900 case Dali::Actor::Property::DRAW_MODE:
2902 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2906 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2908 SetSizeModeFactor( property.Get< Vector3 >() );
2912 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2914 ResizePolicy::Type type;
2915 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2917 SetResizePolicy( type, Dimension::WIDTH );
2922 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2924 ResizePolicy::Type type;
2925 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2927 SetResizePolicy( type, Dimension::HEIGHT );
2932 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2934 SizeScalePolicy::Type type;
2935 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2937 SetSizeScalePolicy( type );
2942 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2944 if( property.Get< bool >() )
2946 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2951 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2953 if( property.Get< bool >() )
2955 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2960 case Dali::Actor::Property::PADDING:
2962 Vector4 padding = property.Get< Vector4 >();
2963 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2964 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2968 case Dali::Actor::Property::MINIMUM_SIZE:
2970 Vector2 size = property.Get< Vector2 >();
2971 SetMinimumSize( size.x, Dimension::WIDTH );
2972 SetMinimumSize( size.y, Dimension::HEIGHT );
2976 case Dali::Actor::Property::MAXIMUM_SIZE:
2978 Vector2 size = property.Get< Vector2 >();
2979 SetMaximumSize( size.x, Dimension::WIDTH );
2980 SetMaximumSize( size.y, Dimension::HEIGHT );
2986 // this can happen in the case of a non-animatable default property so just do nothing
2992 // TODO: This method needs to be removed
2993 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2995 switch( entry.type )
2997 case Property::BOOLEAN:
2999 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3000 DALI_ASSERT_DEBUG( NULL != property );
3002 // property is being used in a separate thread; queue a message to set the property
3003 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3008 case Property::INTEGER:
3010 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3011 DALI_ASSERT_DEBUG( NULL != property );
3013 // property is being used in a separate thread; queue a message to set the property
3014 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3019 case Property::UNSIGNED_INTEGER:
3021 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
3022 DALI_ASSERT_DEBUG( NULL != property );
3024 // property is being used in a separate thread; queue a message to set the property
3025 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3030 case Property::FLOAT:
3032 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3033 DALI_ASSERT_DEBUG( NULL != property );
3035 // property is being used in a separate thread; queue a message to set the property
3036 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3041 case Property::VECTOR2:
3043 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3044 DALI_ASSERT_DEBUG( NULL != property );
3046 // property is being used in a separate thread; queue a message to set the property
3047 if(entry.componentIndex == 0)
3049 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3051 else if(entry.componentIndex == 1)
3053 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3057 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3063 case Property::VECTOR3:
3065 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3066 DALI_ASSERT_DEBUG( NULL != property );
3068 // property is being used in a separate thread; queue a message to set the property
3069 if(entry.componentIndex == 0)
3071 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3073 else if(entry.componentIndex == 1)
3075 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3077 else if(entry.componentIndex == 2)
3079 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3083 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3089 case Property::VECTOR4:
3091 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3092 DALI_ASSERT_DEBUG( NULL != property );
3094 // property is being used in a separate thread; queue a message to set the property
3095 if(entry.componentIndex == 0)
3097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3099 else if(entry.componentIndex == 1)
3101 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3103 else if(entry.componentIndex == 2)
3105 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3107 else if(entry.componentIndex == 3)
3109 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3113 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3119 case Property::ROTATION:
3121 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3122 DALI_ASSERT_DEBUG( NULL != property );
3124 // property is being used in a separate thread; queue a message to set the property
3125 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3130 case Property::MATRIX:
3132 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3133 DALI_ASSERT_DEBUG( NULL != property );
3135 // property is being used in a separate thread; queue a message to set the property
3136 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3141 case Property::MATRIX3:
3143 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3144 DALI_ASSERT_DEBUG( NULL != property );
3146 // property is being used in a separate thread; queue a message to set the property
3147 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3154 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3160 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3162 Property::Value value;
3166 case Dali::Actor::Property::PARENT_ORIGIN:
3168 value = GetCurrentParentOrigin();
3172 case Dali::Actor::Property::PARENT_ORIGIN_X:
3174 value = GetCurrentParentOrigin().x;
3178 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3180 value = GetCurrentParentOrigin().y;
3184 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3186 value = GetCurrentParentOrigin().z;
3190 case Dali::Actor::Property::ANCHOR_POINT:
3192 value = GetCurrentAnchorPoint();
3196 case Dali::Actor::Property::ANCHOR_POINT_X:
3198 value = GetCurrentAnchorPoint().x;
3202 case Dali::Actor::Property::ANCHOR_POINT_Y:
3204 value = GetCurrentAnchorPoint().y;
3208 case Dali::Actor::Property::ANCHOR_POINT_Z:
3210 value = GetCurrentAnchorPoint().z;
3214 case Dali::Actor::Property::SIZE:
3216 value = GetCurrentSize();
3220 case Dali::Actor::Property::SIZE_WIDTH:
3222 value = GetCurrentSize().width;
3226 case Dali::Actor::Property::SIZE_HEIGHT:
3228 value = GetCurrentSize().height;
3232 case Dali::Actor::Property::SIZE_DEPTH:
3234 value = GetCurrentSize().depth;
3238 case Dali::Actor::Property::POSITION:
3240 value = GetCurrentPosition();
3244 case Dali::Actor::Property::POSITION_X:
3246 value = GetCurrentPosition().x;
3250 case Dali::Actor::Property::POSITION_Y:
3252 value = GetCurrentPosition().y;
3256 case Dali::Actor::Property::POSITION_Z:
3258 value = GetCurrentPosition().z;
3262 case Dali::Actor::Property::WORLD_POSITION:
3264 value = GetCurrentWorldPosition();
3268 case Dali::Actor::Property::WORLD_POSITION_X:
3270 value = GetCurrentWorldPosition().x;
3274 case Dali::Actor::Property::WORLD_POSITION_Y:
3276 value = GetCurrentWorldPosition().y;
3280 case Dali::Actor::Property::WORLD_POSITION_Z:
3282 value = GetCurrentWorldPosition().z;
3286 case Dali::Actor::Property::ORIENTATION:
3288 value = GetCurrentOrientation();
3292 case Dali::Actor::Property::WORLD_ORIENTATION:
3294 value = GetCurrentWorldOrientation();
3298 case Dali::Actor::Property::SCALE:
3300 value = GetCurrentScale();
3304 case Dali::Actor::Property::SCALE_X:
3306 value = GetCurrentScale().x;
3310 case Dali::Actor::Property::SCALE_Y:
3312 value = GetCurrentScale().y;
3316 case Dali::Actor::Property::SCALE_Z:
3318 value = GetCurrentScale().z;
3322 case Dali::Actor::Property::WORLD_SCALE:
3324 value = GetCurrentWorldScale();
3328 case Dali::Actor::Property::VISIBLE:
3330 value = IsVisible();
3334 case Dali::Actor::Property::COLOR:
3336 value = GetCurrentColor();
3340 case Dali::Actor::Property::COLOR_RED:
3342 value = GetCurrentColor().r;
3346 case Dali::Actor::Property::COLOR_GREEN:
3348 value = GetCurrentColor().g;
3352 case Dali::Actor::Property::COLOR_BLUE:
3354 value = GetCurrentColor().b;
3358 case Dali::Actor::Property::COLOR_ALPHA:
3360 value = GetCurrentColor().a;
3364 case Dali::Actor::Property::WORLD_COLOR:
3366 value = GetCurrentWorldColor();
3370 case Dali::Actor::Property::WORLD_MATRIX:
3372 value = GetCurrentWorldMatrix();
3376 case Dali::Actor::Property::NAME:
3382 case Dali::Actor::Property::SENSITIVE:
3384 value = IsSensitive();
3388 case Dali::Actor::Property::LEAVE_REQUIRED:
3390 value = GetLeaveRequired();
3394 case Dali::Actor::Property::INHERIT_ORIENTATION:
3396 value = IsOrientationInherited();
3400 case Dali::Actor::Property::INHERIT_SCALE:
3402 value = IsScaleInherited();
3406 case Dali::Actor::Property::COLOR_MODE:
3408 value = Scripting::GetColorMode( GetColorMode() );
3412 case Dali::Actor::Property::POSITION_INHERITANCE:
3414 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3418 case Dali::Actor::Property::DRAW_MODE:
3420 value = Scripting::GetDrawMode( GetDrawMode() );
3424 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3426 value = GetSizeModeFactor();
3430 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3432 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3436 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3438 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3442 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3444 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3448 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3450 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3454 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3456 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3460 case Dali::Actor::Property::PADDING:
3462 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3463 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3464 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3468 case Dali::Actor::Property::MINIMUM_SIZE:
3470 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3474 case Dali::Actor::Property::MAXIMUM_SIZE:
3476 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3482 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3490 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3495 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3497 // This method should only return an object connected to the scene-graph
3498 return OnStage() ? mNode : NULL;
3501 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3503 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3505 const PropertyBase* property( NULL );
3507 // This method should only return a property of an object connected to the scene-graph
3513 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3515 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3516 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3518 property = animatable->GetSceneGraphProperty();
3520 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3522 CustomPropertyMetadata* custom = FindCustomProperty( index );
3523 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3525 property = custom->GetSceneGraphProperty();
3527 else if( NULL != mNode )
3531 case Dali::Actor::Property::SIZE:
3532 property = &mNode->mSize;
3535 case Dali::Actor::Property::SIZE_WIDTH:
3536 property = &mNode->mSize;
3539 case Dali::Actor::Property::SIZE_HEIGHT:
3540 property = &mNode->mSize;
3543 case Dali::Actor::Property::SIZE_DEPTH:
3544 property = &mNode->mSize;
3547 case Dali::Actor::Property::POSITION:
3548 property = &mNode->mPosition;
3551 case Dali::Actor::Property::POSITION_X:
3552 property = &mNode->mPosition;
3555 case Dali::Actor::Property::POSITION_Y:
3556 property = &mNode->mPosition;
3559 case Dali::Actor::Property::POSITION_Z:
3560 property = &mNode->mPosition;
3563 case Dali::Actor::Property::ORIENTATION:
3564 property = &mNode->mOrientation;
3567 case Dali::Actor::Property::SCALE:
3568 property = &mNode->mScale;
3571 case Dali::Actor::Property::SCALE_X:
3572 property = &mNode->mScale;
3575 case Dali::Actor::Property::SCALE_Y:
3576 property = &mNode->mScale;
3579 case Dali::Actor::Property::SCALE_Z:
3580 property = &mNode->mScale;
3583 case Dali::Actor::Property::VISIBLE:
3584 property = &mNode->mVisible;
3587 case Dali::Actor::Property::COLOR:
3588 property = &mNode->mColor;
3591 case Dali::Actor::Property::COLOR_RED:
3592 property = &mNode->mColor;
3595 case Dali::Actor::Property::COLOR_GREEN:
3596 property = &mNode->mColor;
3599 case Dali::Actor::Property::COLOR_BLUE:
3600 property = &mNode->mColor;
3603 case Dali::Actor::Property::COLOR_ALPHA:
3604 property = &mNode->mColor;
3615 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3617 const PropertyInputImpl* property( NULL );
3619 // This method should only return a property of an object connected to the scene-graph
3625 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3627 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3628 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3630 property = animatable->GetSceneGraphProperty();
3632 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3634 CustomPropertyMetadata* custom = FindCustomProperty( index );
3635 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3636 property = custom->GetSceneGraphProperty();
3638 else if( NULL != mNode )
3642 case Dali::Actor::Property::PARENT_ORIGIN:
3643 property = &mNode->mParentOrigin;
3646 case Dali::Actor::Property::PARENT_ORIGIN_X:
3647 property = &mNode->mParentOrigin;
3650 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3651 property = &mNode->mParentOrigin;
3654 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3655 property = &mNode->mParentOrigin;
3658 case Dali::Actor::Property::ANCHOR_POINT:
3659 property = &mNode->mAnchorPoint;
3662 case Dali::Actor::Property::ANCHOR_POINT_X:
3663 property = &mNode->mAnchorPoint;
3666 case Dali::Actor::Property::ANCHOR_POINT_Y:
3667 property = &mNode->mAnchorPoint;
3670 case Dali::Actor::Property::ANCHOR_POINT_Z:
3671 property = &mNode->mAnchorPoint;
3674 case Dali::Actor::Property::SIZE:
3675 property = &mNode->mSize;
3678 case Dali::Actor::Property::SIZE_WIDTH:
3679 property = &mNode->mSize;
3682 case Dali::Actor::Property::SIZE_HEIGHT:
3683 property = &mNode->mSize;
3686 case Dali::Actor::Property::SIZE_DEPTH:
3687 property = &mNode->mSize;
3690 case Dali::Actor::Property::POSITION:
3691 property = &mNode->mPosition;
3694 case Dali::Actor::Property::POSITION_X:
3695 property = &mNode->mPosition;
3698 case Dali::Actor::Property::POSITION_Y:
3699 property = &mNode->mPosition;
3702 case Dali::Actor::Property::POSITION_Z:
3703 property = &mNode->mPosition;
3706 case Dali::Actor::Property::WORLD_POSITION:
3707 property = &mNode->mWorldPosition;
3710 case Dali::Actor::Property::WORLD_POSITION_X:
3711 property = &mNode->mWorldPosition;
3714 case Dali::Actor::Property::WORLD_POSITION_Y:
3715 property = &mNode->mWorldPosition;
3718 case Dali::Actor::Property::WORLD_POSITION_Z:
3719 property = &mNode->mWorldPosition;
3722 case Dali::Actor::Property::ORIENTATION:
3723 property = &mNode->mOrientation;
3726 case Dali::Actor::Property::WORLD_ORIENTATION:
3727 property = &mNode->mWorldOrientation;
3730 case Dali::Actor::Property::SCALE:
3731 property = &mNode->mScale;
3734 case Dali::Actor::Property::SCALE_X:
3735 property = &mNode->mScale;
3738 case Dali::Actor::Property::SCALE_Y:
3739 property = &mNode->mScale;
3742 case Dali::Actor::Property::SCALE_Z:
3743 property = &mNode->mScale;
3746 case Dali::Actor::Property::WORLD_SCALE:
3747 property = &mNode->mWorldScale;
3750 case Dali::Actor::Property::VISIBLE:
3751 property = &mNode->mVisible;
3754 case Dali::Actor::Property::COLOR:
3755 property = &mNode->mColor;
3758 case Dali::Actor::Property::COLOR_RED:
3759 property = &mNode->mColor;
3762 case Dali::Actor::Property::COLOR_GREEN:
3763 property = &mNode->mColor;
3766 case Dali::Actor::Property::COLOR_BLUE:
3767 property = &mNode->mColor;
3770 case Dali::Actor::Property::COLOR_ALPHA:
3771 property = &mNode->mColor;
3774 case Dali::Actor::Property::WORLD_COLOR:
3775 property = &mNode->mWorldColor;
3778 case Dali::Actor::Property::WORLD_MATRIX:
3779 property = &mNode->mWorldMatrix;
3790 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3792 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3794 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3796 // check whether the animatable property is registered already, if not then register one.
3797 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3798 if( animatableProperty )
3800 componentIndex = animatableProperty->componentIndex;
3807 case Dali::Actor::Property::PARENT_ORIGIN_X:
3808 case Dali::Actor::Property::ANCHOR_POINT_X:
3809 case Dali::Actor::Property::SIZE_WIDTH:
3810 case Dali::Actor::Property::POSITION_X:
3811 case Dali::Actor::Property::WORLD_POSITION_X:
3812 case Dali::Actor::Property::SCALE_X:
3813 case Dali::Actor::Property::COLOR_RED:
3819 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3820 case Dali::Actor::Property::ANCHOR_POINT_Y:
3821 case Dali::Actor::Property::SIZE_HEIGHT:
3822 case Dali::Actor::Property::POSITION_Y:
3823 case Dali::Actor::Property::WORLD_POSITION_Y:
3824 case Dali::Actor::Property::SCALE_Y:
3825 case Dali::Actor::Property::COLOR_GREEN:
3831 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3832 case Dali::Actor::Property::ANCHOR_POINT_Z:
3833 case Dali::Actor::Property::SIZE_DEPTH:
3834 case Dali::Actor::Property::POSITION_Z:
3835 case Dali::Actor::Property::WORLD_POSITION_Z:
3836 case Dali::Actor::Property::SCALE_Z:
3837 case Dali::Actor::Property::COLOR_BLUE:
3843 case Dali::Actor::Property::COLOR_ALPHA:
3857 return componentIndex;
3860 void Actor::SetParent( Actor* parent, int index )
3864 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3868 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3871 // Instruct each actor to create a corresponding node in the scene graph
3872 ConnectToStage( index );
3875 else // parent being set to NULL
3877 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3881 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3884 DALI_ASSERT_ALWAYS( mNode != NULL );
3888 // Disconnect the Node & its children from the scene-graph.
3889 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3892 // Instruct each actor to discard pointers to the scene-graph
3893 DisconnectFromStage();
3898 SceneGraph::Node* Actor::CreateNode() const
3903 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3906 Actor* actor = dynamic_cast< Actor* >( object );
3910 if( 0 == actionName.compare( ACTION_SHOW ) )
3912 actor->SetVisible( true );
3915 else if( 0 == actionName.compare( ACTION_HIDE ) )
3917 actor->SetVisible( false );
3925 void Actor::EnsureRelayoutData()
3927 // Assign relayout data.
3928 if( !mRelayoutData )
3930 mRelayoutData = new RelayoutData();
3934 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3936 // Check if actor is dependent on parent
3937 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3939 if( ( dimension & ( 1 << i ) ) )
3941 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3942 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3952 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3954 // Check if actor is dependent on children
3955 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3957 if( ( dimension & ( 1 << i ) ) )
3959 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3960 switch( resizePolicy )
3962 case ResizePolicy::FIT_TO_CHILDREN:
3963 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3979 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3981 return Actor::RelayoutDependentOnChildren( dimension );
3984 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3986 // Check each possible dimension and see if it is dependent on the input one
3987 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3989 if( dimension & ( 1 << i ) )
3991 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3998 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4000 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4002 if( dimension & ( 1 << i ) )
4004 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4009 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4011 // If more than one dimension is requested, just return the first one found
4012 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4014 if( ( dimension & ( 1 << i ) ) )
4016 return mRelayoutData->negotiatedDimensions[ i ];
4020 return 0.0f; // Default
4023 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4025 EnsureRelayoutData();
4027 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4029 if( dimension & ( 1 << i ) )
4031 mRelayoutData->dimensionPadding[ i ] = padding;
4036 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4038 if ( mRelayoutData )
4040 // If more than one dimension is requested, just return the first one found
4041 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4043 if( ( dimension & ( 1 << i ) ) )
4045 return mRelayoutData->dimensionPadding[ i ];
4050 return GetDefaultDimensionPadding();
4053 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4055 EnsureRelayoutData();
4057 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4059 if( dimension & ( 1 << i ) )
4061 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4066 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4068 if ( mRelayoutData )
4070 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4072 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4082 float Actor::GetHeightForWidthBase( float width )
4084 float height = 0.0f;
4086 const Vector3 naturalSize = GetNaturalSize();
4087 if( naturalSize.width > 0.0f )
4089 height = naturalSize.height * width / naturalSize.width;
4091 else // we treat 0 as 1:1 aspect ratio
4099 float Actor::GetWidthForHeightBase( float height )
4103 const Vector3 naturalSize = GetNaturalSize();
4104 if( naturalSize.height > 0.0f )
4106 width = naturalSize.width * height / naturalSize.height;
4108 else // we treat 0 as 1:1 aspect ratio
4116 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4118 // Fill to parent, taking size mode factor into account
4119 switch( child.GetResizePolicy( dimension ) )
4121 case ResizePolicy::FILL_TO_PARENT:
4123 return GetLatestSize( dimension );
4126 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4128 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4131 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4133 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4138 return GetLatestSize( dimension );
4143 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4145 // Can be overridden in derived class
4146 return CalculateChildSizeBase( child, dimension );
4149 float Actor::GetHeightForWidth( float width )
4151 // Can be overridden in derived class
4152 return GetHeightForWidthBase( width );
4155 float Actor::GetWidthForHeight( float height )
4157 // Can be overridden in derived class
4158 return GetWidthForHeightBase( height );
4161 float Actor::GetLatestSize( Dimension::Type dimension ) const
4163 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4166 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4168 Vector2 padding = GetPadding( dimension );
4170 return GetLatestSize( dimension ) + padding.x + padding.y;
4173 float Actor::NegotiateFromParent( Dimension::Type dimension )
4175 Actor* parent = GetParent();
4178 Vector2 padding( GetPadding( dimension ) );
4179 Vector2 parentPadding( parent->GetPadding( dimension ) );
4180 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4186 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4188 float maxDimensionPoint = 0.0f;
4190 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4192 Dali::Actor child = GetChildAt( i );
4193 Actor& childImpl = GetImplementation( child );
4195 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4197 // Calculate the min and max points that the children range across
4198 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4199 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4200 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4204 return maxDimensionPoint;
4207 float Actor::GetSize( Dimension::Type dimension ) const
4209 return GetDimensionValue( GetTargetSize(), dimension );
4212 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4214 return GetDimensionValue( GetNaturalSize(), dimension );
4217 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4219 switch( GetResizePolicy( dimension ) )
4221 case ResizePolicy::USE_NATURAL_SIZE:
4223 return GetNaturalSize( dimension );
4226 case ResizePolicy::FIXED:
4228 return GetDimensionValue( GetPreferredSize(), dimension );
4231 case ResizePolicy::USE_ASSIGNED_SIZE:
4233 return GetDimensionValue( maximumSize, dimension );
4236 case ResizePolicy::FILL_TO_PARENT:
4237 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4238 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4240 return NegotiateFromParent( dimension );
4243 case ResizePolicy::FIT_TO_CHILDREN:
4245 return NegotiateFromChildren( dimension );
4248 case ResizePolicy::DIMENSION_DEPENDENCY:
4250 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4253 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4255 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4258 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4260 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4272 return 0.0f; // Default
4275 float Actor::ClampDimension( float size, Dimension::Type dimension )
4277 const float minSize = GetMinimumSize( dimension );
4278 const float maxSize = GetMaximumSize( dimension );
4280 return std::max( minSize, std::min( size, maxSize ) );
4283 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4285 // Check if it needs to be negotiated
4286 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4288 // Check that we havn't gotten into an infinite loop
4289 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4290 bool recursionFound = false;
4291 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4293 if( *it == searchActor )
4295 recursionFound = true;
4300 if( !recursionFound )
4302 // Record the path that we have taken
4303 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4305 // Dimension dependency check
4306 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4308 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4310 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4312 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4316 // Parent dependency check
4317 Actor* parent = GetParent();
4318 if( parent && RelayoutDependentOnParent( dimension ) )
4320 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4323 // Children dependency check
4324 if( RelayoutDependentOnChildren( dimension ) )
4326 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4328 Dali::Actor child = GetChildAt( i );
4329 Actor& childImpl = GetImplementation( child );
4331 // Only relayout child first if it is not dependent on this actor
4332 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4334 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4339 // For deriving classes
4340 OnCalculateRelayoutSize( dimension );
4342 // All dependencies checked, calculate the size and set negotiated flag
4343 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4345 SetNegotiatedDimension( newSize, dimension );
4346 SetLayoutNegotiated( true, dimension );
4348 // For deriving classes
4349 OnLayoutNegotiated( newSize, dimension );
4351 // This actor has been successfully processed, pop it off the recursion stack
4352 recursionStack.pop_back();
4356 // TODO: Break infinite loop
4357 SetLayoutNegotiated( true, dimension );
4362 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4364 // Negotiate all dimensions that require it
4365 ActorDimensionStack recursionStack;
4367 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4369 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4372 NegotiateDimension( dimension, allocatedSize, recursionStack );
4376 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4378 switch( mRelayoutData->sizeSetPolicy )
4380 case SizeScalePolicy::USE_SIZE_SET:
4385 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4387 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4388 const Vector3 naturalSize = GetNaturalSize();
4389 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4391 const float sizeRatio = size.width / size.height;
4392 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4394 if( naturalSizeRatio < sizeRatio )
4396 return Vector2( naturalSizeRatio * size.height, size.height );
4398 else if( naturalSizeRatio > sizeRatio )
4400 return Vector2( size.width, size.width / naturalSizeRatio );
4411 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4413 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4414 const Vector3 naturalSize = GetNaturalSize();
4415 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4417 const float sizeRatio = size.width / size.height;
4418 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4420 if( naturalSizeRatio < sizeRatio )
4422 return Vector2( size.width, size.width / naturalSizeRatio );
4424 else if( naturalSizeRatio > sizeRatio )
4426 return Vector2( naturalSizeRatio * size.height, size.height );
4444 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4446 // Do the set actor size
4447 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4449 // Adjust for size set policy
4450 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4452 // Lock the flag to stop recursive relayouts on set size
4453 mRelayoutData->insideRelayout = true;
4454 SetSize( negotiatedSize );
4455 mRelayoutData->insideRelayout = false;
4457 // Clear flags for all dimensions
4458 SetLayoutDirty( false );
4460 // Give deriving classes a chance to respond
4461 OnRelayout( negotiatedSize, container );
4463 if( !mOnRelayoutSignal.Empty() )
4465 Dali::Actor handle( this );
4466 mOnRelayoutSignal.Emit( handle );
4470 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4472 // Do the negotiation
4473 NegotiateDimensions( allocatedSize );
4475 // Set the actor size
4476 SetNegotiatedSize( container );
4478 // Negotiate down to children
4479 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4481 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4483 Dali::Actor child = GetChildAt( i );
4485 // Only relayout if required
4486 if( GetImplementation( child ).RelayoutRequired() )
4488 container.Add( child, newBounds );
4493 void Actor::RelayoutRequest( Dimension::Type dimension )
4495 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4496 if( relayoutController )
4498 Dali::Actor self( this );
4499 relayoutController->RequestRelayout( self, dimension );
4503 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4507 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4511 void Actor::SetPreferredSize( const Vector2& size )
4513 EnsureRelayoutData();
4515 if( size.width > 0.0f )
4517 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4520 if( size.height > 0.0f )
4522 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4525 mRelayoutData->preferredSize = size;
4530 Vector2 Actor::GetPreferredSize() const
4532 if ( mRelayoutData )
4534 return mRelayoutData->preferredSize;
4537 return GetDefaultPreferredSize();
4540 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4542 EnsureRelayoutData();
4544 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4546 if( dimension & ( 1 << i ) )
4548 mRelayoutData->minimumSize[ i ] = size;
4555 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4557 if ( mRelayoutData )
4559 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4561 if( dimension & ( 1 << i ) )
4563 return mRelayoutData->minimumSize[ i ];
4568 return 0.0f; // Default
4571 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4573 EnsureRelayoutData();
4575 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4577 if( dimension & ( 1 << i ) )
4579 mRelayoutData->maximumSize[ i ] = size;
4586 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4588 if ( mRelayoutData )
4590 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4592 if( dimension & ( 1 << i ) )
4594 return mRelayoutData->maximumSize[ i ];
4599 return FLT_MAX; // Default
4602 } // namespace Internal