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:
282 case Dimension::HEIGHT:
284 return values.height;
295 * @brief Extract a given dimension from a Vector3
297 * @param[in] values The values to extract from
298 * @param[in] dimension The dimension to extract
299 * @return Return the value for the dimension
301 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
303 return GetDimensionValue( values.GetVectorXY(), dimension );
307 } // unnamed namespace
309 ActorPtr Actor::New()
311 ActorPtr actor( new Actor( BASIC ) );
313 // Second-phase construction
319 const std::string& Actor::GetName() const
324 void Actor::SetName( const std::string& name )
330 // ATTENTION: string for debug purposes is not thread safe.
331 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
335 unsigned int Actor::GetId() const
340 void Actor::Attach( ActorAttachment& attachment )
342 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
346 attachment.Connect();
349 mAttachment = ActorAttachmentPtr( &attachment );
352 ActorAttachmentPtr Actor::GetAttachment()
357 bool Actor::OnStage() const
362 Dali::Layer Actor::GetLayer()
366 // Short-circuit for Layer derived actors
369 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
372 // Find the immediate Layer parent
373 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
375 if( parent->IsLayer() )
377 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
384 void Actor::Add( Actor& child )
386 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
387 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
391 mChildren = new ActorContainer;
394 Actor* const oldParent( child.mParent );
396 // child might already be ours
397 if( this != oldParent )
399 // if we already have parent, unparent us first
402 oldParent->Remove( child ); // This causes OnChildRemove callback
404 // Old parent may need to readjust to missing child
405 if( oldParent->RelayoutDependentOnChildren() )
407 oldParent->RelayoutRequest();
411 // Guard against Add() during previous OnChildRemove callback
414 // Do this first, since user callbacks from within SetParent() may need to remove child
415 mChildren->push_back( Dali::Actor( &child ) );
417 // SetParent asserts that child can be added
418 child.SetParent( this );
420 // Notification for derived classes
423 // Only put in a relayout request if there is a suitable dependency
424 if( RelayoutDependentOnChildren() )
432 void Actor::Insert( unsigned int index, Actor& child )
434 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
435 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
439 mChildren = new ActorContainer;
442 Actor* const oldParent( child.mParent );
444 // since an explicit position has been given, always insert, even if already a child
447 oldParent->Remove( child ); // This causes OnChildRemove callback
449 // Old parent may need to readjust to missing child
450 if( oldParent->RelayoutDependentOnChildren() )
452 oldParent->RelayoutRequest();
456 // Guard against Add() during previous OnChildRemove callback
459 // Do this first, since user callbacks from within SetParent() may need to remove child
460 if( index < GetChildCount() )
462 ActorIter it = mChildren->begin();
463 std::advance( it, index );
464 mChildren->insert( it, Dali::Actor( &child ) );
468 mChildren->push_back( Dali::Actor( &child ) );
470 // SetParent asserts that child can be added
471 child.SetParent( this, index );
473 // Notification for derived classes
476 // Only put in a relayout request if there is a suitable dependency
477 if( RelayoutDependentOnChildren() )
482 if( child.RelayoutDependentOnParent() )
484 child.RelayoutRequest();
489 void Actor::Remove( Actor& child )
491 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
501 // Find the child in mChildren, and unparent it
502 ActorIter end = mChildren->end();
503 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
505 Actor& actor = GetImplementation( *iter );
507 if( &actor == &child )
509 // Keep handle for OnChildRemove notification
510 removed = Dali::Actor( &actor );
512 // Do this first, since user callbacks from within SetParent() may need to add the child
513 mChildren->erase( iter );
515 DALI_ASSERT_DEBUG( actor.GetParent() == this );
516 actor.SetParent( NULL );
524 // Notification for derived classes
525 OnChildRemove( GetImplementation( removed ) );
527 // Only put in a relayout request if there is a suitable dependency
528 if( RelayoutDependentOnChildren() )
535 void Actor::Unparent()
539 // Remove this actor from the parent. The remove will put a relayout request in for
540 // the parent if required
541 mParent->Remove( *this );
542 // mParent is now NULL!
546 unsigned int Actor::GetChildCount() const
548 return ( NULL != mChildren ) ? mChildren->size() : 0;
551 Dali::Actor Actor::GetChildAt( unsigned int index ) const
553 DALI_ASSERT_ALWAYS( index < GetChildCount() );
555 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
558 ActorPtr Actor::FindChildByName( const std::string& actorName )
561 if( actorName == mName )
567 ActorIter end = mChildren->end();
568 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
570 child = GetImplementation( *iter ).FindChildByName( actorName );
581 ActorPtr Actor::FindChildById( const unsigned int id )
590 ActorIter end = mChildren->end();
591 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
593 child = GetImplementation( *iter ).FindChildById( id );
604 void Actor::SetParentOrigin( const Vector3& origin )
608 // mNode is being used in a separate thread; queue a message to set the value & base value
609 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
612 // Cache for event-thread access
615 // not allocated, check if different from default
616 if( ParentOrigin::DEFAULT != origin )
618 mParentOrigin = new Vector3( origin );
623 // check if different from current costs more than just set
624 *mParentOrigin = origin;
628 void Actor::SetParentOriginX( float x )
630 const Vector3& current = GetCurrentParentOrigin();
632 SetParentOrigin( Vector3( x, current.y, current.z ) );
635 void Actor::SetParentOriginY( float y )
637 const Vector3& current = GetCurrentParentOrigin();
639 SetParentOrigin( Vector3( current.x, y, current.z ) );
642 void Actor::SetParentOriginZ( float z )
644 const Vector3& current = GetCurrentParentOrigin();
646 SetParentOrigin( Vector3( current.x, current.y, z ) );
649 const Vector3& Actor::GetCurrentParentOrigin() const
651 // Cached for event-thread access
652 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
655 void Actor::SetAnchorPoint( const Vector3& anchor )
659 // mNode is being used in a separate thread; queue a message to set the value & base value
660 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
663 // Cache for event-thread access
666 // not allocated, check if different from default
667 if( AnchorPoint::DEFAULT != anchor )
669 mAnchorPoint = new Vector3( anchor );
674 // check if different from current costs more than just set
675 *mAnchorPoint = anchor;
679 void Actor::SetAnchorPointX( float x )
681 const Vector3& current = GetCurrentAnchorPoint();
683 SetAnchorPoint( Vector3( x, current.y, current.z ) );
686 void Actor::SetAnchorPointY( float y )
688 const Vector3& current = GetCurrentAnchorPoint();
690 SetAnchorPoint( Vector3( current.x, y, current.z ) );
693 void Actor::SetAnchorPointZ( float z )
695 const Vector3& current = GetCurrentAnchorPoint();
697 SetAnchorPoint( Vector3( current.x, current.y, z ) );
700 const Vector3& Actor::GetCurrentAnchorPoint() const
702 // Cached for event-thread access
703 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
706 void Actor::SetPosition( float x, float y )
708 SetPosition( Vector3( x, y, 0.0f ) );
711 void Actor::SetPosition( float x, float y, float z )
713 SetPosition( Vector3( x, y, z ) );
716 void Actor::SetPosition( const Vector3& position )
718 mTargetPosition = position;
722 // mNode is being used in a separate thread; queue a message to set the value & base value
723 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
727 void Actor::SetX( float x )
729 mTargetPosition.x = x;
733 // mNode is being used in a separate thread; queue a message to set the value & base value
734 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
738 void Actor::SetY( float y )
740 mTargetPosition.y = y;
744 // mNode is being used in a separate thread; queue a message to set the value & base value
745 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
749 void Actor::SetZ( float z )
751 mTargetPosition.z = z;
755 // mNode is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
760 void Actor::TranslateBy( const Vector3& distance )
762 mTargetPosition += distance;
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
771 const Vector3& Actor::GetCurrentPosition() const
775 // mNode is being used in a separate thread; copy the value from the previous update
776 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
779 return Vector3::ZERO;
782 const Vector3& Actor::GetTargetPosition() const
784 return mTargetPosition;
787 const Vector3& Actor::GetCurrentWorldPosition() const
791 // mNode is being used in a separate thread; copy the value from the previous update
792 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
795 return Vector3::ZERO;
798 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
800 // this flag is not animatable so keep the value
801 mPositionInheritanceMode = mode;
804 // mNode is being used in a separate thread; queue a message to set the value
805 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
809 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
811 // Cached for event-thread access
812 return mPositionInheritanceMode;
815 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
817 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
818 normalizedAxis.Normalize();
820 Quaternion orientation( angle, normalizedAxis );
822 SetOrientation( orientation );
825 void Actor::SetOrientation( const Quaternion& orientation )
829 // mNode is being used in a separate thread; queue a message to set the value & base value
830 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
834 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
838 // mNode is being used in a separate thread; queue a message to set the value & base value
839 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
843 void Actor::RotateBy( const Quaternion& relativeRotation )
847 // mNode is being used in a separate thread; queue a message to set the value & base value
848 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
852 const Quaternion& Actor::GetCurrentOrientation() const
856 // mNode is being used in a separate thread; copy the value from the previous update
857 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
860 return Quaternion::IDENTITY;
863 const Quaternion& Actor::GetCurrentWorldOrientation() const
867 // mNode is being used in a separate thread; copy the value from the previous update
868 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
871 return Quaternion::IDENTITY;
874 void Actor::SetScale( float scale )
876 SetScale( Vector3( scale, scale, scale ) );
879 void Actor::SetScale( float x, float y, float z )
881 SetScale( Vector3( x, y, z ) );
884 void Actor::SetScale( const Vector3& scale )
888 // mNode is being used in a separate thread; queue a message to set the value & base value
889 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
893 void Actor::SetScaleX( float x )
897 // mNode is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
902 void Actor::SetScaleY( float y )
906 // mNode is being used in a separate thread; queue a message to set the value & base value
907 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
911 void Actor::SetScaleZ( float z )
915 // mNode is being used in a separate thread; queue a message to set the value & base value
916 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
920 void Actor::SetInitialVolume( const Vector3& volume )
924 // mNode is being used in a separate thread; queue a message to set the value
925 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
929 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
933 // mNode is being used in a separate thread; queue a message to set the value
934 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
938 bool Actor::GetTransmitGeometryScaling() const
942 // mNode is being used in a separate thread; copy the value from the previous update
943 return mNode->GetTransmitGeometryScaling();
949 void Actor::ScaleBy( const Vector3& relativeScale )
953 // mNode is being used in a separate thread; queue a message to set the value & base value
954 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
958 const Vector3& Actor::GetCurrentScale() const
962 // mNode is being used in a separate thread; copy the value from the previous update
963 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
969 const Vector3& Actor::GetCurrentWorldScale() const
973 // mNode is being used in a separate thread; copy the value from the previous update
974 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
980 void Actor::SetInheritScale( bool inherit )
982 // non animateable so keep local copy
983 mInheritScale = inherit;
986 // mNode is being used in a separate thread; queue a message to set the value
987 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
991 bool Actor::IsScaleInherited() const
993 return mInheritScale;
996 Matrix Actor::GetCurrentWorldMatrix() const
1000 // World matrix is no longer updated unless there is something observing the node.
1001 // Need to calculate it from node's world position, orientation and scale:
1002 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1003 Matrix worldMatrix(false);
1004 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1005 mNode->GetWorldOrientation( updateBufferIndex ),
1006 mNode->GetWorldPosition( updateBufferIndex ) );
1010 return Matrix::IDENTITY;
1013 void Actor::SetVisible( bool visible )
1017 // mNode is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1022 bool Actor::IsVisible() const
1026 // mNode is being used in a separate thread; copy the value from the previous update
1027 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1033 void Actor::SetOpacity( float opacity )
1037 // mNode is being used in a separate thread; queue a message to set the value & base value
1038 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1042 float Actor::GetCurrentOpacity() const
1046 // mNode is being used in a separate thread; copy the value from the previous update
1047 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1053 const Vector4& Actor::GetCurrentWorldColor() const
1057 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1060 return Color::WHITE;
1063 void Actor::SetColor( const Vector4& color )
1067 // mNode is being used in a separate thread; queue a message to set the value & base value
1068 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1072 void Actor::SetColorRed( float red )
1076 // mNode is being used in a separate thread; queue a message to set the value & base value
1077 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1081 void Actor::SetColorGreen( float green )
1085 // mNode is being used in a separate thread; queue a message to set the value & base value
1086 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1090 void Actor::SetColorBlue( float blue )
1094 // mNode is being used in a separate thread; queue a message to set the value & base value
1095 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1099 const Vector4& Actor::GetCurrentColor() const
1103 // mNode is being used in a separate thread; copy the value from the previous update
1104 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1107 return Color::WHITE;
1110 void Actor::SetInheritOrientation( bool inherit )
1112 // non animateable so keep local copy
1113 mInheritOrientation = inherit;
1116 // mNode is being used in a separate thread; queue a message to set the value
1117 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1121 bool Actor::IsOrientationInherited() const
1123 return mInheritOrientation;
1126 void Actor::SetSizeModeFactor( const Vector3& factor )
1128 EnsureRelayoutData();
1130 mRelayoutData->sizeModeFactor = factor;
1133 const Vector3& Actor::GetSizeModeFactor() const
1135 EnsureRelayoutData();
1137 return mRelayoutData->sizeModeFactor;
1140 void Actor::SetColorMode( ColorMode colorMode )
1142 // non animateable so keep local copy
1143 mColorMode = colorMode;
1146 // mNode is being used in a separate thread; queue a message to set the value
1147 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1151 ColorMode Actor::GetColorMode() const
1153 // we have cached copy
1157 void Actor::SetSize( float width, float height )
1159 SetSize( Vector2( width, height ) );
1162 void Actor::SetSize( float width, float height, float depth )
1164 SetSize( Vector3( width, height, depth ) );
1167 void Actor::SetSize( const Vector2& size )
1169 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1172 void Actor::SetSizeInternal( const Vector2& size )
1174 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1177 float Actor::CalculateSizeZ( const Vector2& size ) const
1179 return std::min( size.width, size.height );
1182 void Actor::SetSize( const Vector3& size )
1184 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1186 SetPreferredSize( size.GetVectorXY() );
1190 SetSizeInternal( size );
1194 void Actor::SetSizeInternal( const Vector3& size )
1196 // dont allow recursive loop
1197 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1198 // 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
1199 if( ( NULL != mNode )&&
1200 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1201 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1202 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1206 // mNode is being used in a separate thread; queue a message to set the value & base value
1207 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1209 // Notification for derived classes
1210 mInsideOnSizeSet = true;
1211 OnSizeSet( mTargetSize );
1212 mInsideOnSizeSet = false;
1214 // Raise a relayout request if the flag is not locked
1215 if( mRelayoutData && !mRelayoutData->insideRelayout )
1222 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1224 mTargetSize = targetSize;
1226 // Notify deriving classes
1227 OnSizeAnimation( animation, mTargetSize );
1230 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1232 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1234 mTargetSize.width = targetSize;
1236 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1238 mTargetSize.height = targetSize;
1240 // Notify deriving classes
1241 OnSizeAnimation( animation, mTargetSize );
1244 void Actor::SetWidth( float width )
1248 // mNode is being used in a separate thread; queue a message to set the value & base value
1249 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1253 void Actor::SetHeight( float height )
1257 // mNode is being used in a separate thread; queue a message to set the value & base value
1258 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1262 void Actor::SetDepth( float depth )
1266 // mNode is being used in a separate thread; queue a message to set the value & base value
1267 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1271 const Vector3& Actor::GetTargetSize() const
1276 const Vector3& Actor::GetCurrentSize() const
1280 // mNode is being used in a separate thread; copy the value from the previous update
1281 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1284 return Vector3::ZERO;
1287 Vector3 Actor::GetNaturalSize() const
1289 // It is up to deriving classes to return the appropriate natural size
1290 return Vector3( 0.0f, 0.0f, 0.0f );
1293 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1295 EnsureRelayoutData();
1297 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1299 if( dimension & ( 1 << i ) )
1301 mRelayoutData->resizePolicies[ i ] = policy;
1305 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1307 if( dimension & Dimension::WIDTH )
1309 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1312 if( dimension & Dimension::HEIGHT )
1314 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1318 // If calling SetResizePolicy, assume we want relayout enabled
1319 SetRelayoutEnabled( true );
1321 OnSetResizePolicy( policy, dimension );
1323 // Trigger relayout on this control
1327 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1329 EnsureRelayoutData();
1331 // If more than one dimension is requested, just return the first one found
1332 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1334 if( ( dimension & ( 1 << i ) ) )
1336 return mRelayoutData->resizePolicies[ i ];
1340 return ResizePolicy::DEFAULT;
1343 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1345 EnsureRelayoutData();
1347 mRelayoutData->sizeSetPolicy = policy;
1350 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1352 EnsureRelayoutData();
1354 return mRelayoutData->sizeSetPolicy;
1357 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1359 EnsureRelayoutData();
1361 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1363 if( dimension & ( 1 << i ) )
1365 mRelayoutData->dimensionDependencies[ i ] = dependency;
1370 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1372 EnsureRelayoutData();
1374 // If more than one dimension is requested, just return the first one found
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( ( dimension & ( 1 << i ) ) )
1379 return mRelayoutData->dimensionDependencies[ i ];
1383 return Dimension::ALL_DIMENSIONS; // Default
1386 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1388 // If relayout data has not been allocated yet and the client is requesting
1389 // to disable it, do nothing
1390 if( mRelayoutData || relayoutEnabled )
1392 EnsureRelayoutData();
1394 mRelayoutData->relayoutEnabled = relayoutEnabled;
1398 bool Actor::IsRelayoutEnabled() const
1400 // Assume that if relayout data has not been allocated yet then
1401 // relayout is disabled
1402 return mRelayoutData && mRelayoutData->relayoutEnabled;
1405 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1407 EnsureRelayoutData();
1409 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1411 if( dimension & ( 1 << i ) )
1413 mRelayoutData->dimensionDirty[ i ] = dirty;
1418 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1420 EnsureRelayoutData();
1422 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1424 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1433 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1435 EnsureRelayoutData();
1437 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1440 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1442 EnsureRelayoutData();
1444 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1447 #ifdef DALI_DYNAMICS_SUPPORT
1449 //--------------- Dynamics ---------------
1451 void Actor::DisableDynamics()
1453 if( NULL != mDynamicsData )
1455 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1457 // ensure dynamics object are disconnected from scene
1458 DisconnectDynamics();
1460 // delete joint owned by this actor
1461 while( !mDynamicsData->joints.empty() )
1463 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1466 // delete other joints referencing this actor
1467 while( !mDynamicsData->referencedJoints.empty() )
1469 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1470 ActorPtr jointOwner( joint->GetActor( true ) );
1473 jointOwner->RemoveDynamicsJoint( joint );
1477 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1480 // delete the DynamicsBody object
1481 mDynamicsData->body.Reset();
1483 // Discard Dynamics data structure
1484 delete mDynamicsData;
1485 mDynamicsData = NULL;
1489 DynamicsBodyPtr Actor::GetDynamicsBody() const
1491 DynamicsBodyPtr body;
1493 if( NULL != mDynamicsData )
1495 body = mDynamicsData->body;
1501 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1503 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1505 if( NULL == mDynamicsData )
1507 mDynamicsData = new DynamicsData( this );
1510 if( !mDynamicsData->body )
1512 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1516 DynamicsWorldPtr world( DynamicsWorld::Get() );
1519 if( mParent == world->GetRootActor().Get() )
1521 mDynamicsData->body->Connect( GetEventThreadServices() );
1527 return mDynamicsData->body;
1530 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1532 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1533 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1536 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1538 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1539 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1541 DynamicsJointPtr joint;
1543 DynamicsWorldPtr world( DynamicsWorld::Get() );
1547 if( NULL != mDynamicsData )
1549 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1551 if( mDynamicsData->joints.end() != it )
1553 // use existing joint
1559 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1560 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1564 bodyA = EnableDynamics( new DynamicsBodyConfig );
1569 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1572 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1573 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1575 if( OnStage() && attachedActor->OnStage() )
1577 joint->Connect( GetEventThreadServices() );
1580 attachedActor->ReferenceJoint( joint );
1582 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1583 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1590 const int Actor::GetNumberOfJoints() const
1592 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1595 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1597 DynamicsJointPtr joint;
1599 if( NULL != mDynamicsData )
1601 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1603 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1605 for( int i = 0; i < index; ++i )
1617 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1619 DynamicsJointPtr joint;
1621 if( NULL != mDynamicsData )
1623 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1625 if( mDynamicsData->joints.end() != it )
1627 // use existing joint
1635 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1637 if( NULL != mDynamicsData )
1639 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1640 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1642 for(; it != endIt; ++it )
1644 if( it->second == joint.Get() )
1646 ActorPtr attachedActor( it->first );
1648 if( OnStage() && attachedActor && attachedActor->OnStage() )
1650 joint->Disconnect( GetEventThreadServices() );
1655 attachedActor->ReleaseJoint( joint );
1656 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1657 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1660 mDynamicsData->joints.erase(it);
1667 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1669 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1671 if( NULL != mDynamicsData )
1673 mDynamicsData->referencedJoints.push_back(joint);
1677 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1679 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1681 if( NULL != mDynamicsData )
1683 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1685 if( it != mDynamicsData->referencedJoints.end() )
1687 mDynamicsData->referencedJoints.erase( it );
1692 void Actor::SetDynamicsRoot(bool flag)
1694 if( mIsDynamicsRoot != flag )
1696 mIsDynamicsRoot = flag;
1698 if( OnStage() && mChildren )
1700 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1701 ActorIter end = mChildren->end();
1702 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1704 Actor& child = GetImplementation(*iter);
1706 if( child.GetDynamicsBody() )
1708 if( mIsDynamicsRoot )
1710 child.ConnectDynamics();
1714 child.DisconnectDynamics();
1722 bool Actor::IsDynamicsRoot() const
1724 return mIsDynamicsRoot;
1727 void Actor::AttachedActorOnStage( Dali::Actor actor )
1729 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1733 ActorPtr attachedActor( &GetImplementation(actor) );
1735 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1736 if( NULL != mDynamicsData )
1738 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1739 if( mDynamicsData->joints.end() != it )
1741 DynamicsJointPtr joint( it->second );
1742 joint->Connect( GetEventThreadServices() );
1748 void Actor::AttachedActorOffStage( Dali::Actor actor )
1750 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1754 ActorPtr attachedActor( &GetImplementation(actor) );
1756 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1757 if( NULL != mDynamicsData )
1759 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1760 if( mDynamicsData->joints.end() != it )
1762 DynamicsJointPtr joint( it->second );
1763 joint->Disconnect( GetEventThreadServices() );
1769 void Actor::ConnectDynamics()
1771 if( NULL != mDynamicsData && mDynamicsData->body )
1773 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1775 mDynamicsData->body->Connect( GetEventThreadServices() );
1777 // Connect all joints where attachedActor is also on stage
1778 if( !mDynamicsData->joints.empty() )
1780 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1781 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1783 for(; it != endIt; ++it )
1785 Actor* attachedActor( it->first );
1786 if( NULL != attachedActor && attachedActor->OnStage() )
1788 DynamicsJointPtr joint( it->second );
1790 joint->Connect( GetEventThreadServices() );
1798 void Actor::DisconnectDynamics()
1800 if( NULL != mDynamicsData && mDynamicsData->body )
1804 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1806 // Disconnect all joints
1807 if( !mDynamicsData->joints.empty() )
1809 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1810 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1812 for(; it != endIt; ++it )
1814 DynamicsJointPtr joint( it->second );
1816 joint->Disconnect( GetEventThreadServices() );
1823 #endif // DALI_DYNAMICS_SUPPORT
1825 void Actor::SetOverlay( bool enable )
1827 // Setting STENCIL will override OVERLAY
1828 if( DrawMode::STENCIL != mDrawMode )
1830 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1834 bool Actor::IsOverlay() const
1836 return ( DrawMode::OVERLAY == mDrawMode );
1839 void Actor::SetDrawMode( DrawMode::Type drawMode )
1841 // this flag is not animatable so keep the value
1842 mDrawMode = drawMode;
1845 // mNode is being used in a separate thread; queue a message to set the value
1846 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1850 DrawMode::Type Actor::GetDrawMode() const
1855 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1857 // only valid when on-stage
1860 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1862 Vector2 converted( screenX, screenY );
1864 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1865 const int taskCount = taskList.GetTaskCount();
1866 for( int i = taskCount - 1; i >= 0; --i )
1868 Dali::RenderTask task = taskList.GetTask( i );
1869 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1871 // found a task where this conversion was ok so return
1879 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1881 bool retval = false;
1882 // only valid when on-stage
1885 CameraActor* camera = renderTask.GetCameraActor();
1889 renderTask.GetViewport( viewport );
1891 // need to translate coordinates to render tasks coordinate space
1892 Vector2 converted( screenX, screenY );
1893 if( renderTask.TranslateCoordinates( converted ) )
1895 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1902 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1904 // Early-out if mNode is NULL
1910 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1912 // Calculate the ModelView matrix
1913 Matrix modelView( false/*don't init*/);
1914 // need to use the components as world matrix is only updated for actors that need it
1915 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1916 Matrix::Multiply( modelView, modelView, viewMatrix );
1918 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1919 Matrix invertedMvp( false/*don't init*/);
1920 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1921 bool success = invertedMvp.Invert();
1923 // Convert to GL coordinates
1924 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1929 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1936 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1942 if( XyPlaneIntersect( nearPos, farPos, local ) )
1944 Vector3 size = GetCurrentSize();
1945 localX = local.x + size.x * 0.5f;
1946 localY = local.y + size.y * 0.5f;
1957 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1960 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1962 Mathematical Formulation
1964 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1966 ( p - c ) dot ( p - c ) = r^2
1968 Given a ray with a point of origin 'o', and a direction vector 'd':
1970 ray(t) = o + td, t >= 0
1972 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1974 (o + td - c ) dot ( o + td - c ) = r^2
1976 To solve for t we first expand the above into a more recognisable quadratic equation form
1978 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1987 B = 2( o - c ) dot d
1988 C = ( o - c ) dot ( o - c ) - r^2
1990 which can be solved using a standard quadratic formula.
1992 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1994 Practical Simplification
1996 In a renderer, we often differentiate between world space and object space. In the object space
1997 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1998 into object space, the mathematical solution presented above can be simplified significantly.
2000 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2004 and we can find the t at which the (transformed) ray intersects the sphere by
2006 ( o + td ) dot ( o + td ) = r^2
2008 According to the reasoning above, we expand the above quadratic equation into the general form
2012 which now has coefficients:
2019 // Early out if mNode is NULL
2025 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2027 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2028 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2029 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2031 // Compute the radius is not needed, square radius it's enough.
2032 const Vector3& size( mNode->GetSize( bufferIndex ) );
2034 // Scale the sphere.
2035 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2037 const float width = size.width * scale.width;
2038 const float height = size.height * scale.height;
2040 float squareSphereRadius = 0.5f * ( width * width + height * height );
2042 float a = rayDir.Dot( rayDir ); // a
2043 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2044 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2046 return ( b2 * b2 - a * c ) >= 0.f;
2049 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2056 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2058 // Transforms the ray to the local reference system.
2060 // Calculate the inverse of Model matrix
2061 Matrix invModelMatrix( false/*don't init*/);
2062 // need to use the components as world matrix is only updated for actors that need it
2063 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2065 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2066 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2068 // Test with the actor's XY plane (Normal = 0 0 1 1).
2070 float a = -rayOriginLocal.z;
2071 float b = rayDirLocal.z;
2073 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2075 // Ray travels distance * rayDirLocal to intersect with plane.
2078 const Vector3& size = mNode->GetSize( bufferIndex );
2080 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2081 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2083 // Test with the actor's geometry.
2084 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2091 void Actor::SetLeaveRequired( bool required )
2093 mLeaveRequired = required;
2096 bool Actor::GetLeaveRequired() const
2098 return mLeaveRequired;
2101 void Actor::SetKeyboardFocusable( bool focusable )
2103 mKeyboardFocusable = focusable;
2106 bool Actor::IsKeyboardFocusable() const
2108 return mKeyboardFocusable;
2111 bool Actor::GetTouchRequired() const
2113 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2116 bool Actor::GetHoverRequired() const
2118 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2121 bool Actor::GetWheelEventRequired() const
2123 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2126 bool Actor::IsHittable() const
2128 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2131 ActorGestureData& Actor::GetGestureData()
2133 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2134 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2135 if( NULL == mGestureData )
2137 mGestureData = new ActorGestureData;
2139 return *mGestureData;
2142 bool Actor::IsGestureRequred( Gesture::Type type ) const
2144 return mGestureData && mGestureData->IsGestureRequred( type );
2147 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2149 bool consumed = false;
2151 if( !mTouchedSignal.Empty() )
2153 Dali::Actor handle( this );
2154 consumed = mTouchedSignal.Emit( handle, event );
2159 // Notification for derived classes
2160 consumed = OnTouchEvent( event );
2166 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2168 bool consumed = false;
2170 if( !mHoveredSignal.Empty() )
2172 Dali::Actor handle( this );
2173 consumed = mHoveredSignal.Emit( handle, event );
2178 // Notification for derived classes
2179 consumed = OnHoverEvent( event );
2185 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2187 bool consumed = false;
2189 if( !mWheelEventSignal.Empty() )
2191 Dali::Actor handle( this );
2192 consumed = mWheelEventSignal.Emit( handle, event );
2197 // Notification for derived classes
2198 consumed = OnWheelEvent( event );
2204 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2206 return mTouchedSignal;
2209 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2211 return mHoveredSignal;
2214 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2216 return mWheelEventSignal;
2219 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2221 return mOnStageSignal;
2224 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2226 return mOffStageSignal;
2229 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2231 return mOnRelayoutSignal;
2234 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2236 bool connected( true );
2237 Actor* actor = dynamic_cast< Actor* >( object );
2239 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2241 actor->TouchedSignal().Connect( tracker, functor );
2243 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2245 actor->HoveredSignal().Connect( tracker, functor );
2247 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2249 actor->WheelEventSignal().Connect( tracker, functor );
2251 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2253 actor->OnStageSignal().Connect( tracker, functor );
2255 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2257 actor->OffStageSignal().Connect( tracker, functor );
2261 // signalName does not match any signal
2268 Actor::Actor( DerivedType derivedType )
2272 mParentOrigin( NULL ),
2273 mAnchorPoint( NULL ),
2274 mRelayoutData( NULL ),
2275 #ifdef DALI_DYNAMICS_SUPPORT
2276 mDynamicsData( NULL ),
2278 mGestureData( NULL ),
2280 mTargetSize( 0.0f, 0.0f, 0.0f ),
2282 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2283 mIsRoot( ROOT_LAYER == derivedType ),
2284 mIsRenderable( RENDERABLE == derivedType ),
2285 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2286 mIsOnStage( false ),
2287 mIsDynamicsRoot( false ),
2289 mLeaveRequired( false ),
2290 mKeyboardFocusable( false ),
2291 mDerivedRequiresTouch( false ),
2292 mDerivedRequiresHover( false ),
2293 mDerivedRequiresWheelEvent( false ),
2294 mOnStageSignalled( false ),
2295 mInsideOnSizeSet( false ),
2296 mInheritOrientation( true ),
2297 mInheritScale( true ),
2298 mDrawMode( DrawMode::NORMAL ),
2299 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2300 mColorMode( Node::DEFAULT_COLOR_MODE )
2304 void Actor::Initialize()
2307 SceneGraph::Node* node = CreateNode();
2309 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2310 mNode = node; // Keep raw-pointer to Node
2314 GetEventThreadServices().RegisterObject( this );
2319 // Remove mParent pointers from children even if we're destroying core,
2320 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2323 ActorConstIter endIter = mChildren->end();
2324 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2326 Actor& actor = GetImplementation( *iter );
2327 actor.SetParent( NULL );
2332 // Guard to allow handle destruction after Core has been destroyed
2333 if( EventThreadServices::IsCoreRunning() )
2337 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2338 mNode = NULL; // Node is about to be destroyed
2341 GetEventThreadServices().UnregisterObject( this );
2344 #ifdef DALI_DYNAMICS_SUPPORT
2346 delete mDynamicsData;
2349 // Cleanup optional gesture data
2350 delete mGestureData;
2352 // Cleanup optional parent origin and anchor
2353 delete mParentOrigin;
2354 delete mAnchorPoint;
2356 // Delete optional relayout data
2359 delete mRelayoutData;
2363 void Actor::ConnectToStage( int index )
2365 // This container is used instead of walking the Actor hierachy.
2366 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2367 ActorContainer connectionList;
2369 // This stage is atomic i.e. not interrupted by user callbacks
2370 RecursiveConnectToStage( connectionList, index );
2372 // Notify applications about the newly connected actors.
2373 const ActorIter endIter = connectionList.end();
2374 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2376 Actor& actor = GetImplementation( *iter );
2377 actor.NotifyStageConnection();
2383 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2385 DALI_ASSERT_ALWAYS( !OnStage() );
2389 ConnectToSceneGraph( index );
2391 // Notification for internal derived classes
2392 OnStageConnectionInternal();
2394 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2395 connectionList.push_back( Dali::Actor( this ) );
2397 // Recursively connect children
2400 ActorConstIter endIter = mChildren->end();
2401 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2403 Actor& actor = GetImplementation( *iter );
2404 actor.RecursiveConnectToStage( connectionList );
2410 * This method is called when the Actor is connected to the Stage.
2411 * The parent must have added its Node to the scene-graph.
2412 * The child must connect its Node to the parent's Node.
2413 * This is resursive; the child calls ConnectToStage() for its children.
2415 void Actor::ConnectToSceneGraph( int index )
2417 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2421 // Reparent Node in next Update
2422 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2425 // Notify attachment
2428 mAttachment->Connect();
2431 #ifdef DALI_DYNAMICS_SUPPORT
2433 if( NULL != mDynamicsData )
2439 // Request relayout on all actors that are added to the scenegraph
2442 // Notification for Object::Observers
2446 void Actor::NotifyStageConnection()
2448 // Actors can be removed (in a callback), before the on-stage stage is reported.
2449 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2450 if( OnStage() && !mOnStageSignalled )
2452 // Notification for external (CustomActor) derived classes
2453 OnStageConnectionExternal();
2455 if( !mOnStageSignal.Empty() )
2457 Dali::Actor handle( this );
2458 mOnStageSignal.Emit( handle );
2461 // Guard against Remove during callbacks
2464 mOnStageSignalled = true; // signal required next time Actor is removed
2469 void Actor::DisconnectFromStage()
2471 // This container is used instead of walking the Actor hierachy.
2472 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2473 ActorContainer disconnectionList;
2475 // This stage is atomic i.e. not interrupted by user callbacks
2476 RecursiveDisconnectFromStage( disconnectionList );
2478 // Notify applications about the newly disconnected actors.
2479 const ActorIter endIter = disconnectionList.end();
2480 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2482 Actor& actor = GetImplementation( *iter );
2483 actor.NotifyStageDisconnection();
2487 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2489 DALI_ASSERT_ALWAYS( OnStage() );
2491 // Recursively disconnect children
2494 ActorConstIter endIter = mChildren->end();
2495 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2497 Actor& actor = GetImplementation( *iter );
2498 actor.RecursiveDisconnectFromStage( disconnectionList );
2502 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2503 disconnectionList.push_back( Dali::Actor( this ) );
2505 // Notification for internal derived classes
2506 OnStageDisconnectionInternal();
2508 DisconnectFromSceneGraph();
2514 * This method is called by an actor or its parent, before a node removal message is sent.
2515 * This is recursive; the child calls DisconnectFromStage() for its children.
2517 void Actor::DisconnectFromSceneGraph()
2519 // Notification for Object::Observers
2520 OnSceneObjectRemove();
2522 // Notify attachment
2525 mAttachment->Disconnect();
2528 #ifdef DALI_DYNAMICS_SUPPORT
2530 if( NULL != mDynamicsData )
2532 DisconnectDynamics();
2537 void Actor::NotifyStageDisconnection()
2539 // Actors can be added (in a callback), before the off-stage state is reported.
2540 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2541 // only do this step if there is a stage, i.e. Core is not being shut down
2542 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2544 // Notification for external (CustomeActor) derived classes
2545 OnStageDisconnectionExternal();
2547 if( !mOffStageSignal.Empty() )
2549 Dali::Actor handle( this );
2550 mOffStageSignal.Emit( handle );
2553 // Guard against Add during callbacks
2556 mOnStageSignalled = false; // signal required next time Actor is added
2561 bool Actor::IsNodeConnected() const
2563 bool connected( false );
2568 if( mNode->IsRoot() || mNode->GetParent() )
2577 unsigned int Actor::GetDefaultPropertyCount() const
2579 return DEFAULT_PROPERTY_COUNT;
2582 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2584 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2586 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2588 indices.PushBack( i );
2592 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2594 if( index < DEFAULT_PROPERTY_COUNT )
2596 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2602 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2604 Property::Index index = Property::INVALID_INDEX;
2606 // Look for name in default properties
2607 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2609 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2610 if( 0 == name.compare( property->name ) )
2620 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2622 if( index < DEFAULT_PROPERTY_COUNT )
2624 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2630 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2632 if( index < DEFAULT_PROPERTY_COUNT )
2634 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2640 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2642 if( index < DEFAULT_PROPERTY_COUNT )
2644 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2650 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2652 if( index < DEFAULT_PROPERTY_COUNT )
2654 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2657 // index out of range...return Property::NONE
2658 return Property::NONE;
2661 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2665 case Dali::Actor::Property::PARENT_ORIGIN:
2667 SetParentOrigin( property.Get< Vector3 >() );
2671 case Dali::Actor::Property::PARENT_ORIGIN_X:
2673 SetParentOriginX( property.Get< float >() );
2677 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2679 SetParentOriginY( property.Get< float >() );
2683 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2685 SetParentOriginZ( property.Get< float >() );
2689 case Dali::Actor::Property::ANCHOR_POINT:
2691 SetAnchorPoint( property.Get< Vector3 >() );
2695 case Dali::Actor::Property::ANCHOR_POINT_X:
2697 SetAnchorPointX( property.Get< float >() );
2701 case Dali::Actor::Property::ANCHOR_POINT_Y:
2703 SetAnchorPointY( property.Get< float >() );
2707 case Dali::Actor::Property::ANCHOR_POINT_Z:
2709 SetAnchorPointZ( property.Get< float >() );
2713 case Dali::Actor::Property::SIZE:
2715 SetSize( property.Get< Vector3 >() );
2719 case Dali::Actor::Property::SIZE_WIDTH:
2721 SetWidth( property.Get< float >() );
2725 case Dali::Actor::Property::SIZE_HEIGHT:
2727 SetHeight( property.Get< float >() );
2731 case Dali::Actor::Property::SIZE_DEPTH:
2733 SetDepth( property.Get< float >() );
2737 case Dali::Actor::Property::POSITION:
2739 SetPosition( property.Get< Vector3 >() );
2743 case Dali::Actor::Property::POSITION_X:
2745 SetX( property.Get< float >() );
2749 case Dali::Actor::Property::POSITION_Y:
2751 SetY( property.Get< float >() );
2755 case Dali::Actor::Property::POSITION_Z:
2757 SetZ( property.Get< float >() );
2761 case Dali::Actor::Property::ORIENTATION:
2763 SetOrientation( property.Get< Quaternion >() );
2767 case Dali::Actor::Property::SCALE:
2769 SetScale( property.Get< Vector3 >() );
2773 case Dali::Actor::Property::SCALE_X:
2775 SetScaleX( property.Get< float >() );
2779 case Dali::Actor::Property::SCALE_Y:
2781 SetScaleY( property.Get< float >() );
2785 case Dali::Actor::Property::SCALE_Z:
2787 SetScaleZ( property.Get< float >() );
2791 case Dali::Actor::Property::VISIBLE:
2793 SetVisible( property.Get< bool >() );
2797 case Dali::Actor::Property::COLOR:
2799 SetColor( property.Get< Vector4 >() );
2803 case Dali::Actor::Property::COLOR_RED:
2805 SetColorRed( property.Get< float >() );
2809 case Dali::Actor::Property::COLOR_GREEN:
2811 SetColorGreen( property.Get< float >() );
2815 case Dali::Actor::Property::COLOR_BLUE:
2817 SetColorBlue( property.Get< float >() );
2821 case Dali::Actor::Property::COLOR_ALPHA:
2823 SetOpacity( property.Get< float >() );
2827 case Dali::Actor::Property::NAME:
2829 SetName( property.Get< std::string >() );
2833 case Dali::Actor::Property::SENSITIVE:
2835 SetSensitive( property.Get< bool >() );
2839 case Dali::Actor::Property::LEAVE_REQUIRED:
2841 SetLeaveRequired( property.Get< bool >() );
2845 case Dali::Actor::Property::INHERIT_ORIENTATION:
2847 SetInheritOrientation( property.Get< bool >() );
2851 case Dali::Actor::Property::INHERIT_SCALE:
2853 SetInheritScale( property.Get< bool >() );
2857 case Dali::Actor::Property::COLOR_MODE:
2859 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2863 case Dali::Actor::Property::POSITION_INHERITANCE:
2865 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2869 case Dali::Actor::Property::DRAW_MODE:
2871 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2875 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2877 SetSizeModeFactor( property.Get< Vector3 >() );
2881 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2883 ResizePolicy::Type type;
2884 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2886 SetResizePolicy( type, Dimension::WIDTH );
2891 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2893 ResizePolicy::Type type;
2894 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2896 SetResizePolicy( type, Dimension::HEIGHT );
2901 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2903 SizeScalePolicy::Type type;
2904 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2906 SetSizeScalePolicy( type );
2911 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2913 if( property.Get< bool >() )
2915 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2920 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2922 if( property.Get< bool >() )
2924 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2929 case Dali::Actor::Property::PADDING:
2931 Vector4 padding = property.Get< Vector4 >();
2932 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2933 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2937 case Dali::Actor::Property::MINIMUM_SIZE:
2939 Vector2 size = property.Get< Vector2 >();
2940 SetMinimumSize( size.x, Dimension::WIDTH );
2941 SetMinimumSize( size.y, Dimension::HEIGHT );
2945 case Dali::Actor::Property::MAXIMUM_SIZE:
2947 Vector2 size = property.Get< Vector2 >();
2948 SetMaximumSize( size.x, Dimension::WIDTH );
2949 SetMaximumSize( size.y, Dimension::HEIGHT );
2955 // this can happen in the case of a non-animatable default property so just do nothing
2961 // TODO: This method needs to be removed
2962 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2964 switch( entry.type )
2966 case Property::BOOLEAN:
2968 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2969 DALI_ASSERT_DEBUG( NULL != property );
2971 // property is being used in a separate thread; queue a message to set the property
2972 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2977 case Property::INTEGER:
2979 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2980 DALI_ASSERT_DEBUG( NULL != property );
2982 // property is being used in a separate thread; queue a message to set the property
2983 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2988 case Property::UNSIGNED_INTEGER:
2990 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2991 DALI_ASSERT_DEBUG( NULL != property );
2993 // property is being used in a separate thread; queue a message to set the property
2994 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2999 case Property::FLOAT:
3001 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3002 DALI_ASSERT_DEBUG( NULL != property );
3004 // property is being used in a separate thread; queue a message to set the property
3005 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3010 case Property::VECTOR2:
3012 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3013 DALI_ASSERT_DEBUG( NULL != property );
3015 // property is being used in a separate thread; queue a message to set the property
3016 if(entry.componentIndex == 0)
3018 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3020 else if(entry.componentIndex == 1)
3022 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3026 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3032 case Property::VECTOR3:
3034 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3035 DALI_ASSERT_DEBUG( NULL != property );
3037 // property is being used in a separate thread; queue a message to set the property
3038 if(entry.componentIndex == 0)
3040 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3042 else if(entry.componentIndex == 1)
3044 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3046 else if(entry.componentIndex == 2)
3048 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3052 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3058 case Property::VECTOR4:
3060 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3061 DALI_ASSERT_DEBUG( NULL != property );
3063 // property is being used in a separate thread; queue a message to set the property
3064 if(entry.componentIndex == 0)
3066 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3068 else if(entry.componentIndex == 1)
3070 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3072 else if(entry.componentIndex == 2)
3074 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3076 else if(entry.componentIndex == 3)
3078 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3082 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3088 case Property::ROTATION:
3090 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3091 DALI_ASSERT_DEBUG( NULL != property );
3093 // property is being used in a separate thread; queue a message to set the property
3094 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3099 case Property::MATRIX:
3101 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3102 DALI_ASSERT_DEBUG( NULL != property );
3104 // property is being used in a separate thread; queue a message to set the property
3105 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3110 case Property::MATRIX3:
3112 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3113 DALI_ASSERT_DEBUG( NULL != property );
3115 // property is being used in a separate thread; queue a message to set the property
3116 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3123 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3129 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3131 Property::Value value;
3135 case Dali::Actor::Property::PARENT_ORIGIN:
3137 value = GetCurrentParentOrigin();
3141 case Dali::Actor::Property::PARENT_ORIGIN_X:
3143 value = GetCurrentParentOrigin().x;
3147 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3149 value = GetCurrentParentOrigin().y;
3153 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3155 value = GetCurrentParentOrigin().z;
3159 case Dali::Actor::Property::ANCHOR_POINT:
3161 value = GetCurrentAnchorPoint();
3165 case Dali::Actor::Property::ANCHOR_POINT_X:
3167 value = GetCurrentAnchorPoint().x;
3171 case Dali::Actor::Property::ANCHOR_POINT_Y:
3173 value = GetCurrentAnchorPoint().y;
3177 case Dali::Actor::Property::ANCHOR_POINT_Z:
3179 value = GetCurrentAnchorPoint().z;
3183 case Dali::Actor::Property::SIZE:
3185 value = GetCurrentSize();
3189 case Dali::Actor::Property::SIZE_WIDTH:
3191 value = GetCurrentSize().width;
3195 case Dali::Actor::Property::SIZE_HEIGHT:
3197 value = GetCurrentSize().height;
3201 case Dali::Actor::Property::SIZE_DEPTH:
3203 value = GetCurrentSize().depth;
3207 case Dali::Actor::Property::POSITION:
3209 value = GetCurrentPosition();
3213 case Dali::Actor::Property::POSITION_X:
3215 value = GetCurrentPosition().x;
3219 case Dali::Actor::Property::POSITION_Y:
3221 value = GetCurrentPosition().y;
3225 case Dali::Actor::Property::POSITION_Z:
3227 value = GetCurrentPosition().z;
3231 case Dali::Actor::Property::WORLD_POSITION:
3233 value = GetCurrentWorldPosition();
3237 case Dali::Actor::Property::WORLD_POSITION_X:
3239 value = GetCurrentWorldPosition().x;
3243 case Dali::Actor::Property::WORLD_POSITION_Y:
3245 value = GetCurrentWorldPosition().y;
3249 case Dali::Actor::Property::WORLD_POSITION_Z:
3251 value = GetCurrentWorldPosition().z;
3255 case Dali::Actor::Property::ORIENTATION:
3257 value = GetCurrentOrientation();
3261 case Dali::Actor::Property::WORLD_ORIENTATION:
3263 value = GetCurrentWorldOrientation();
3267 case Dali::Actor::Property::SCALE:
3269 value = GetCurrentScale();
3273 case Dali::Actor::Property::SCALE_X:
3275 value = GetCurrentScale().x;
3279 case Dali::Actor::Property::SCALE_Y:
3281 value = GetCurrentScale().y;
3285 case Dali::Actor::Property::SCALE_Z:
3287 value = GetCurrentScale().z;
3291 case Dali::Actor::Property::WORLD_SCALE:
3293 value = GetCurrentWorldScale();
3297 case Dali::Actor::Property::VISIBLE:
3299 value = IsVisible();
3303 case Dali::Actor::Property::COLOR:
3305 value = GetCurrentColor();
3309 case Dali::Actor::Property::COLOR_RED:
3311 value = GetCurrentColor().r;
3315 case Dali::Actor::Property::COLOR_GREEN:
3317 value = GetCurrentColor().g;
3321 case Dali::Actor::Property::COLOR_BLUE:
3323 value = GetCurrentColor().b;
3327 case Dali::Actor::Property::COLOR_ALPHA:
3329 value = GetCurrentColor().a;
3333 case Dali::Actor::Property::WORLD_COLOR:
3335 value = GetCurrentWorldColor();
3339 case Dali::Actor::Property::WORLD_MATRIX:
3341 value = GetCurrentWorldMatrix();
3345 case Dali::Actor::Property::NAME:
3351 case Dali::Actor::Property::SENSITIVE:
3353 value = IsSensitive();
3357 case Dali::Actor::Property::LEAVE_REQUIRED:
3359 value = GetLeaveRequired();
3363 case Dali::Actor::Property::INHERIT_ORIENTATION:
3365 value = IsOrientationInherited();
3369 case Dali::Actor::Property::INHERIT_SCALE:
3371 value = IsScaleInherited();
3375 case Dali::Actor::Property::COLOR_MODE:
3377 value = Scripting::GetColorMode( GetColorMode() );
3381 case Dali::Actor::Property::POSITION_INHERITANCE:
3383 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3387 case Dali::Actor::Property::DRAW_MODE:
3389 value = Scripting::GetDrawMode( GetDrawMode() );
3393 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3395 value = GetSizeModeFactor();
3399 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3401 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3405 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3407 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3411 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3413 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3417 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3419 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3423 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3425 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3429 case Dali::Actor::Property::PADDING:
3431 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3432 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3433 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3437 case Dali::Actor::Property::MINIMUM_SIZE:
3439 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3443 case Dali::Actor::Property::MAXIMUM_SIZE:
3445 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3451 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3459 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3464 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3466 // This method should only return an object connected to the scene-graph
3467 return OnStage() ? mNode : NULL;
3470 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3472 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3474 const PropertyBase* property( NULL );
3476 // This method should only return a property of an object connected to the scene-graph
3482 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3484 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3485 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3487 property = animatable->GetSceneGraphProperty();
3489 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3491 CustomPropertyMetadata* custom = FindCustomProperty( index );
3492 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3494 property = custom->GetSceneGraphProperty();
3496 else if( NULL != mNode )
3500 case Dali::Actor::Property::SIZE:
3501 property = &mNode->mSize;
3504 case Dali::Actor::Property::SIZE_WIDTH:
3505 property = &mNode->mSize;
3508 case Dali::Actor::Property::SIZE_HEIGHT:
3509 property = &mNode->mSize;
3512 case Dali::Actor::Property::SIZE_DEPTH:
3513 property = &mNode->mSize;
3516 case Dali::Actor::Property::POSITION:
3517 property = &mNode->mPosition;
3520 case Dali::Actor::Property::POSITION_X:
3521 property = &mNode->mPosition;
3524 case Dali::Actor::Property::POSITION_Y:
3525 property = &mNode->mPosition;
3528 case Dali::Actor::Property::POSITION_Z:
3529 property = &mNode->mPosition;
3532 case Dali::Actor::Property::ORIENTATION:
3533 property = &mNode->mOrientation;
3536 case Dali::Actor::Property::SCALE:
3537 property = &mNode->mScale;
3540 case Dali::Actor::Property::SCALE_X:
3541 property = &mNode->mScale;
3544 case Dali::Actor::Property::SCALE_Y:
3545 property = &mNode->mScale;
3548 case Dali::Actor::Property::SCALE_Z:
3549 property = &mNode->mScale;
3552 case Dali::Actor::Property::VISIBLE:
3553 property = &mNode->mVisible;
3556 case Dali::Actor::Property::COLOR:
3557 property = &mNode->mColor;
3560 case Dali::Actor::Property::COLOR_RED:
3561 property = &mNode->mColor;
3564 case Dali::Actor::Property::COLOR_GREEN:
3565 property = &mNode->mColor;
3568 case Dali::Actor::Property::COLOR_BLUE:
3569 property = &mNode->mColor;
3572 case Dali::Actor::Property::COLOR_ALPHA:
3573 property = &mNode->mColor;
3584 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3586 const PropertyInputImpl* property( NULL );
3588 // This method should only return a property of an object connected to the scene-graph
3594 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3596 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3597 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3599 property = animatable->GetSceneGraphProperty();
3601 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3603 CustomPropertyMetadata* custom = FindCustomProperty( index );
3604 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3605 property = custom->GetSceneGraphProperty();
3607 else if( NULL != mNode )
3611 case Dali::Actor::Property::PARENT_ORIGIN:
3612 property = &mNode->mParentOrigin;
3615 case Dali::Actor::Property::PARENT_ORIGIN_X:
3616 property = &mNode->mParentOrigin;
3619 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3620 property = &mNode->mParentOrigin;
3623 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3624 property = &mNode->mParentOrigin;
3627 case Dali::Actor::Property::ANCHOR_POINT:
3628 property = &mNode->mAnchorPoint;
3631 case Dali::Actor::Property::ANCHOR_POINT_X:
3632 property = &mNode->mAnchorPoint;
3635 case Dali::Actor::Property::ANCHOR_POINT_Y:
3636 property = &mNode->mAnchorPoint;
3639 case Dali::Actor::Property::ANCHOR_POINT_Z:
3640 property = &mNode->mAnchorPoint;
3643 case Dali::Actor::Property::SIZE:
3644 property = &mNode->mSize;
3647 case Dali::Actor::Property::SIZE_WIDTH:
3648 property = &mNode->mSize;
3651 case Dali::Actor::Property::SIZE_HEIGHT:
3652 property = &mNode->mSize;
3655 case Dali::Actor::Property::SIZE_DEPTH:
3656 property = &mNode->mSize;
3659 case Dali::Actor::Property::POSITION:
3660 property = &mNode->mPosition;
3663 case Dali::Actor::Property::POSITION_X:
3664 property = &mNode->mPosition;
3667 case Dali::Actor::Property::POSITION_Y:
3668 property = &mNode->mPosition;
3671 case Dali::Actor::Property::POSITION_Z:
3672 property = &mNode->mPosition;
3675 case Dali::Actor::Property::WORLD_POSITION:
3676 property = &mNode->mWorldPosition;
3679 case Dali::Actor::Property::WORLD_POSITION_X:
3680 property = &mNode->mWorldPosition;
3683 case Dali::Actor::Property::WORLD_POSITION_Y:
3684 property = &mNode->mWorldPosition;
3687 case Dali::Actor::Property::WORLD_POSITION_Z:
3688 property = &mNode->mWorldPosition;
3691 case Dali::Actor::Property::ORIENTATION:
3692 property = &mNode->mOrientation;
3695 case Dali::Actor::Property::WORLD_ORIENTATION:
3696 property = &mNode->mWorldOrientation;
3699 case Dali::Actor::Property::SCALE:
3700 property = &mNode->mScale;
3703 case Dali::Actor::Property::SCALE_X:
3704 property = &mNode->mScale;
3707 case Dali::Actor::Property::SCALE_Y:
3708 property = &mNode->mScale;
3711 case Dali::Actor::Property::SCALE_Z:
3712 property = &mNode->mScale;
3715 case Dali::Actor::Property::WORLD_SCALE:
3716 property = &mNode->mWorldScale;
3719 case Dali::Actor::Property::VISIBLE:
3720 property = &mNode->mVisible;
3723 case Dali::Actor::Property::COLOR:
3724 property = &mNode->mColor;
3727 case Dali::Actor::Property::COLOR_RED:
3728 property = &mNode->mColor;
3731 case Dali::Actor::Property::COLOR_GREEN:
3732 property = &mNode->mColor;
3735 case Dali::Actor::Property::COLOR_BLUE:
3736 property = &mNode->mColor;
3739 case Dali::Actor::Property::COLOR_ALPHA:
3740 property = &mNode->mColor;
3743 case Dali::Actor::Property::WORLD_COLOR:
3744 property = &mNode->mWorldColor;
3747 case Dali::Actor::Property::WORLD_MATRIX:
3748 property = &mNode->mWorldMatrix;
3759 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3761 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3763 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3765 // check whether the animatable property is registered already, if not then register one.
3766 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3767 if( animatableProperty )
3769 componentIndex = animatableProperty->componentIndex;
3776 case Dali::Actor::Property::PARENT_ORIGIN_X:
3777 case Dali::Actor::Property::ANCHOR_POINT_X:
3778 case Dali::Actor::Property::SIZE_WIDTH:
3779 case Dali::Actor::Property::POSITION_X:
3780 case Dali::Actor::Property::WORLD_POSITION_X:
3781 case Dali::Actor::Property::SCALE_X:
3782 case Dali::Actor::Property::COLOR_RED:
3788 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3789 case Dali::Actor::Property::ANCHOR_POINT_Y:
3790 case Dali::Actor::Property::SIZE_HEIGHT:
3791 case Dali::Actor::Property::POSITION_Y:
3792 case Dali::Actor::Property::WORLD_POSITION_Y:
3793 case Dali::Actor::Property::SCALE_Y:
3794 case Dali::Actor::Property::COLOR_GREEN:
3800 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3801 case Dali::Actor::Property::ANCHOR_POINT_Z:
3802 case Dali::Actor::Property::SIZE_DEPTH:
3803 case Dali::Actor::Property::POSITION_Z:
3804 case Dali::Actor::Property::WORLD_POSITION_Z:
3805 case Dali::Actor::Property::SCALE_Z:
3806 case Dali::Actor::Property::COLOR_BLUE:
3812 case Dali::Actor::Property::COLOR_ALPHA:
3826 return componentIndex;
3829 void Actor::SetParent( Actor* parent, int index )
3833 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3837 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3840 // Instruct each actor to create a corresponding node in the scene graph
3841 ConnectToStage( index );
3844 else // parent being set to NULL
3846 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3850 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3853 DALI_ASSERT_ALWAYS( mNode != NULL );
3857 // Disconnect the Node & its children from the scene-graph.
3858 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3861 // Instruct each actor to discard pointers to the scene-graph
3862 DisconnectFromStage();
3867 SceneGraph::Node* Actor::CreateNode() const
3872 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3875 Actor* actor = dynamic_cast< Actor* >( object );
3879 if( 0 == actionName.compare( ACTION_SHOW ) )
3881 actor->SetVisible( true );
3884 else if( 0 == actionName.compare( ACTION_HIDE ) )
3886 actor->SetVisible( false );
3894 void Actor::EnsureRelayoutData() const
3896 // Assign relayout data.
3897 if( !mRelayoutData )
3899 mRelayoutData = new RelayoutData();
3903 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3905 // Check if actor is dependent on parent
3906 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3908 if( ( dimension & ( 1 << i ) ) )
3910 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3911 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3921 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3923 // Check if actor is dependent on children
3924 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3926 if( ( dimension & ( 1 << i ) ) )
3928 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3929 switch( resizePolicy )
3931 case ResizePolicy::FIT_TO_CHILDREN:
3932 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3948 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3950 return Actor::RelayoutDependentOnChildren( dimension );
3953 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3955 // Check each possible dimension and see if it is dependent on the input one
3956 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3958 if( dimension & ( 1 << i ) )
3960 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3967 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3969 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3971 if( dimension & ( 1 << i ) )
3973 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3978 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3980 // If more than one dimension is requested, just return the first one found
3981 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3983 if( ( dimension & ( 1 << i ) ) )
3985 return mRelayoutData->negotiatedDimensions[ i ];
3989 return 0.0f; // Default
3992 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3994 EnsureRelayoutData();
3996 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3998 if( dimension & ( 1 << i ) )
4000 mRelayoutData->dimensionPadding[ i ] = padding;
4005 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4007 EnsureRelayoutData();
4009 // If more than one dimension is requested, just return the first one found
4010 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4012 if( ( dimension & ( 1 << i ) ) )
4014 return mRelayoutData->dimensionPadding[ i ];
4018 return Vector2( 0.0f, 0.0f ); // Default
4021 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4023 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4025 if( dimension & ( 1 << i ) )
4027 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4032 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4034 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4036 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4045 float Actor::GetHeightForWidthBase( float width )
4047 float height = 0.0f;
4049 const Vector3 naturalSize = GetNaturalSize();
4050 if( naturalSize.width > 0.0f )
4052 height = naturalSize.height * width / naturalSize.width;
4054 else // we treat 0 as 1:1 aspect ratio
4062 float Actor::GetWidthForHeightBase( float height )
4066 const Vector3 naturalSize = GetNaturalSize();
4067 if( naturalSize.height > 0.0f )
4069 width = naturalSize.width * height / naturalSize.height;
4071 else // we treat 0 as 1:1 aspect ratio
4079 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4081 // Fill to parent, taking size mode factor into account
4082 switch( child.GetResizePolicy( dimension ) )
4084 case ResizePolicy::FILL_TO_PARENT:
4086 return GetLatestSize( dimension );
4089 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4091 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4094 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4096 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4101 return GetLatestSize( dimension );
4106 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4108 // Can be overridden in derived class
4109 return CalculateChildSizeBase( child, dimension );
4112 float Actor::GetHeightForWidth( float width )
4114 // Can be overridden in derived class
4115 return GetHeightForWidthBase( width );
4118 float Actor::GetWidthForHeight( float height )
4120 // Can be overridden in derived class
4121 return GetWidthForHeightBase( height );
4124 float Actor::GetLatestSize( Dimension::Type dimension ) const
4126 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4129 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4131 Vector2 padding = GetPadding( dimension );
4133 return GetLatestSize( dimension ) + padding.x + padding.y;
4136 float Actor::NegotiateFromParent( Dimension::Type dimension )
4138 Actor* parent = GetParent();
4141 Vector2 padding( GetPadding( dimension ) );
4142 Vector2 parentPadding( parent->GetPadding( dimension ) );
4143 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4149 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4151 float maxDimensionPoint = 0.0f;
4153 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4155 Dali::Actor child = GetChildAt( i );
4156 Actor& childImpl = GetImplementation( child );
4158 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4160 // Calculate the min and max points that the children range across
4161 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4162 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4163 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4167 return maxDimensionPoint;
4170 float Actor::GetSize( Dimension::Type dimension ) const
4172 return GetDimensionValue( GetTargetSize(), dimension );
4175 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4177 return GetDimensionValue( GetNaturalSize(), dimension );
4180 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4182 switch( GetResizePolicy( dimension ) )
4184 case ResizePolicy::USE_NATURAL_SIZE:
4186 return GetNaturalSize( dimension );
4189 case ResizePolicy::FIXED:
4191 return GetDimensionValue( GetPreferredSize(), dimension );
4194 case ResizePolicy::USE_ASSIGNED_SIZE:
4196 return GetDimensionValue( maximumSize, dimension );
4199 case ResizePolicy::FILL_TO_PARENT:
4200 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4201 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4203 return NegotiateFromParent( dimension );
4206 case ResizePolicy::FIT_TO_CHILDREN:
4208 return NegotiateFromChildren( dimension );
4211 case ResizePolicy::DIMENSION_DEPENDENCY:
4213 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4216 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4218 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4221 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4223 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4235 return 0.0f; // Default
4238 float Actor::ClampDimension( float size, Dimension::Type dimension )
4240 const float minSize = GetMinimumSize( dimension );
4241 const float maxSize = GetMaximumSize( dimension );
4243 return std::max( minSize, std::min( size, maxSize ) );
4246 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4248 // Check if it needs to be negotiated
4249 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4251 // Check that we havn't gotten into an infinite loop
4252 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4253 bool recursionFound = false;
4254 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4256 if( *it == searchActor )
4258 recursionFound = true;
4263 if( !recursionFound )
4265 // Record the path that we have taken
4266 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4268 // Dimension dependency check
4269 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4271 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4273 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4275 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4279 // Parent dependency check
4280 Actor* parent = GetParent();
4281 if( parent && RelayoutDependentOnParent( dimension ) )
4283 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4286 // Children dependency check
4287 if( RelayoutDependentOnChildren( dimension ) )
4289 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4291 Dali::Actor child = GetChildAt( i );
4292 Actor& childImpl = GetImplementation( child );
4294 // Only relayout child first if it is not dependent on this actor
4295 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4297 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4302 // For deriving classes
4303 OnCalculateRelayoutSize( dimension );
4305 // All dependencies checked, calculate the size and set negotiated flag
4306 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4308 SetNegotiatedDimension( newSize, dimension );
4309 SetLayoutNegotiated( true, dimension );
4311 // For deriving classes
4312 OnLayoutNegotiated( newSize, dimension );
4314 // This actor has been successfully processed, pop it off the recursion stack
4315 recursionStack.pop_back();
4319 // TODO: Break infinite loop
4320 SetLayoutNegotiated( true, dimension );
4325 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4327 // Negotiate all dimensions that require it
4328 ActorDimensionStack recursionStack;
4330 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4332 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4335 NegotiateDimension( dimension, allocatedSize, recursionStack );
4339 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4341 switch( mRelayoutData->sizeSetPolicy )
4343 case SizeScalePolicy::USE_SIZE_SET:
4348 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4350 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4351 const Vector3 naturalSize = GetNaturalSize();
4352 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4354 const float sizeRatio = size.width / size.height;
4355 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4357 if( naturalSizeRatio < sizeRatio )
4359 return Vector2( naturalSizeRatio * size.height, size.height );
4361 else if( naturalSizeRatio > sizeRatio )
4363 return Vector2( size.width, size.width / naturalSizeRatio );
4374 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4376 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4377 const Vector3 naturalSize = GetNaturalSize();
4378 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4380 const float sizeRatio = size.width / size.height;
4381 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4383 if( naturalSizeRatio < sizeRatio )
4385 return Vector2( size.width, size.width / naturalSizeRatio );
4387 else if( naturalSizeRatio > sizeRatio )
4389 return Vector2( naturalSizeRatio * size.height, size.height );
4407 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4409 // Do the set actor size
4410 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4412 // Adjust for size set policy
4413 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4415 // Lock the flag to stop recursive relayouts on set size
4416 mRelayoutData->insideRelayout = true;
4417 SetSize( negotiatedSize );
4418 mRelayoutData->insideRelayout = false;
4420 // Clear flags for all dimensions
4421 SetLayoutDirty( false );
4423 // Give deriving classes a chance to respond
4424 OnRelayout( negotiatedSize, container );
4426 if( !mOnRelayoutSignal.Empty() )
4428 Dali::Actor handle( this );
4429 mOnRelayoutSignal.Emit( handle );
4433 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4435 // Do the negotiation
4436 NegotiateDimensions( allocatedSize );
4438 // Set the actor size
4439 SetNegotiatedSize( container );
4441 // Negotiate down to children
4442 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4444 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4446 Dali::Actor child = GetChildAt( i );
4448 // Only relayout if required
4449 if( GetImplementation( child ).RelayoutRequired() )
4451 container.Add( child, newBounds );
4456 void Actor::RelayoutRequest( Dimension::Type dimension )
4458 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4459 if( relayoutController )
4461 Dali::Actor self( this );
4462 relayoutController->RequestRelayout( self, dimension );
4466 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4470 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4474 void Actor::SetPreferredSize( const Vector2& size )
4476 EnsureRelayoutData();
4478 if( size.width > 0.0f )
4480 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4483 if( size.height > 0.0f )
4485 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4488 mRelayoutData->preferredSize = size;
4493 Vector2 Actor::GetPreferredSize() const
4495 EnsureRelayoutData();
4497 return mRelayoutData->preferredSize;
4500 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4502 EnsureRelayoutData();
4504 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4506 if( dimension & ( 1 << i ) )
4508 mRelayoutData->minimumSize[ i ] = size;
4515 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4517 EnsureRelayoutData();
4519 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4521 if( dimension & ( 1 << i ) )
4523 return mRelayoutData->minimumSize[ i ];
4527 return 0.0f; // Default
4530 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4532 EnsureRelayoutData();
4534 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4536 if( dimension & ( 1 << i ) )
4538 mRelayoutData->maximumSize[ i ] = size;
4545 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4547 EnsureRelayoutData();
4549 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4551 if( dimension & ( 1 << i ) )
4553 return mRelayoutData->maximumSize[ i ];
4557 return 0.0f; // Default
4560 } // namespace Internal