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;
107 * Struct to collect relayout variables
109 struct Actor::RelayoutData
112 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
114 // Set size negotiation defaults
115 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
117 resizePolicies[ i ] = ResizePolicy::DEFAULT;
118 negotiatedDimensions[ i ] = 0.0f;
119 dimensionNegotiated[ i ] = false;
120 dimensionDirty[ i ] = false;
121 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
122 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
123 minimumSize[ i ] = 0.0f;
124 maximumSize[ i ] = FLT_MAX;
128 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
130 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
132 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
134 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
136 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
137 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
139 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
140 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
142 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
144 Vector2 preferredSize; ///< The preferred size of the actor
146 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
148 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
149 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
152 #ifdef DALI_DYNAMICS_SUPPORT
154 // Encapsulate actor related dynamics data
157 DynamicsData( Actor* slotOwner )
158 : slotDelegate( slotOwner )
162 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
163 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
165 DynamicsBodyPtr body;
166 JointContainer joints;
167 ReferencedJointContainer referencedJoints;
169 SlotDelegate< Actor > slotDelegate;
172 #endif // DALI_DYNAMICS_SUPPORT
174 namespace // unnamed namespace
180 * We want to discourage the use of property strings (minimize string comparisons),
181 * particularly for the default properties.
182 * Name Type writable animatable constraint-input enum for index-checking
184 DALI_PROPERTY_TABLE_BEGIN
185 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
186 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
187 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
188 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
189 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
190 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
191 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
192 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
193 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
194 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
195 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
196 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
197 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
198 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
199 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
200 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
201 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
202 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
203 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
204 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
205 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
206 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
207 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
208 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
209 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
210 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
211 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
212 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
213 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
214 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
215 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
216 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
217 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
218 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
219 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
220 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
221 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
222 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
223 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
224 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
225 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
226 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
227 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
228 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
229 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
230 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
231 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
232 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
233 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
234 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
235 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
236 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
237 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
241 const char* const SIGNAL_TOUCHED = "touched";
242 const char* const SIGNAL_HOVERED = "hovered";
243 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
244 const char* const SIGNAL_ON_STAGE = "on-stage";
245 const char* const SIGNAL_OFF_STAGE = "off-stage";
249 const char* const ACTION_SHOW = "show";
250 const char* const ACTION_HIDE = "hide";
252 BaseHandle CreateActor()
254 return Dali::Actor::New();
257 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
259 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
264 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
265 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
268 * @brief Extract a given dimension from a Vector2
270 * @param[in] values The values to extract from
271 * @param[in] dimension The dimension to extract
272 * @return Return the value for the dimension
274 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
278 case Dimension::WIDTH:
283 case Dimension::HEIGHT:
285 return values.height;
298 * @brief Extract a given dimension from a Vector3
300 * @param[in] values The values to extract from
301 * @param[in] dimension The dimension to extract
302 * @return Return the value for the dimension
304 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
306 return GetDimensionValue( values.GetVectorXY(), dimension );
309 } // unnamed namespace
311 ActorPtr Actor::New()
313 ActorPtr actor( new Actor( BASIC ) );
315 // Second-phase construction
321 const std::string& Actor::GetName() const
326 void Actor::SetName( const std::string& name )
332 // ATTENTION: string for debug purposes is not thread safe.
333 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
337 unsigned int Actor::GetId() const
342 void Actor::Attach( ActorAttachment& attachment )
344 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
348 attachment.Connect();
351 mAttachment = ActorAttachmentPtr( &attachment );
354 ActorAttachmentPtr Actor::GetAttachment()
359 bool Actor::OnStage() const
364 Dali::Layer Actor::GetLayer()
368 // Short-circuit for Layer derived actors
371 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
374 // Find the immediate Layer parent
375 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
377 if( parent->IsLayer() )
379 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
386 void Actor::Add( Actor& child )
388 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
389 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
393 mChildren = new ActorContainer;
396 Actor* const oldParent( child.mParent );
398 // child might already be ours
399 if( this != oldParent )
401 // if we already have parent, unparent us first
404 oldParent->Remove( child ); // This causes OnChildRemove callback
406 // Old parent may need to readjust to missing child
407 if( oldParent->RelayoutDependentOnChildren() )
409 oldParent->RelayoutRequest();
413 // Guard against Add() during previous OnChildRemove callback
416 // Do this first, since user callbacks from within SetParent() may need to remove child
417 mChildren->push_back( Dali::Actor( &child ) );
419 // SetParent asserts that child can be added
420 child.SetParent( this );
422 // Notification for derived classes
425 // Only put in a relayout request if there is a suitable dependency
426 if( RelayoutDependentOnChildren() )
434 void Actor::Insert( unsigned int index, Actor& child )
436 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
437 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
441 mChildren = new ActorContainer;
444 Actor* const oldParent( child.mParent );
446 // since an explicit position has been given, always insert, even if already a child
449 oldParent->Remove( child ); // This causes OnChildRemove callback
451 // Old parent may need to readjust to missing child
452 if( oldParent->RelayoutDependentOnChildren() )
454 oldParent->RelayoutRequest();
458 // Guard against Add() during previous OnChildRemove callback
461 // Do this first, since user callbacks from within SetParent() may need to remove child
462 if( index < GetChildCount() )
464 ActorIter it = mChildren->begin();
465 std::advance( it, index );
466 mChildren->insert( it, Dali::Actor( &child ) );
470 mChildren->push_back( Dali::Actor( &child ) );
472 // SetParent asserts that child can be added
473 child.SetParent( this, index );
475 // Notification for derived classes
478 // Only put in a relayout request if there is a suitable dependency
479 if( RelayoutDependentOnChildren() )
484 if( child.RelayoutDependentOnParent() )
486 child.RelayoutRequest();
491 void Actor::Remove( Actor& child )
493 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
503 // Find the child in mChildren, and unparent it
504 ActorIter end = mChildren->end();
505 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
507 Actor& actor = GetImplementation( *iter );
509 if( &actor == &child )
511 // Keep handle for OnChildRemove notification
512 removed = Dali::Actor( &actor );
514 // Do this first, since user callbacks from within SetParent() may need to add the child
515 mChildren->erase( iter );
517 DALI_ASSERT_DEBUG( actor.GetParent() == this );
518 actor.SetParent( NULL );
526 // Notification for derived classes
527 OnChildRemove( GetImplementation( removed ) );
529 // Only put in a relayout request if there is a suitable dependency
530 if( RelayoutDependentOnChildren() )
537 void Actor::Unparent()
541 // Remove this actor from the parent. The remove will put a relayout request in for
542 // the parent if required
543 mParent->Remove( *this );
544 // mParent is now NULL!
548 unsigned int Actor::GetChildCount() const
550 return ( NULL != mChildren ) ? mChildren->size() : 0;
553 Dali::Actor Actor::GetChildAt( unsigned int index ) const
555 DALI_ASSERT_ALWAYS( index < GetChildCount() );
557 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
560 ActorPtr Actor::FindChildByName( const std::string& actorName )
563 if( actorName == mName )
569 ActorIter end = mChildren->end();
570 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
572 child = GetImplementation( *iter ).FindChildByName( actorName );
583 ActorPtr Actor::FindChildById( const unsigned int id )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = GetImplementation( *iter ).FindChildById( id );
606 void Actor::SetParentOrigin( const Vector3& origin )
610 // mNode is being used in a separate thread; queue a message to set the value & base value
611 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
614 // Cache for event-thread access
617 // not allocated, check if different from default
618 if( ParentOrigin::DEFAULT != origin )
620 mParentOrigin = new Vector3( origin );
625 // check if different from current costs more than just set
626 *mParentOrigin = origin;
630 void Actor::SetParentOriginX( float x )
632 const Vector3& current = GetCurrentParentOrigin();
634 SetParentOrigin( Vector3( x, current.y, current.z ) );
637 void Actor::SetParentOriginY( float y )
639 const Vector3& current = GetCurrentParentOrigin();
641 SetParentOrigin( Vector3( current.x, y, current.z ) );
644 void Actor::SetParentOriginZ( float z )
646 const Vector3& current = GetCurrentParentOrigin();
648 SetParentOrigin( Vector3( current.x, current.y, z ) );
651 const Vector3& Actor::GetCurrentParentOrigin() const
653 // Cached for event-thread access
654 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
657 void Actor::SetAnchorPoint( const Vector3& anchor )
661 // mNode is being used in a separate thread; queue a message to set the value & base value
662 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
665 // Cache for event-thread access
668 // not allocated, check if different from default
669 if( AnchorPoint::DEFAULT != anchor )
671 mAnchorPoint = new Vector3( anchor );
676 // check if different from current costs more than just set
677 *mAnchorPoint = anchor;
681 void Actor::SetAnchorPointX( float x )
683 const Vector3& current = GetCurrentAnchorPoint();
685 SetAnchorPoint( Vector3( x, current.y, current.z ) );
688 void Actor::SetAnchorPointY( float y )
690 const Vector3& current = GetCurrentAnchorPoint();
692 SetAnchorPoint( Vector3( current.x, y, current.z ) );
695 void Actor::SetAnchorPointZ( float z )
697 const Vector3& current = GetCurrentAnchorPoint();
699 SetAnchorPoint( Vector3( current.x, current.y, z ) );
702 const Vector3& Actor::GetCurrentAnchorPoint() const
704 // Cached for event-thread access
705 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
708 void Actor::SetPosition( float x, float y )
710 SetPosition( Vector3( x, y, 0.0f ) );
713 void Actor::SetPosition( float x, float y, float z )
715 SetPosition( Vector3( x, y, z ) );
718 void Actor::SetPosition( const Vector3& position )
720 mTargetPosition = position;
724 // mNode is being used in a separate thread; queue a message to set the value & base value
725 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
729 void Actor::SetX( float x )
731 mTargetPosition.x = x;
735 // mNode is being used in a separate thread; queue a message to set the value & base value
736 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
740 void Actor::SetY( float y )
742 mTargetPosition.y = y;
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
751 void Actor::SetZ( float z )
753 mTargetPosition.z = z;
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>::BakeZ, z );
762 void Actor::TranslateBy( const Vector3& distance )
764 mTargetPosition += distance;
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
773 const Vector3& Actor::GetCurrentPosition() const
777 // mNode is being used in a separate thread; copy the value from the previous update
778 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
781 return Vector3::ZERO;
784 const Vector3& Actor::GetTargetPosition() const
786 return mTargetPosition;
789 const Vector3& Actor::GetCurrentWorldPosition() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 return Vector3::ZERO;
800 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
802 // this flag is not animatable so keep the value
803 mPositionInheritanceMode = mode;
806 // mNode is being used in a separate thread; queue a message to set the value
807 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
811 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
813 // Cached for event-thread access
814 return mPositionInheritanceMode;
817 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
819 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
820 normalizedAxis.Normalize();
822 Quaternion orientation( angle, normalizedAxis );
824 SetOrientation( orientation );
827 void Actor::SetOrientation( const Quaternion& orientation )
831 // mNode is being used in a separate thread; queue a message to set the value & base value
832 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
836 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
840 // mNode is being used in a separate thread; queue a message to set the value & base value
841 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
845 void Actor::RotateBy( const Quaternion& relativeRotation )
849 // mNode is being used in a separate thread; queue a message to set the value & base value
850 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
854 const Quaternion& Actor::GetCurrentOrientation() const
858 // mNode is being used in a separate thread; copy the value from the previous update
859 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
862 return Quaternion::IDENTITY;
865 const Quaternion& Actor::GetCurrentWorldOrientation() const
869 // mNode is being used in a separate thread; copy the value from the previous update
870 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
873 return Quaternion::IDENTITY;
876 void Actor::SetScale( float scale )
878 SetScale( Vector3( scale, scale, scale ) );
881 void Actor::SetScale( float x, float y, float z )
883 SetScale( Vector3( x, y, z ) );
886 void Actor::SetScale( const Vector3& scale )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
895 void Actor::SetScaleX( float x )
899 // mNode is being used in a separate thread; queue a message to set the value & base value
900 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
904 void Actor::SetScaleY( float y )
908 // mNode is being used in a separate thread; queue a message to set the value & base value
909 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
913 void Actor::SetScaleZ( float z )
917 // mNode is being used in a separate thread; queue a message to set the value & base value
918 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
922 void Actor::SetInitialVolume( const Vector3& volume )
926 // mNode is being used in a separate thread; queue a message to set the value
927 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
931 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
935 // mNode is being used in a separate thread; queue a message to set the value
936 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
940 bool Actor::GetTransmitGeometryScaling() const
944 // mNode is being used in a separate thread; copy the value from the previous update
945 return mNode->GetTransmitGeometryScaling();
951 void Actor::ScaleBy( const Vector3& relativeScale )
955 // mNode is being used in a separate thread; queue a message to set the value & base value
956 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
960 const Vector3& Actor::GetCurrentScale() const
964 // mNode is being used in a separate thread; copy the value from the previous update
965 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
971 const Vector3& Actor::GetCurrentWorldScale() const
975 // mNode is being used in a separate thread; copy the value from the previous update
976 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
982 void Actor::SetInheritScale( bool inherit )
984 // non animateable so keep local copy
985 mInheritScale = inherit;
988 // mNode is being used in a separate thread; queue a message to set the value
989 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
993 bool Actor::IsScaleInherited() const
995 return mInheritScale;
998 Matrix Actor::GetCurrentWorldMatrix() const
1002 // World matrix is no longer updated unless there is something observing the node.
1003 // Need to calculate it from node's world position, orientation and scale:
1004 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1005 Matrix worldMatrix(false);
1006 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1007 mNode->GetWorldOrientation( updateBufferIndex ),
1008 mNode->GetWorldPosition( updateBufferIndex ) );
1012 return Matrix::IDENTITY;
1015 void Actor::SetVisible( bool visible )
1019 // mNode is being used in a separate thread; queue a message to set the value & base value
1020 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1024 bool Actor::IsVisible() const
1028 // mNode is being used in a separate thread; copy the value from the previous update
1029 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1035 void Actor::SetOpacity( float opacity )
1039 // mNode is being used in a separate thread; queue a message to set the value & base value
1040 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1044 float Actor::GetCurrentOpacity() const
1048 // mNode is being used in a separate thread; copy the value from the previous update
1049 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1055 const Vector4& Actor::GetCurrentWorldColor() const
1059 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1062 return Color::WHITE;
1065 void Actor::SetColor( const Vector4& color )
1069 // mNode is being used in a separate thread; queue a message to set the value & base value
1070 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1074 void Actor::SetColorRed( float red )
1078 // mNode is being used in a separate thread; queue a message to set the value & base value
1079 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1083 void Actor::SetColorGreen( float green )
1087 // mNode is being used in a separate thread; queue a message to set the value & base value
1088 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1092 void Actor::SetColorBlue( float blue )
1096 // mNode is being used in a separate thread; queue a message to set the value & base value
1097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1101 const Vector4& Actor::GetCurrentColor() const
1105 // mNode is being used in a separate thread; copy the value from the previous update
1106 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1109 return Color::WHITE;
1112 void Actor::SetInheritOrientation( bool inherit )
1114 // non animateable so keep local copy
1115 mInheritOrientation = inherit;
1118 // mNode is being used in a separate thread; queue a message to set the value
1119 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1123 bool Actor::IsOrientationInherited() const
1125 return mInheritOrientation;
1128 void Actor::SetSizeModeFactor( const Vector3& factor )
1130 EnsureRelayoutData();
1132 mRelayoutData->sizeModeFactor = factor;
1135 const Vector3& Actor::GetSizeModeFactor() const
1137 EnsureRelayoutData();
1139 return mRelayoutData->sizeModeFactor;
1142 void Actor::SetColorMode( ColorMode colorMode )
1144 // non animateable so keep local copy
1145 mColorMode = colorMode;
1148 // mNode is being used in a separate thread; queue a message to set the value
1149 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1153 ColorMode Actor::GetColorMode() const
1155 // we have cached copy
1159 void Actor::SetSize( float width, float height )
1161 SetSize( Vector2( width, height ) );
1164 void Actor::SetSize( float width, float height, float depth )
1166 SetSize( Vector3( width, height, depth ) );
1169 void Actor::SetSize( const Vector2& size )
1171 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1174 void Actor::SetSizeInternal( const Vector2& size )
1176 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1179 float Actor::CalculateSizeZ( const Vector2& size ) const
1181 return std::min( size.width, size.height );
1184 void Actor::SetSize( const Vector3& size )
1186 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1188 SetPreferredSize( size.GetVectorXY() );
1192 SetSizeInternal( size );
1196 void Actor::SetSizeInternal( const Vector3& size )
1198 // dont allow recursive loop
1199 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1200 // 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
1201 if( ( NULL != mNode )&&
1202 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1203 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1204 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1208 // mNode is being used in a separate thread; queue a message to set the value & base value
1209 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1211 // Notification for derived classes
1212 mInsideOnSizeSet = true;
1213 OnSizeSet( mTargetSize );
1214 mInsideOnSizeSet = false;
1216 // Raise a relayout request if the flag is not locked
1217 if( mRelayoutData && !mRelayoutData->insideRelayout )
1224 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1226 mTargetSize = targetSize;
1228 // Notify deriving classes
1229 OnSizeAnimation( animation, mTargetSize );
1232 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1234 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1236 mTargetSize.width = targetSize;
1238 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1240 mTargetSize.height = targetSize;
1242 // Notify deriving classes
1243 OnSizeAnimation( animation, mTargetSize );
1246 void Actor::SetWidth( float width )
1250 // mNode is being used in a separate thread; queue a message to set the value & base value
1251 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1255 void Actor::SetHeight( float height )
1259 // mNode is being used in a separate thread; queue a message to set the value & base value
1260 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1264 void Actor::SetDepth( float depth )
1268 // mNode is being used in a separate thread; queue a message to set the value & base value
1269 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1273 const Vector3& Actor::GetTargetSize() const
1278 const Vector3& Actor::GetCurrentSize() const
1282 // mNode is being used in a separate thread; copy the value from the previous update
1283 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1286 return Vector3::ZERO;
1289 Vector3 Actor::GetNaturalSize() const
1291 // It is up to deriving classes to return the appropriate natural size
1292 return Vector3( 0.0f, 0.0f, 0.0f );
1295 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1297 EnsureRelayoutData();
1299 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1301 if( dimension & ( 1 << i ) )
1303 mRelayoutData->resizePolicies[ i ] = policy;
1307 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1309 if( dimension & Dimension::WIDTH )
1311 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1314 if( dimension & Dimension::HEIGHT )
1316 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1320 // If calling SetResizePolicy, assume we want relayout enabled
1321 SetRelayoutEnabled( true );
1323 OnSetResizePolicy( policy, dimension );
1325 // Trigger relayout on this control
1329 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1331 EnsureRelayoutData();
1333 // If more than one dimension is requested, just return the first one found
1334 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1336 if( ( dimension & ( 1 << i ) ) )
1338 return mRelayoutData->resizePolicies[ i ];
1342 return ResizePolicy::DEFAULT;
1345 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1347 EnsureRelayoutData();
1349 mRelayoutData->sizeSetPolicy = policy;
1352 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1354 EnsureRelayoutData();
1356 return mRelayoutData->sizeSetPolicy;
1359 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1361 EnsureRelayoutData();
1363 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1365 if( dimension & ( 1 << i ) )
1367 mRelayoutData->dimensionDependencies[ i ] = dependency;
1372 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1374 EnsureRelayoutData();
1376 // If more than one dimension is requested, just return the first one found
1377 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1379 if( ( dimension & ( 1 << i ) ) )
1381 return mRelayoutData->dimensionDependencies[ i ];
1385 return Dimension::ALL_DIMENSIONS; // Default
1388 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1390 // If relayout data has not been allocated yet and the client is requesting
1391 // to disable it, do nothing
1392 if( mRelayoutData || relayoutEnabled )
1394 EnsureRelayoutData();
1396 mRelayoutData->relayoutEnabled = relayoutEnabled;
1400 bool Actor::IsRelayoutEnabled() const
1402 // Assume that if relayout data has not been allocated yet then
1403 // relayout is disabled
1404 return mRelayoutData && mRelayoutData->relayoutEnabled;
1407 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1409 EnsureRelayoutData();
1411 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1413 if( dimension & ( 1 << i ) )
1415 mRelayoutData->dimensionDirty[ i ] = dirty;
1420 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1422 EnsureRelayoutData();
1424 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1426 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1435 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1437 EnsureRelayoutData();
1439 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1442 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1444 EnsureRelayoutData();
1446 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1449 #ifdef DALI_DYNAMICS_SUPPORT
1451 //--------------- Dynamics ---------------
1453 void Actor::DisableDynamics()
1455 if( NULL != mDynamicsData )
1457 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1459 // ensure dynamics object are disconnected from scene
1460 DisconnectDynamics();
1462 // delete joint owned by this actor
1463 while( !mDynamicsData->joints.empty() )
1465 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1468 // delete other joints referencing this actor
1469 while( !mDynamicsData->referencedJoints.empty() )
1471 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1472 ActorPtr jointOwner( joint->GetActor( true ) );
1475 jointOwner->RemoveDynamicsJoint( joint );
1479 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1482 // delete the DynamicsBody object
1483 mDynamicsData->body.Reset();
1485 // Discard Dynamics data structure
1486 delete mDynamicsData;
1487 mDynamicsData = NULL;
1491 DynamicsBodyPtr Actor::GetDynamicsBody() const
1493 DynamicsBodyPtr body;
1495 if( NULL != mDynamicsData )
1497 body = mDynamicsData->body;
1503 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1505 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1507 if( NULL == mDynamicsData )
1509 mDynamicsData = new DynamicsData( this );
1512 if( !mDynamicsData->body )
1514 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1518 DynamicsWorldPtr world( DynamicsWorld::Get() );
1521 if( mParent == world->GetRootActor().Get() )
1523 mDynamicsData->body->Connect( GetEventThreadServices() );
1529 return mDynamicsData->body;
1532 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1534 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1535 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1538 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1540 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1541 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1543 DynamicsJointPtr joint;
1545 DynamicsWorldPtr world( DynamicsWorld::Get() );
1549 if( NULL != mDynamicsData )
1551 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1553 if( mDynamicsData->joints.end() != it )
1555 // use existing joint
1561 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1562 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1566 bodyA = EnableDynamics( new DynamicsBodyConfig );
1571 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1574 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1575 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1577 if( OnStage() && attachedActor->OnStage() )
1579 joint->Connect( GetEventThreadServices() );
1582 attachedActor->ReferenceJoint( joint );
1584 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1585 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1592 const int Actor::GetNumberOfJoints() const
1594 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1597 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1599 DynamicsJointPtr joint;
1601 if( NULL != mDynamicsData )
1603 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1605 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1607 for( int i = 0; i < index; ++i )
1619 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1621 DynamicsJointPtr joint;
1623 if( NULL != mDynamicsData )
1625 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1627 if( mDynamicsData->joints.end() != it )
1629 // use existing joint
1637 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1639 if( NULL != mDynamicsData )
1641 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1642 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1644 for(; it != endIt; ++it )
1646 if( it->second == joint.Get() )
1648 ActorPtr attachedActor( it->first );
1650 if( OnStage() && attachedActor && attachedActor->OnStage() )
1652 joint->Disconnect( GetEventThreadServices() );
1657 attachedActor->ReleaseJoint( joint );
1658 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1659 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1662 mDynamicsData->joints.erase(it);
1669 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1671 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1673 if( NULL != mDynamicsData )
1675 mDynamicsData->referencedJoints.push_back(joint);
1679 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1681 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1683 if( NULL != mDynamicsData )
1685 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1687 if( it != mDynamicsData->referencedJoints.end() )
1689 mDynamicsData->referencedJoints.erase( it );
1694 void Actor::SetDynamicsRoot(bool flag)
1696 if( mIsDynamicsRoot != flag )
1698 mIsDynamicsRoot = flag;
1700 if( OnStage() && mChildren )
1702 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1703 ActorIter end = mChildren->end();
1704 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1706 Actor& child = GetImplementation(*iter);
1708 if( child.GetDynamicsBody() )
1710 if( mIsDynamicsRoot )
1712 child.ConnectDynamics();
1716 child.DisconnectDynamics();
1724 bool Actor::IsDynamicsRoot() const
1726 return mIsDynamicsRoot;
1729 void Actor::AttachedActorOnStage( Dali::Actor actor )
1731 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1735 ActorPtr attachedActor( &GetImplementation(actor) );
1737 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1738 if( NULL != mDynamicsData )
1740 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1741 if( mDynamicsData->joints.end() != it )
1743 DynamicsJointPtr joint( it->second );
1744 joint->Connect( GetEventThreadServices() );
1750 void Actor::AttachedActorOffStage( Dali::Actor actor )
1752 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1756 ActorPtr attachedActor( &GetImplementation(actor) );
1758 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1759 if( NULL != mDynamicsData )
1761 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1762 if( mDynamicsData->joints.end() != it )
1764 DynamicsJointPtr joint( it->second );
1765 joint->Disconnect( GetEventThreadServices() );
1771 void Actor::ConnectDynamics()
1773 if( NULL != mDynamicsData && mDynamicsData->body )
1775 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1777 mDynamicsData->body->Connect( GetEventThreadServices() );
1779 // Connect all joints where attachedActor is also on stage
1780 if( !mDynamicsData->joints.empty() )
1782 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1783 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1785 for(; it != endIt; ++it )
1787 Actor* attachedActor( it->first );
1788 if( NULL != attachedActor && attachedActor->OnStage() )
1790 DynamicsJointPtr joint( it->second );
1792 joint->Connect( GetEventThreadServices() );
1800 void Actor::DisconnectDynamics()
1802 if( NULL != mDynamicsData && mDynamicsData->body )
1806 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1808 // Disconnect all joints
1809 if( !mDynamicsData->joints.empty() )
1811 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1812 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1814 for(; it != endIt; ++it )
1816 DynamicsJointPtr joint( it->second );
1818 joint->Disconnect( GetEventThreadServices() );
1825 #endif // DALI_DYNAMICS_SUPPORT
1827 void Actor::SetOverlay( bool enable )
1829 // Setting STENCIL will override OVERLAY
1830 if( DrawMode::STENCIL != mDrawMode )
1832 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1836 bool Actor::IsOverlay() const
1838 return ( DrawMode::OVERLAY == mDrawMode );
1841 void Actor::SetDrawMode( DrawMode::Type drawMode )
1843 // this flag is not animatable so keep the value
1844 mDrawMode = drawMode;
1847 // mNode is being used in a separate thread; queue a message to set the value
1848 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1852 DrawMode::Type Actor::GetDrawMode() const
1857 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1859 // only valid when on-stage
1862 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1864 Vector2 converted( screenX, screenY );
1866 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1867 const int taskCount = taskList.GetTaskCount();
1868 for( int i = taskCount - 1; i >= 0; --i )
1870 Dali::RenderTask task = taskList.GetTask( i );
1871 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1873 // found a task where this conversion was ok so return
1881 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1883 bool retval = false;
1884 // only valid when on-stage
1887 CameraActor* camera = renderTask.GetCameraActor();
1891 renderTask.GetViewport( viewport );
1893 // need to translate coordinates to render tasks coordinate space
1894 Vector2 converted( screenX, screenY );
1895 if( renderTask.TranslateCoordinates( converted ) )
1897 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1904 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1906 // Early-out if mNode is NULL
1912 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1914 // Calculate the ModelView matrix
1915 Matrix modelView( false/*don't init*/);
1916 // need to use the components as world matrix is only updated for actors that need it
1917 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1918 Matrix::Multiply( modelView, modelView, viewMatrix );
1920 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1921 Matrix invertedMvp( false/*don't init*/);
1922 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1923 bool success = invertedMvp.Invert();
1925 // Convert to GL coordinates
1926 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1931 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1938 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1944 if( XyPlaneIntersect( nearPos, farPos, local ) )
1946 Vector3 size = GetCurrentSize();
1947 localX = local.x + size.x * 0.5f;
1948 localY = local.y + size.y * 0.5f;
1959 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1962 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1964 Mathematical Formulation
1966 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1968 ( p - c ) dot ( p - c ) = r^2
1970 Given a ray with a point of origin 'o', and a direction vector 'd':
1972 ray(t) = o + td, t >= 0
1974 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1976 (o + td - c ) dot ( o + td - c ) = r^2
1978 To solve for t we first expand the above into a more recognisable quadratic equation form
1980 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1989 B = 2( o - c ) dot d
1990 C = ( o - c ) dot ( o - c ) - r^2
1992 which can be solved using a standard quadratic formula.
1994 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1996 Practical Simplification
1998 In a renderer, we often differentiate between world space and object space. In the object space
1999 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2000 into object space, the mathematical solution presented above can be simplified significantly.
2002 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2006 and we can find the t at which the (transformed) ray intersects the sphere by
2008 ( o + td ) dot ( o + td ) = r^2
2010 According to the reasoning above, we expand the above quadratic equation into the general form
2014 which now has coefficients:
2021 // Early out if mNode is NULL
2027 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2029 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2030 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2031 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2033 // Compute the radius is not needed, square radius it's enough.
2034 const Vector3& size( mNode->GetSize( bufferIndex ) );
2036 // Scale the sphere.
2037 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2039 const float width = size.width * scale.width;
2040 const float height = size.height * scale.height;
2042 float squareSphereRadius = 0.5f * ( width * width + height * height );
2044 float a = rayDir.Dot( rayDir ); // a
2045 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2046 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2048 return ( b2 * b2 - a * c ) >= 0.f;
2051 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2058 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2060 // Transforms the ray to the local reference system.
2062 // Calculate the inverse of Model matrix
2063 Matrix invModelMatrix( false/*don't init*/);
2064 // need to use the components as world matrix is only updated for actors that need it
2065 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2067 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2068 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2070 // Test with the actor's XY plane (Normal = 0 0 1 1).
2072 float a = -rayOriginLocal.z;
2073 float b = rayDirLocal.z;
2075 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2077 // Ray travels distance * rayDirLocal to intersect with plane.
2080 const Vector3& size = mNode->GetSize( bufferIndex );
2082 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2083 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2085 // Test with the actor's geometry.
2086 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2093 void Actor::SetLeaveRequired( bool required )
2095 mLeaveRequired = required;
2098 bool Actor::GetLeaveRequired() const
2100 return mLeaveRequired;
2103 void Actor::SetKeyboardFocusable( bool focusable )
2105 mKeyboardFocusable = focusable;
2108 bool Actor::IsKeyboardFocusable() const
2110 return mKeyboardFocusable;
2113 bool Actor::GetTouchRequired() const
2115 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2118 bool Actor::GetHoverRequired() const
2120 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2123 bool Actor::GetWheelEventRequired() const
2125 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2128 bool Actor::IsHittable() const
2130 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2133 ActorGestureData& Actor::GetGestureData()
2135 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2136 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2137 if( NULL == mGestureData )
2139 mGestureData = new ActorGestureData;
2141 return *mGestureData;
2144 bool Actor::IsGestureRequred( Gesture::Type type ) const
2146 return mGestureData && mGestureData->IsGestureRequred( type );
2149 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2151 bool consumed = false;
2153 if( !mTouchedSignal.Empty() )
2155 Dali::Actor handle( this );
2156 consumed = mTouchedSignal.Emit( handle, event );
2161 // Notification for derived classes
2162 consumed = OnTouchEvent( event );
2168 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2170 bool consumed = false;
2172 if( !mHoveredSignal.Empty() )
2174 Dali::Actor handle( this );
2175 consumed = mHoveredSignal.Emit( handle, event );
2180 // Notification for derived classes
2181 consumed = OnHoverEvent( event );
2187 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2189 bool consumed = false;
2191 if( !mWheelEventSignal.Empty() )
2193 Dali::Actor handle( this );
2194 consumed = mWheelEventSignal.Emit( handle, event );
2199 // Notification for derived classes
2200 consumed = OnWheelEvent( event );
2206 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2208 return mTouchedSignal;
2211 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2213 return mHoveredSignal;
2216 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2218 return mWheelEventSignal;
2221 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2223 return mOnStageSignal;
2226 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2228 return mOffStageSignal;
2231 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2233 return mOnRelayoutSignal;
2236 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2238 bool connected( true );
2239 Actor* actor = dynamic_cast< Actor* >( object );
2241 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2243 actor->TouchedSignal().Connect( tracker, functor );
2245 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2247 actor->HoveredSignal().Connect( tracker, functor );
2249 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2251 actor->WheelEventSignal().Connect( tracker, functor );
2253 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2255 actor->OnStageSignal().Connect( tracker, functor );
2257 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2259 actor->OffStageSignal().Connect( tracker, functor );
2263 // signalName does not match any signal
2270 Actor::Actor( DerivedType derivedType )
2274 mParentOrigin( NULL ),
2275 mAnchorPoint( NULL ),
2276 mRelayoutData( NULL ),
2277 #ifdef DALI_DYNAMICS_SUPPORT
2278 mDynamicsData( NULL ),
2280 mGestureData( NULL ),
2282 mTargetSize( 0.0f, 0.0f, 0.0f ),
2284 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2285 mIsRoot( ROOT_LAYER == derivedType ),
2286 mIsRenderable( RENDERABLE == derivedType ),
2287 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2288 mIsOnStage( false ),
2289 mIsDynamicsRoot( false ),
2291 mLeaveRequired( false ),
2292 mKeyboardFocusable( false ),
2293 mDerivedRequiresTouch( false ),
2294 mDerivedRequiresHover( false ),
2295 mDerivedRequiresWheelEvent( false ),
2296 mOnStageSignalled( false ),
2297 mInsideOnSizeSet( false ),
2298 mInheritOrientation( true ),
2299 mInheritScale( true ),
2300 mDrawMode( DrawMode::NORMAL ),
2301 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2302 mColorMode( Node::DEFAULT_COLOR_MODE )
2306 void Actor::Initialize()
2309 SceneGraph::Node* node = CreateNode();
2311 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2312 mNode = node; // Keep raw-pointer to Node
2316 GetEventThreadServices().RegisterObject( this );
2321 // Remove mParent pointers from children even if we're destroying core,
2322 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2325 ActorConstIter endIter = mChildren->end();
2326 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2328 Actor& actor = GetImplementation( *iter );
2329 actor.SetParent( NULL );
2334 // Guard to allow handle destruction after Core has been destroyed
2335 if( EventThreadServices::IsCoreRunning() )
2339 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2340 mNode = NULL; // Node is about to be destroyed
2343 GetEventThreadServices().UnregisterObject( this );
2346 #ifdef DALI_DYNAMICS_SUPPORT
2348 delete mDynamicsData;
2351 // Cleanup optional gesture data
2352 delete mGestureData;
2354 // Cleanup optional parent origin and anchor
2355 delete mParentOrigin;
2356 delete mAnchorPoint;
2358 // Delete optional relayout data
2361 delete mRelayoutData;
2365 void Actor::ConnectToStage( int index )
2367 // This container is used instead of walking the Actor hierachy.
2368 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2369 ActorContainer connectionList;
2371 // This stage is atomic i.e. not interrupted by user callbacks
2372 RecursiveConnectToStage( connectionList, index );
2374 // Notify applications about the newly connected actors.
2375 const ActorIter endIter = connectionList.end();
2376 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2378 Actor& actor = GetImplementation( *iter );
2379 actor.NotifyStageConnection();
2385 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2387 DALI_ASSERT_ALWAYS( !OnStage() );
2391 ConnectToSceneGraph( index );
2393 // Notification for internal derived classes
2394 OnStageConnectionInternal();
2396 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2397 connectionList.push_back( Dali::Actor( this ) );
2399 // Recursively connect children
2402 ActorConstIter endIter = mChildren->end();
2403 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2405 Actor& actor = GetImplementation( *iter );
2406 actor.RecursiveConnectToStage( connectionList );
2412 * This method is called when the Actor is connected to the Stage.
2413 * The parent must have added its Node to the scene-graph.
2414 * The child must connect its Node to the parent's Node.
2415 * This is resursive; the child calls ConnectToStage() for its children.
2417 void Actor::ConnectToSceneGraph( int index )
2419 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2423 // Reparent Node in next Update
2424 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2427 // Notify attachment
2430 mAttachment->Connect();
2433 #ifdef DALI_DYNAMICS_SUPPORT
2435 if( NULL != mDynamicsData )
2441 // Request relayout on all actors that are added to the scenegraph
2444 // Notification for Object::Observers
2448 void Actor::NotifyStageConnection()
2450 // Actors can be removed (in a callback), before the on-stage stage is reported.
2451 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2452 if( OnStage() && !mOnStageSignalled )
2454 // Notification for external (CustomActor) derived classes
2455 OnStageConnectionExternal();
2457 if( !mOnStageSignal.Empty() )
2459 Dali::Actor handle( this );
2460 mOnStageSignal.Emit( handle );
2463 // Guard against Remove during callbacks
2466 mOnStageSignalled = true; // signal required next time Actor is removed
2471 void Actor::DisconnectFromStage()
2473 // This container is used instead of walking the Actor hierachy.
2474 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2475 ActorContainer disconnectionList;
2477 // This stage is atomic i.e. not interrupted by user callbacks
2478 RecursiveDisconnectFromStage( disconnectionList );
2480 // Notify applications about the newly disconnected actors.
2481 const ActorIter endIter = disconnectionList.end();
2482 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2484 Actor& actor = GetImplementation( *iter );
2485 actor.NotifyStageDisconnection();
2489 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2491 DALI_ASSERT_ALWAYS( OnStage() );
2493 // Recursively disconnect children
2496 ActorConstIter endIter = mChildren->end();
2497 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2499 Actor& actor = GetImplementation( *iter );
2500 actor.RecursiveDisconnectFromStage( disconnectionList );
2504 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2505 disconnectionList.push_back( Dali::Actor( this ) );
2507 // Notification for internal derived classes
2508 OnStageDisconnectionInternal();
2510 DisconnectFromSceneGraph();
2516 * This method is called by an actor or its parent, before a node removal message is sent.
2517 * This is recursive; the child calls DisconnectFromStage() for its children.
2519 void Actor::DisconnectFromSceneGraph()
2521 // Notification for Object::Observers
2522 OnSceneObjectRemove();
2524 // Notify attachment
2527 mAttachment->Disconnect();
2530 #ifdef DALI_DYNAMICS_SUPPORT
2532 if( NULL != mDynamicsData )
2534 DisconnectDynamics();
2539 void Actor::NotifyStageDisconnection()
2541 // Actors can be added (in a callback), before the off-stage state is reported.
2542 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2543 // only do this step if there is a stage, i.e. Core is not being shut down
2544 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2546 // Notification for external (CustomeActor) derived classes
2547 OnStageDisconnectionExternal();
2549 if( !mOffStageSignal.Empty() )
2551 Dali::Actor handle( this );
2552 mOffStageSignal.Emit( handle );
2555 // Guard against Add during callbacks
2558 mOnStageSignalled = false; // signal required next time Actor is added
2563 bool Actor::IsNodeConnected() const
2565 bool connected( false );
2570 if( mNode->IsRoot() || mNode->GetParent() )
2579 unsigned int Actor::GetDefaultPropertyCount() const
2581 return DEFAULT_PROPERTY_COUNT;
2584 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2586 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2588 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2590 indices.PushBack( i );
2594 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2596 if( index < DEFAULT_PROPERTY_COUNT )
2598 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2604 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2606 Property::Index index = Property::INVALID_INDEX;
2608 // Look for name in default properties
2609 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2611 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2612 if( 0 == name.compare( property->name ) )
2622 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2624 if( index < DEFAULT_PROPERTY_COUNT )
2626 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2632 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2634 if( index < DEFAULT_PROPERTY_COUNT )
2636 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2642 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2644 if( index < DEFAULT_PROPERTY_COUNT )
2646 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2652 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2654 if( index < DEFAULT_PROPERTY_COUNT )
2656 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2659 // index out of range...return Property::NONE
2660 return Property::NONE;
2663 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2667 case Dali::Actor::Property::PARENT_ORIGIN:
2669 SetParentOrigin( property.Get< Vector3 >() );
2673 case Dali::Actor::Property::PARENT_ORIGIN_X:
2675 SetParentOriginX( property.Get< float >() );
2679 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2681 SetParentOriginY( property.Get< float >() );
2685 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2687 SetParentOriginZ( property.Get< float >() );
2691 case Dali::Actor::Property::ANCHOR_POINT:
2693 SetAnchorPoint( property.Get< Vector3 >() );
2697 case Dali::Actor::Property::ANCHOR_POINT_X:
2699 SetAnchorPointX( property.Get< float >() );
2703 case Dali::Actor::Property::ANCHOR_POINT_Y:
2705 SetAnchorPointY( property.Get< float >() );
2709 case Dali::Actor::Property::ANCHOR_POINT_Z:
2711 SetAnchorPointZ( property.Get< float >() );
2715 case Dali::Actor::Property::SIZE:
2717 SetSize( property.Get< Vector3 >() );
2721 case Dali::Actor::Property::SIZE_WIDTH:
2723 SetWidth( property.Get< float >() );
2727 case Dali::Actor::Property::SIZE_HEIGHT:
2729 SetHeight( property.Get< float >() );
2733 case Dali::Actor::Property::SIZE_DEPTH:
2735 SetDepth( property.Get< float >() );
2739 case Dali::Actor::Property::POSITION:
2741 SetPosition( property.Get< Vector3 >() );
2745 case Dali::Actor::Property::POSITION_X:
2747 SetX( property.Get< float >() );
2751 case Dali::Actor::Property::POSITION_Y:
2753 SetY( property.Get< float >() );
2757 case Dali::Actor::Property::POSITION_Z:
2759 SetZ( property.Get< float >() );
2763 case Dali::Actor::Property::ORIENTATION:
2765 SetOrientation( property.Get< Quaternion >() );
2769 case Dali::Actor::Property::SCALE:
2771 SetScale( property.Get< Vector3 >() );
2775 case Dali::Actor::Property::SCALE_X:
2777 SetScaleX( property.Get< float >() );
2781 case Dali::Actor::Property::SCALE_Y:
2783 SetScaleY( property.Get< float >() );
2787 case Dali::Actor::Property::SCALE_Z:
2789 SetScaleZ( property.Get< float >() );
2793 case Dali::Actor::Property::VISIBLE:
2795 SetVisible( property.Get< bool >() );
2799 case Dali::Actor::Property::COLOR:
2801 SetColor( property.Get< Vector4 >() );
2805 case Dali::Actor::Property::COLOR_RED:
2807 SetColorRed( property.Get< float >() );
2811 case Dali::Actor::Property::COLOR_GREEN:
2813 SetColorGreen( property.Get< float >() );
2817 case Dali::Actor::Property::COLOR_BLUE:
2819 SetColorBlue( property.Get< float >() );
2823 case Dali::Actor::Property::COLOR_ALPHA:
2825 SetOpacity( property.Get< float >() );
2829 case Dali::Actor::Property::NAME:
2831 SetName( property.Get< std::string >() );
2835 case Dali::Actor::Property::SENSITIVE:
2837 SetSensitive( property.Get< bool >() );
2841 case Dali::Actor::Property::LEAVE_REQUIRED:
2843 SetLeaveRequired( property.Get< bool >() );
2847 case Dali::Actor::Property::INHERIT_ORIENTATION:
2849 SetInheritOrientation( property.Get< bool >() );
2853 case Dali::Actor::Property::INHERIT_SCALE:
2855 SetInheritScale( property.Get< bool >() );
2859 case Dali::Actor::Property::COLOR_MODE:
2861 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2865 case Dali::Actor::Property::POSITION_INHERITANCE:
2867 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2871 case Dali::Actor::Property::DRAW_MODE:
2873 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2877 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2879 SetSizeModeFactor( property.Get< Vector3 >() );
2883 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2885 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2889 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2891 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2895 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2897 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2901 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2903 if( property.Get< bool >() )
2905 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2910 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2912 if( property.Get< bool >() )
2914 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2919 case Dali::Actor::Property::PADDING:
2921 Vector4 padding = property.Get< Vector4 >();
2922 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2923 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2927 case Dali::Actor::Property::MINIMUM_SIZE:
2929 Vector2 size = property.Get< Vector2 >();
2930 SetMinimumSize( size.x, Dimension::WIDTH );
2931 SetMinimumSize( size.y, Dimension::HEIGHT );
2935 case Dali::Actor::Property::MAXIMUM_SIZE:
2937 Vector2 size = property.Get< Vector2 >();
2938 SetMaximumSize( size.x, Dimension::WIDTH );
2939 SetMaximumSize( size.y, Dimension::HEIGHT );
2945 // this can happen in the case of a non-animatable default property so just do nothing
2951 // TODO: This method needs to be removed
2952 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2954 switch( entry.type )
2956 case Property::BOOLEAN:
2958 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2959 DALI_ASSERT_DEBUG( NULL != property );
2961 // property is being used in a separate thread; queue a message to set the property
2962 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2967 case Property::INTEGER:
2969 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2970 DALI_ASSERT_DEBUG( NULL != property );
2972 // property is being used in a separate thread; queue a message to set the property
2973 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2978 case Property::UNSIGNED_INTEGER:
2980 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2981 DALI_ASSERT_DEBUG( NULL != property );
2983 // property is being used in a separate thread; queue a message to set the property
2984 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2989 case Property::FLOAT:
2991 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2992 DALI_ASSERT_DEBUG( NULL != property );
2994 // property is being used in a separate thread; queue a message to set the property
2995 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3000 case Property::VECTOR2:
3002 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3003 DALI_ASSERT_DEBUG( NULL != property );
3005 // property is being used in a separate thread; queue a message to set the property
3006 if(entry.componentIndex == 0)
3008 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3010 else if(entry.componentIndex == 1)
3012 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3016 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3022 case Property::VECTOR3:
3024 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3025 DALI_ASSERT_DEBUG( NULL != property );
3027 // property is being used in a separate thread; queue a message to set the property
3028 if(entry.componentIndex == 0)
3030 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3032 else if(entry.componentIndex == 1)
3034 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3036 else if(entry.componentIndex == 2)
3038 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3042 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3048 case Property::VECTOR4:
3050 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3051 DALI_ASSERT_DEBUG( NULL != property );
3053 // property is being used in a separate thread; queue a message to set the property
3054 if(entry.componentIndex == 0)
3056 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3058 else if(entry.componentIndex == 1)
3060 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3062 else if(entry.componentIndex == 2)
3064 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3066 else if(entry.componentIndex == 3)
3068 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3072 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3078 case Property::ROTATION:
3080 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3081 DALI_ASSERT_DEBUG( NULL != property );
3083 // property is being used in a separate thread; queue a message to set the property
3084 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3089 case Property::MATRIX:
3091 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( 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 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3100 case Property::MATRIX3:
3102 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3103 DALI_ASSERT_DEBUG( NULL != property );
3105 // property is being used in a separate thread; queue a message to set the property
3106 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3113 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3119 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3121 Property::Value value;
3125 case Dali::Actor::Property::PARENT_ORIGIN:
3127 value = GetCurrentParentOrigin();
3131 case Dali::Actor::Property::PARENT_ORIGIN_X:
3133 value = GetCurrentParentOrigin().x;
3137 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3139 value = GetCurrentParentOrigin().y;
3143 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3145 value = GetCurrentParentOrigin().z;
3149 case Dali::Actor::Property::ANCHOR_POINT:
3151 value = GetCurrentAnchorPoint();
3155 case Dali::Actor::Property::ANCHOR_POINT_X:
3157 value = GetCurrentAnchorPoint().x;
3161 case Dali::Actor::Property::ANCHOR_POINT_Y:
3163 value = GetCurrentAnchorPoint().y;
3167 case Dali::Actor::Property::ANCHOR_POINT_Z:
3169 value = GetCurrentAnchorPoint().z;
3173 case Dali::Actor::Property::SIZE:
3175 value = GetCurrentSize();
3179 case Dali::Actor::Property::SIZE_WIDTH:
3181 value = GetCurrentSize().width;
3185 case Dali::Actor::Property::SIZE_HEIGHT:
3187 value = GetCurrentSize().height;
3191 case Dali::Actor::Property::SIZE_DEPTH:
3193 value = GetCurrentSize().depth;
3197 case Dali::Actor::Property::POSITION:
3199 value = GetCurrentPosition();
3203 case Dali::Actor::Property::POSITION_X:
3205 value = GetCurrentPosition().x;
3209 case Dali::Actor::Property::POSITION_Y:
3211 value = GetCurrentPosition().y;
3215 case Dali::Actor::Property::POSITION_Z:
3217 value = GetCurrentPosition().z;
3221 case Dali::Actor::Property::WORLD_POSITION:
3223 value = GetCurrentWorldPosition();
3227 case Dali::Actor::Property::WORLD_POSITION_X:
3229 value = GetCurrentWorldPosition().x;
3233 case Dali::Actor::Property::WORLD_POSITION_Y:
3235 value = GetCurrentWorldPosition().y;
3239 case Dali::Actor::Property::WORLD_POSITION_Z:
3241 value = GetCurrentWorldPosition().z;
3245 case Dali::Actor::Property::ORIENTATION:
3247 value = GetCurrentOrientation();
3251 case Dali::Actor::Property::WORLD_ORIENTATION:
3253 value = GetCurrentWorldOrientation();
3257 case Dali::Actor::Property::SCALE:
3259 value = GetCurrentScale();
3263 case Dali::Actor::Property::SCALE_X:
3265 value = GetCurrentScale().x;
3269 case Dali::Actor::Property::SCALE_Y:
3271 value = GetCurrentScale().y;
3275 case Dali::Actor::Property::SCALE_Z:
3277 value = GetCurrentScale().z;
3281 case Dali::Actor::Property::WORLD_SCALE:
3283 value = GetCurrentWorldScale();
3287 case Dali::Actor::Property::VISIBLE:
3289 value = IsVisible();
3293 case Dali::Actor::Property::COLOR:
3295 value = GetCurrentColor();
3299 case Dali::Actor::Property::COLOR_RED:
3301 value = GetCurrentColor().r;
3305 case Dali::Actor::Property::COLOR_GREEN:
3307 value = GetCurrentColor().g;
3311 case Dali::Actor::Property::COLOR_BLUE:
3313 value = GetCurrentColor().b;
3317 case Dali::Actor::Property::COLOR_ALPHA:
3319 value = GetCurrentColor().a;
3323 case Dali::Actor::Property::WORLD_COLOR:
3325 value = GetCurrentWorldColor();
3329 case Dali::Actor::Property::WORLD_MATRIX:
3331 value = GetCurrentWorldMatrix();
3335 case Dali::Actor::Property::NAME:
3341 case Dali::Actor::Property::SENSITIVE:
3343 value = IsSensitive();
3347 case Dali::Actor::Property::LEAVE_REQUIRED:
3349 value = GetLeaveRequired();
3353 case Dali::Actor::Property::INHERIT_ORIENTATION:
3355 value = IsOrientationInherited();
3359 case Dali::Actor::Property::INHERIT_SCALE:
3361 value = IsScaleInherited();
3365 case Dali::Actor::Property::COLOR_MODE:
3367 value = Scripting::GetColorMode( GetColorMode() );
3371 case Dali::Actor::Property::POSITION_INHERITANCE:
3373 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3377 case Dali::Actor::Property::DRAW_MODE:
3379 value = Scripting::GetDrawMode( GetDrawMode() );
3383 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3385 value = GetSizeModeFactor();
3389 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3391 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3395 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3397 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3401 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3403 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3407 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3409 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3413 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3415 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3419 case Dali::Actor::Property::PADDING:
3421 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3422 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3423 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3427 case Dali::Actor::Property::MINIMUM_SIZE:
3429 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3433 case Dali::Actor::Property::MAXIMUM_SIZE:
3435 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3441 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3449 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3454 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3456 // This method should only return an object connected to the scene-graph
3457 return OnStage() ? mNode : NULL;
3460 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3462 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3464 const PropertyBase* property( NULL );
3466 // This method should only return a property of an object connected to the scene-graph
3472 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3474 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3475 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3477 property = animatable->GetSceneGraphProperty();
3479 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3481 CustomPropertyMetadata* custom = FindCustomProperty( index );
3482 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3484 property = custom->GetSceneGraphProperty();
3486 else if( NULL != mNode )
3490 case Dali::Actor::Property::SIZE:
3491 property = &mNode->mSize;
3494 case Dali::Actor::Property::SIZE_WIDTH:
3495 property = &mNode->mSize;
3498 case Dali::Actor::Property::SIZE_HEIGHT:
3499 property = &mNode->mSize;
3502 case Dali::Actor::Property::SIZE_DEPTH:
3503 property = &mNode->mSize;
3506 case Dali::Actor::Property::POSITION:
3507 property = &mNode->mPosition;
3510 case Dali::Actor::Property::POSITION_X:
3511 property = &mNode->mPosition;
3514 case Dali::Actor::Property::POSITION_Y:
3515 property = &mNode->mPosition;
3518 case Dali::Actor::Property::POSITION_Z:
3519 property = &mNode->mPosition;
3522 case Dali::Actor::Property::ORIENTATION:
3523 property = &mNode->mOrientation;
3526 case Dali::Actor::Property::SCALE:
3527 property = &mNode->mScale;
3530 case Dali::Actor::Property::SCALE_X:
3531 property = &mNode->mScale;
3534 case Dali::Actor::Property::SCALE_Y:
3535 property = &mNode->mScale;
3538 case Dali::Actor::Property::SCALE_Z:
3539 property = &mNode->mScale;
3542 case Dali::Actor::Property::VISIBLE:
3543 property = &mNode->mVisible;
3546 case Dali::Actor::Property::COLOR:
3547 property = &mNode->mColor;
3550 case Dali::Actor::Property::COLOR_RED:
3551 property = &mNode->mColor;
3554 case Dali::Actor::Property::COLOR_GREEN:
3555 property = &mNode->mColor;
3558 case Dali::Actor::Property::COLOR_BLUE:
3559 property = &mNode->mColor;
3562 case Dali::Actor::Property::COLOR_ALPHA:
3563 property = &mNode->mColor;
3574 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3576 const PropertyInputImpl* property( NULL );
3578 // This method should only return a property of an object connected to the scene-graph
3584 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3586 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3587 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3589 property = animatable->GetSceneGraphProperty();
3591 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3593 CustomPropertyMetadata* custom = FindCustomProperty( index );
3594 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3595 property = custom->GetSceneGraphProperty();
3597 else if( NULL != mNode )
3601 case Dali::Actor::Property::PARENT_ORIGIN:
3602 property = &mNode->mParentOrigin;
3605 case Dali::Actor::Property::PARENT_ORIGIN_X:
3606 property = &mNode->mParentOrigin;
3609 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3610 property = &mNode->mParentOrigin;
3613 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3614 property = &mNode->mParentOrigin;
3617 case Dali::Actor::Property::ANCHOR_POINT:
3618 property = &mNode->mAnchorPoint;
3621 case Dali::Actor::Property::ANCHOR_POINT_X:
3622 property = &mNode->mAnchorPoint;
3625 case Dali::Actor::Property::ANCHOR_POINT_Y:
3626 property = &mNode->mAnchorPoint;
3629 case Dali::Actor::Property::ANCHOR_POINT_Z:
3630 property = &mNode->mAnchorPoint;
3633 case Dali::Actor::Property::SIZE:
3634 property = &mNode->mSize;
3637 case Dali::Actor::Property::SIZE_WIDTH:
3638 property = &mNode->mSize;
3641 case Dali::Actor::Property::SIZE_HEIGHT:
3642 property = &mNode->mSize;
3645 case Dali::Actor::Property::SIZE_DEPTH:
3646 property = &mNode->mSize;
3649 case Dali::Actor::Property::POSITION:
3650 property = &mNode->mPosition;
3653 case Dali::Actor::Property::POSITION_X:
3654 property = &mNode->mPosition;
3657 case Dali::Actor::Property::POSITION_Y:
3658 property = &mNode->mPosition;
3661 case Dali::Actor::Property::POSITION_Z:
3662 property = &mNode->mPosition;
3665 case Dali::Actor::Property::WORLD_POSITION:
3666 property = &mNode->mWorldPosition;
3669 case Dali::Actor::Property::WORLD_POSITION_X:
3670 property = &mNode->mWorldPosition;
3673 case Dali::Actor::Property::WORLD_POSITION_Y:
3674 property = &mNode->mWorldPosition;
3677 case Dali::Actor::Property::WORLD_POSITION_Z:
3678 property = &mNode->mWorldPosition;
3681 case Dali::Actor::Property::ORIENTATION:
3682 property = &mNode->mOrientation;
3685 case Dali::Actor::Property::WORLD_ORIENTATION:
3686 property = &mNode->mWorldOrientation;
3689 case Dali::Actor::Property::SCALE:
3690 property = &mNode->mScale;
3693 case Dali::Actor::Property::SCALE_X:
3694 property = &mNode->mScale;
3697 case Dali::Actor::Property::SCALE_Y:
3698 property = &mNode->mScale;
3701 case Dali::Actor::Property::SCALE_Z:
3702 property = &mNode->mScale;
3705 case Dali::Actor::Property::WORLD_SCALE:
3706 property = &mNode->mWorldScale;
3709 case Dali::Actor::Property::VISIBLE:
3710 property = &mNode->mVisible;
3713 case Dali::Actor::Property::COLOR:
3714 property = &mNode->mColor;
3717 case Dali::Actor::Property::COLOR_RED:
3718 property = &mNode->mColor;
3721 case Dali::Actor::Property::COLOR_GREEN:
3722 property = &mNode->mColor;
3725 case Dali::Actor::Property::COLOR_BLUE:
3726 property = &mNode->mColor;
3729 case Dali::Actor::Property::COLOR_ALPHA:
3730 property = &mNode->mColor;
3733 case Dali::Actor::Property::WORLD_COLOR:
3734 property = &mNode->mWorldColor;
3737 case Dali::Actor::Property::WORLD_MATRIX:
3738 property = &mNode->mWorldMatrix;
3749 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3751 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3753 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3755 // check whether the animatable property is registered already, if not then register one.
3756 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3757 if( animatableProperty )
3759 componentIndex = animatableProperty->componentIndex;
3766 case Dali::Actor::Property::PARENT_ORIGIN_X:
3767 case Dali::Actor::Property::ANCHOR_POINT_X:
3768 case Dali::Actor::Property::SIZE_WIDTH:
3769 case Dali::Actor::Property::POSITION_X:
3770 case Dali::Actor::Property::WORLD_POSITION_X:
3771 case Dali::Actor::Property::SCALE_X:
3772 case Dali::Actor::Property::COLOR_RED:
3778 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3779 case Dali::Actor::Property::ANCHOR_POINT_Y:
3780 case Dali::Actor::Property::SIZE_HEIGHT:
3781 case Dali::Actor::Property::POSITION_Y:
3782 case Dali::Actor::Property::WORLD_POSITION_Y:
3783 case Dali::Actor::Property::SCALE_Y:
3784 case Dali::Actor::Property::COLOR_GREEN:
3790 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3791 case Dali::Actor::Property::ANCHOR_POINT_Z:
3792 case Dali::Actor::Property::SIZE_DEPTH:
3793 case Dali::Actor::Property::POSITION_Z:
3794 case Dali::Actor::Property::WORLD_POSITION_Z:
3795 case Dali::Actor::Property::SCALE_Z:
3796 case Dali::Actor::Property::COLOR_BLUE:
3802 case Dali::Actor::Property::COLOR_ALPHA:
3816 return componentIndex;
3819 void Actor::SetParent( Actor* parent, int index )
3823 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3827 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3830 // Instruct each actor to create a corresponding node in the scene graph
3831 ConnectToStage( index );
3834 else // parent being set to NULL
3836 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3840 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3843 DALI_ASSERT_ALWAYS( mNode != NULL );
3847 // Disconnect the Node & its children from the scene-graph.
3848 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3851 // Instruct each actor to discard pointers to the scene-graph
3852 DisconnectFromStage();
3857 SceneGraph::Node* Actor::CreateNode() const
3862 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3865 Actor* actor = dynamic_cast< Actor* >( object );
3869 if( 0 == actionName.compare( ACTION_SHOW ) )
3871 actor->SetVisible( true );
3874 else if( 0 == actionName.compare( ACTION_HIDE ) )
3876 actor->SetVisible( false );
3884 void Actor::EnsureRelayoutData() const
3886 // Assign relayout data.
3887 if( !mRelayoutData )
3889 mRelayoutData = new RelayoutData();
3893 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3895 // Check if actor is dependent on parent
3896 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3898 if( ( dimension & ( 1 << i ) ) )
3900 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3901 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3911 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3913 // Check if actor is dependent on children
3914 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3916 if( ( dimension & ( 1 << i ) ) )
3918 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3919 switch( resizePolicy )
3921 case ResizePolicy::FIT_TO_CHILDREN:
3922 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3938 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3940 return Actor::RelayoutDependentOnChildren( dimension );
3943 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3945 // Check each possible dimension and see if it is dependent on the input one
3946 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3948 if( dimension & ( 1 << i ) )
3950 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3957 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3959 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3961 if( dimension & ( 1 << i ) )
3963 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3968 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3970 // If more than one dimension is requested, just return the first one found
3971 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3973 if( ( dimension & ( 1 << i ) ) )
3975 return mRelayoutData->negotiatedDimensions[ i ];
3979 return 0.0f; // Default
3982 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3984 EnsureRelayoutData();
3986 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3988 if( dimension & ( 1 << i ) )
3990 mRelayoutData->dimensionPadding[ i ] = padding;
3995 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3997 EnsureRelayoutData();
3999 // If more than one dimension is requested, just return the first one found
4000 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4002 if( ( dimension & ( 1 << i ) ) )
4004 return mRelayoutData->dimensionPadding[ i ];
4008 return Vector2( 0.0f, 0.0f ); // Default
4011 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4013 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4015 if( dimension & ( 1 << i ) )
4017 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4022 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4024 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4026 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4035 float Actor::GetHeightForWidthBase( float width )
4037 float height = 0.0f;
4039 const Vector3 naturalSize = GetNaturalSize();
4040 if( naturalSize.width > 0.0f )
4042 height = naturalSize.height * width / naturalSize.width;
4044 else // we treat 0 as 1:1 aspect ratio
4052 float Actor::GetWidthForHeightBase( float height )
4056 const Vector3 naturalSize = GetNaturalSize();
4057 if( naturalSize.height > 0.0f )
4059 width = naturalSize.width * height / naturalSize.height;
4061 else // we treat 0 as 1:1 aspect ratio
4069 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4071 // Fill to parent, taking size mode factor into account
4072 switch( child.GetResizePolicy( dimension ) )
4074 case ResizePolicy::FILL_TO_PARENT:
4076 return GetLatestSize( dimension );
4079 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4081 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4084 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4086 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4091 return GetLatestSize( dimension );
4096 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4098 // Can be overridden in derived class
4099 return CalculateChildSizeBase( child, dimension );
4102 float Actor::GetHeightForWidth( float width )
4104 // Can be overridden in derived class
4105 return GetHeightForWidthBase( width );
4108 float Actor::GetWidthForHeight( float height )
4110 // Can be overridden in derived class
4111 return GetWidthForHeightBase( height );
4114 float Actor::GetLatestSize( Dimension::Type dimension ) const
4116 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4119 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4121 Vector2 padding = GetPadding( dimension );
4123 return GetLatestSize( dimension ) + padding.x + padding.y;
4126 float Actor::NegotiateFromParent( Dimension::Type dimension )
4128 Actor* parent = GetParent();
4131 Vector2 padding( GetPadding( dimension ) );
4132 Vector2 parentPadding( parent->GetPadding( dimension ) );
4133 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4139 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4141 float maxDimensionPoint = 0.0f;
4143 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4145 Dali::Actor child = GetChildAt( i );
4146 Actor& childImpl = GetImplementation( child );
4148 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4150 // Calculate the min and max points that the children range across
4151 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4152 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4153 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4157 return maxDimensionPoint;
4160 float Actor::GetSize( Dimension::Type dimension ) const
4162 return GetDimensionValue( GetTargetSize(), dimension );
4165 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4167 return GetDimensionValue( GetNaturalSize(), dimension );
4170 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4172 switch( GetResizePolicy( dimension ) )
4174 case ResizePolicy::USE_NATURAL_SIZE:
4176 return GetNaturalSize( dimension );
4179 case ResizePolicy::FIXED:
4181 return GetDimensionValue( GetPreferredSize(), dimension );
4184 case ResizePolicy::USE_ASSIGNED_SIZE:
4186 return GetDimensionValue( maximumSize, dimension );
4189 case ResizePolicy::FILL_TO_PARENT:
4190 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4191 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4193 return NegotiateFromParent( dimension );
4196 case ResizePolicy::FIT_TO_CHILDREN:
4198 return NegotiateFromChildren( dimension );
4201 case ResizePolicy::DIMENSION_DEPENDENCY:
4203 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4206 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4208 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4211 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4213 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4225 return 0.0f; // Default
4228 float Actor::ClampDimension( float size, Dimension::Type dimension )
4230 const float minSize = GetMinimumSize( dimension );
4231 const float maxSize = GetMaximumSize( dimension );
4233 return std::max( minSize, std::min( size, maxSize ) );
4236 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4238 // Check if it needs to be negotiated
4239 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4241 // Check that we havn't gotten into an infinite loop
4242 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4243 bool recursionFound = false;
4244 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4246 if( *it == searchActor )
4248 recursionFound = true;
4253 if( !recursionFound )
4255 // Record the path that we have taken
4256 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4258 // Dimension dependency check
4259 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4261 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4263 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4265 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4269 // Parent dependency check
4270 Actor* parent = GetParent();
4271 if( parent && RelayoutDependentOnParent( dimension ) )
4273 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4276 // Children dependency check
4277 if( RelayoutDependentOnChildren( dimension ) )
4279 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4281 Dali::Actor child = GetChildAt( i );
4282 Actor& childImpl = GetImplementation( child );
4284 // Only relayout child first if it is not dependent on this actor
4285 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4287 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4292 // For deriving classes
4293 OnCalculateRelayoutSize( dimension );
4295 // All dependencies checked, calculate the size and set negotiated flag
4296 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4298 SetNegotiatedDimension( newSize, dimension );
4299 SetLayoutNegotiated( true, dimension );
4301 // For deriving classes
4302 OnLayoutNegotiated( newSize, dimension );
4304 // This actor has been successfully processed, pop it off the recursion stack
4305 recursionStack.pop_back();
4309 // TODO: Break infinite loop
4310 SetLayoutNegotiated( true, dimension );
4315 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4317 // Negotiate all dimensions that require it
4318 ActorDimensionStack recursionStack;
4320 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4322 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4325 NegotiateDimension( dimension, allocatedSize, recursionStack );
4329 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4331 switch( mRelayoutData->sizeSetPolicy )
4333 case SizeScalePolicy::USE_SIZE_SET:
4338 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4340 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4341 const Vector3 naturalSize = GetNaturalSize();
4342 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4344 const float sizeRatio = size.width / size.height;
4345 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4347 if( naturalSizeRatio < sizeRatio )
4349 return Vector2( naturalSizeRatio * size.height, size.height );
4351 else if( naturalSizeRatio > sizeRatio )
4353 return Vector2( size.width, size.width / naturalSizeRatio );
4364 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4366 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4367 const Vector3 naturalSize = GetNaturalSize();
4368 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4370 const float sizeRatio = size.width / size.height;
4371 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4373 if( naturalSizeRatio < sizeRatio )
4375 return Vector2( size.width, size.width / naturalSizeRatio );
4377 else if( naturalSizeRatio > sizeRatio )
4379 return Vector2( naturalSizeRatio * size.height, size.height );
4397 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4399 // Do the set actor size
4400 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4402 // Adjust for size set policy
4403 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4405 // Lock the flag to stop recursive relayouts on set size
4406 mRelayoutData->insideRelayout = true;
4407 SetSize( negotiatedSize );
4408 mRelayoutData->insideRelayout = false;
4410 // Clear flags for all dimensions
4411 SetLayoutDirty( false );
4413 // Give deriving classes a chance to respond
4414 OnRelayout( negotiatedSize, container );
4416 if( !mOnRelayoutSignal.Empty() )
4418 Dali::Actor handle( this );
4419 mOnRelayoutSignal.Emit( handle );
4423 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4425 // Do the negotiation
4426 NegotiateDimensions( allocatedSize );
4428 // Set the actor size
4429 SetNegotiatedSize( container );
4431 // Negotiate down to children
4432 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4434 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4436 Dali::Actor child = GetChildAt( i );
4438 // Only relayout if required
4439 if( GetImplementation( child ).RelayoutRequired() )
4441 container.Add( child, newBounds );
4446 void Actor::RelayoutRequest( Dimension::Type dimension )
4448 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4449 if( relayoutController )
4451 Dali::Actor self( this );
4452 relayoutController->RequestRelayout( self, dimension );
4456 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4460 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4464 void Actor::SetPreferredSize( const Vector2& size )
4466 EnsureRelayoutData();
4468 if( size.width > 0.0f )
4470 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4473 if( size.height > 0.0f )
4475 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4478 mRelayoutData->preferredSize = size;
4483 Vector2 Actor::GetPreferredSize() const
4485 EnsureRelayoutData();
4487 return mRelayoutData->preferredSize;
4490 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4492 EnsureRelayoutData();
4494 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4496 if( dimension & ( 1 << i ) )
4498 mRelayoutData->minimumSize[ i ] = size;
4505 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4507 EnsureRelayoutData();
4509 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4511 if( dimension & ( 1 << i ) )
4513 return mRelayoutData->minimumSize[ i ];
4517 return 0.0f; // Default
4520 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4522 EnsureRelayoutData();
4524 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4526 if( dimension & ( 1 << i ) )
4528 mRelayoutData->maximumSize[ i ] = size;
4535 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4537 EnsureRelayoutData();
4539 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4541 if( dimension & ( 1 << i ) )
4543 return mRelayoutData->maximumSize[ i ];
4547 return 0.0f; // Default
4550 } // namespace Internal