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 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 )DALI_ENUM_TO_STRING( FIXED )
75 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
76 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
77 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
79 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
80 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
81 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
82 DALI_ENUM_TO_STRING_TABLE_END( Type )
84 } // unnamed namespace
87 namespace SizeScalePolicy
91 // Enumeration to / from string conversion tables
92 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
93 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
94 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
95 DALI_ENUM_TO_STRING_TABLE_END( Type )
96 } // unnamed namespace
102 unsigned int Actor::mActorCounter = 0;
105 * Struct to collect relayout variables
107 struct Actor::RelayoutData
110 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
112 // Set size negotiation defaults
113 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
115 resizePolicies[ i ] = ResizePolicy::FIXED;
116 negotiatedDimensions[ i ] = 0.0f;
117 dimensionNegotiated[ i ] = false;
118 dimensionDirty[ i ] = false;
119 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
120 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
121 minimumSize[ i ] = 0.0f;
122 maximumSize[ i ] = FLT_MAX;
126 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
128 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
130 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
132 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
134 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
135 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
137 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
138 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
140 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
142 Vector2 preferredSize; ///< The preferred size of the actor
144 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
146 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
147 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
150 #ifdef DYNAMICS_SUPPORT
152 // Encapsulate actor related dynamics data
155 DynamicsData( Actor* slotOwner )
156 : slotDelegate( slotOwner )
160 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
161 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
163 DynamicsBodyPtr body;
164 JointContainer joints;
165 ReferencedJointContainer referencedJoints;
167 SlotDelegate< Actor > slotDelegate;
170 #endif // DYNAMICS_SUPPORT
172 namespace // unnamed namespace
178 * We want to discourage the use of property strings (minimize string comparisons),
179 * particularly for the default properties.
180 * Name Type writable animatable constraint-input enum for index-checking
182 DALI_PROPERTY_TABLE_BEGIN
183 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
184 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
185 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
186 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
187 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
188 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
189 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
190 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
191 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
192 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
193 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
194 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
195 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
196 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
197 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
198 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
199 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
200 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
201 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
202 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
203 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
204 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
205 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
206 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
207 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
208 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
209 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
210 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
211 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
212 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
213 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
214 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
215 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
216 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
217 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
218 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
219 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
220 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
221 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
222 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
223 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
224 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
225 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
226 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
227 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
228 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
229 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
230 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
231 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
232 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
233 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
234 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
235 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
239 const char* const SIGNAL_TOUCHED = "touched";
240 const char* const SIGNAL_HOVERED = "hovered";
241 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
242 const char* const SIGNAL_ON_STAGE = "on-stage";
243 const char* const SIGNAL_OFF_STAGE = "off-stage";
247 const char* const ACTION_SHOW = "show";
248 const char* const ACTION_HIDE = "hide";
250 BaseHandle CreateActor()
252 return Dali::Actor::New();
255 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
257 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
266 * @brief Extract a given dimension from a Vector2
268 * @param[in] values The values to extract from
269 * @param[in] dimension The dimension to extract
270 * @return Return the value for the dimension
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
276 case Dimension::WIDTH:
281 case Dimension::HEIGHT:
283 return values.height;
296 * @brief Extract a given dimension from a Vector3
298 * @param[in] values The values to extract from
299 * @param[in] dimension The dimension to extract
300 * @return Return the value for the dimension
302 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
304 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::FIXED; // 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 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 // 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 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 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 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 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 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2887 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2889 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2893 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2895 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2899 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2901 if( property.Get< bool >() )
2903 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2908 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2910 if( property.Get< bool >() )
2912 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2917 case Dali::Actor::Property::PADDING:
2919 Vector4 padding = property.Get< Vector4 >();
2920 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2921 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2925 case Dali::Actor::Property::MINIMUM_SIZE:
2927 Vector2 size = property.Get< Vector2 >();
2928 SetMinimumSize( size.x, Dimension::WIDTH );
2929 SetMinimumSize( size.y, Dimension::HEIGHT );
2933 case Dali::Actor::Property::MAXIMUM_SIZE:
2935 Vector2 size = property.Get< Vector2 >();
2936 SetMaximumSize( size.x, Dimension::WIDTH );
2937 SetMaximumSize( size.y, Dimension::HEIGHT );
2943 // this can happen in the case of a non-animatable default property so just do nothing
2949 // TODO: This method needs to be removed
2950 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2952 switch( entry.type )
2954 case Property::BOOLEAN:
2956 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2957 DALI_ASSERT_DEBUG( NULL != property );
2959 // property is being used in a separate thread; queue a message to set the property
2960 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2965 case Property::INTEGER:
2967 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2968 DALI_ASSERT_DEBUG( NULL != property );
2970 // property is being used in a separate thread; queue a message to set the property
2971 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2976 case Property::UNSIGNED_INTEGER:
2978 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2979 DALI_ASSERT_DEBUG( NULL != property );
2981 // property is being used in a separate thread; queue a message to set the property
2982 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2987 case Property::FLOAT:
2989 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2990 DALI_ASSERT_DEBUG( NULL != property );
2992 // property is being used in a separate thread; queue a message to set the property
2993 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2998 case Property::VECTOR2:
3000 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3001 DALI_ASSERT_DEBUG( NULL != property );
3003 // property is being used in a separate thread; queue a message to set the property
3004 if(entry.componentIndex == 0)
3006 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3008 else if(entry.componentIndex == 1)
3010 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3014 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3020 case Property::VECTOR3:
3022 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3023 DALI_ASSERT_DEBUG( NULL != property );
3025 // property is being used in a separate thread; queue a message to set the property
3026 if(entry.componentIndex == 0)
3028 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3030 else if(entry.componentIndex == 1)
3032 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3034 else if(entry.componentIndex == 2)
3036 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3040 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3046 case Property::VECTOR4:
3048 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3049 DALI_ASSERT_DEBUG( NULL != property );
3051 // property is being used in a separate thread; queue a message to set the property
3052 if(entry.componentIndex == 0)
3054 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3056 else if(entry.componentIndex == 1)
3058 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3060 else if(entry.componentIndex == 2)
3062 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3064 else if(entry.componentIndex == 3)
3066 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3070 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3076 case Property::ROTATION:
3078 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3079 DALI_ASSERT_DEBUG( NULL != property );
3081 // property is being used in a separate thread; queue a message to set the property
3082 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3087 case Property::MATRIX:
3089 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3090 DALI_ASSERT_DEBUG( NULL != property );
3092 // property is being used in a separate thread; queue a message to set the property
3093 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3098 case Property::MATRIX3:
3100 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3101 DALI_ASSERT_DEBUG( NULL != property );
3103 // property is being used in a separate thread; queue a message to set the property
3104 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3111 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3117 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3119 Property::Value value;
3123 case Dali::Actor::Property::PARENT_ORIGIN:
3125 value = GetCurrentParentOrigin();
3129 case Dali::Actor::Property::PARENT_ORIGIN_X:
3131 value = GetCurrentParentOrigin().x;
3135 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3137 value = GetCurrentParentOrigin().y;
3141 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3143 value = GetCurrentParentOrigin().z;
3147 case Dali::Actor::Property::ANCHOR_POINT:
3149 value = GetCurrentAnchorPoint();
3153 case Dali::Actor::Property::ANCHOR_POINT_X:
3155 value = GetCurrentAnchorPoint().x;
3159 case Dali::Actor::Property::ANCHOR_POINT_Y:
3161 value = GetCurrentAnchorPoint().y;
3165 case Dali::Actor::Property::ANCHOR_POINT_Z:
3167 value = GetCurrentAnchorPoint().z;
3171 case Dali::Actor::Property::SIZE:
3173 value = GetCurrentSize();
3177 case Dali::Actor::Property::SIZE_WIDTH:
3179 value = GetCurrentSize().width;
3183 case Dali::Actor::Property::SIZE_HEIGHT:
3185 value = GetCurrentSize().height;
3189 case Dali::Actor::Property::SIZE_DEPTH:
3191 value = GetCurrentSize().depth;
3195 case Dali::Actor::Property::POSITION:
3197 value = GetCurrentPosition();
3201 case Dali::Actor::Property::POSITION_X:
3203 value = GetCurrentPosition().x;
3207 case Dali::Actor::Property::POSITION_Y:
3209 value = GetCurrentPosition().y;
3213 case Dali::Actor::Property::POSITION_Z:
3215 value = GetCurrentPosition().z;
3219 case Dali::Actor::Property::WORLD_POSITION:
3221 value = GetCurrentWorldPosition();
3225 case Dali::Actor::Property::WORLD_POSITION_X:
3227 value = GetCurrentWorldPosition().x;
3231 case Dali::Actor::Property::WORLD_POSITION_Y:
3233 value = GetCurrentWorldPosition().y;
3237 case Dali::Actor::Property::WORLD_POSITION_Z:
3239 value = GetCurrentWorldPosition().z;
3243 case Dali::Actor::Property::ORIENTATION:
3245 value = GetCurrentOrientation();
3249 case Dali::Actor::Property::WORLD_ORIENTATION:
3251 value = GetCurrentWorldOrientation();
3255 case Dali::Actor::Property::SCALE:
3257 value = GetCurrentScale();
3261 case Dali::Actor::Property::SCALE_X:
3263 value = GetCurrentScale().x;
3267 case Dali::Actor::Property::SCALE_Y:
3269 value = GetCurrentScale().y;
3273 case Dali::Actor::Property::SCALE_Z:
3275 value = GetCurrentScale().z;
3279 case Dali::Actor::Property::WORLD_SCALE:
3281 value = GetCurrentWorldScale();
3285 case Dali::Actor::Property::VISIBLE:
3287 value = IsVisible();
3291 case Dali::Actor::Property::COLOR:
3293 value = GetCurrentColor();
3297 case Dali::Actor::Property::COLOR_RED:
3299 value = GetCurrentColor().r;
3303 case Dali::Actor::Property::COLOR_GREEN:
3305 value = GetCurrentColor().g;
3309 case Dali::Actor::Property::COLOR_BLUE:
3311 value = GetCurrentColor().b;
3315 case Dali::Actor::Property::COLOR_ALPHA:
3317 value = GetCurrentColor().a;
3321 case Dali::Actor::Property::WORLD_COLOR:
3323 value = GetCurrentWorldColor();
3327 case Dali::Actor::Property::WORLD_MATRIX:
3329 value = GetCurrentWorldMatrix();
3333 case Dali::Actor::Property::NAME:
3339 case Dali::Actor::Property::SENSITIVE:
3341 value = IsSensitive();
3345 case Dali::Actor::Property::LEAVE_REQUIRED:
3347 value = GetLeaveRequired();
3351 case Dali::Actor::Property::INHERIT_ORIENTATION:
3353 value = IsOrientationInherited();
3357 case Dali::Actor::Property::INHERIT_SCALE:
3359 value = IsScaleInherited();
3363 case Dali::Actor::Property::COLOR_MODE:
3365 value = Scripting::GetColorMode( GetColorMode() );
3369 case Dali::Actor::Property::POSITION_INHERITANCE:
3371 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3375 case Dali::Actor::Property::DRAW_MODE:
3377 value = Scripting::GetDrawMode( GetDrawMode() );
3381 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3383 value = GetSizeModeFactor();
3387 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3389 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3393 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3395 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3399 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3401 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3405 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3407 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3411 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3413 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3417 case Dali::Actor::Property::PADDING:
3419 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3420 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3421 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3425 case Dali::Actor::Property::MINIMUM_SIZE:
3427 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3431 case Dali::Actor::Property::MAXIMUM_SIZE:
3433 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3439 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3447 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3452 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3454 // This method should only return an object connected to the scene-graph
3455 return OnStage() ? mNode : NULL;
3458 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3460 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3462 const PropertyBase* property( NULL );
3464 // This method should only return a property of an object connected to the scene-graph
3470 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3472 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3473 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3475 property = animatable->GetSceneGraphProperty();
3477 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3479 CustomPropertyMetadata* custom = FindCustomProperty( index );
3480 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3482 property = custom->GetSceneGraphProperty();
3484 else if( NULL != mNode )
3488 case Dali::Actor::Property::SIZE:
3489 property = &mNode->mSize;
3492 case Dali::Actor::Property::SIZE_WIDTH:
3493 property = &mNode->mSize;
3496 case Dali::Actor::Property::SIZE_HEIGHT:
3497 property = &mNode->mSize;
3500 case Dali::Actor::Property::SIZE_DEPTH:
3501 property = &mNode->mSize;
3504 case Dali::Actor::Property::POSITION:
3505 property = &mNode->mPosition;
3508 case Dali::Actor::Property::POSITION_X:
3509 property = &mNode->mPosition;
3512 case Dali::Actor::Property::POSITION_Y:
3513 property = &mNode->mPosition;
3516 case Dali::Actor::Property::POSITION_Z:
3517 property = &mNode->mPosition;
3520 case Dali::Actor::Property::ORIENTATION:
3521 property = &mNode->mOrientation;
3524 case Dali::Actor::Property::SCALE:
3525 property = &mNode->mScale;
3528 case Dali::Actor::Property::SCALE_X:
3529 property = &mNode->mScale;
3532 case Dali::Actor::Property::SCALE_Y:
3533 property = &mNode->mScale;
3536 case Dali::Actor::Property::SCALE_Z:
3537 property = &mNode->mScale;
3540 case Dali::Actor::Property::VISIBLE:
3541 property = &mNode->mVisible;
3544 case Dali::Actor::Property::COLOR:
3545 property = &mNode->mColor;
3548 case Dali::Actor::Property::COLOR_RED:
3549 property = &mNode->mColor;
3552 case Dali::Actor::Property::COLOR_GREEN:
3553 property = &mNode->mColor;
3556 case Dali::Actor::Property::COLOR_BLUE:
3557 property = &mNode->mColor;
3560 case Dali::Actor::Property::COLOR_ALPHA:
3561 property = &mNode->mColor;
3572 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3574 const PropertyInputImpl* property( NULL );
3576 // This method should only return a property of an object connected to the scene-graph
3582 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3584 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3585 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3587 property = animatable->GetSceneGraphProperty();
3589 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3591 CustomPropertyMetadata* custom = FindCustomProperty( index );
3592 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3593 property = custom->GetSceneGraphProperty();
3595 else if( NULL != mNode )
3599 case Dali::Actor::Property::PARENT_ORIGIN:
3600 property = &mNode->mParentOrigin;
3603 case Dali::Actor::Property::PARENT_ORIGIN_X:
3604 property = &mNode->mParentOrigin;
3607 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3608 property = &mNode->mParentOrigin;
3611 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3612 property = &mNode->mParentOrigin;
3615 case Dali::Actor::Property::ANCHOR_POINT:
3616 property = &mNode->mAnchorPoint;
3619 case Dali::Actor::Property::ANCHOR_POINT_X:
3620 property = &mNode->mAnchorPoint;
3623 case Dali::Actor::Property::ANCHOR_POINT_Y:
3624 property = &mNode->mAnchorPoint;
3627 case Dali::Actor::Property::ANCHOR_POINT_Z:
3628 property = &mNode->mAnchorPoint;
3631 case Dali::Actor::Property::SIZE:
3632 property = &mNode->mSize;
3635 case Dali::Actor::Property::SIZE_WIDTH:
3636 property = &mNode->mSize;
3639 case Dali::Actor::Property::SIZE_HEIGHT:
3640 property = &mNode->mSize;
3643 case Dali::Actor::Property::SIZE_DEPTH:
3644 property = &mNode->mSize;
3647 case Dali::Actor::Property::POSITION:
3648 property = &mNode->mPosition;
3651 case Dali::Actor::Property::POSITION_X:
3652 property = &mNode->mPosition;
3655 case Dali::Actor::Property::POSITION_Y:
3656 property = &mNode->mPosition;
3659 case Dali::Actor::Property::POSITION_Z:
3660 property = &mNode->mPosition;
3663 case Dali::Actor::Property::WORLD_POSITION:
3664 property = &mNode->mWorldPosition;
3667 case Dali::Actor::Property::WORLD_POSITION_X:
3668 property = &mNode->mWorldPosition;
3671 case Dali::Actor::Property::WORLD_POSITION_Y:
3672 property = &mNode->mWorldPosition;
3675 case Dali::Actor::Property::WORLD_POSITION_Z:
3676 property = &mNode->mWorldPosition;
3679 case Dali::Actor::Property::ORIENTATION:
3680 property = &mNode->mOrientation;
3683 case Dali::Actor::Property::WORLD_ORIENTATION:
3684 property = &mNode->mWorldOrientation;
3687 case Dali::Actor::Property::SCALE:
3688 property = &mNode->mScale;
3691 case Dali::Actor::Property::SCALE_X:
3692 property = &mNode->mScale;
3695 case Dali::Actor::Property::SCALE_Y:
3696 property = &mNode->mScale;
3699 case Dali::Actor::Property::SCALE_Z:
3700 property = &mNode->mScale;
3703 case Dali::Actor::Property::WORLD_SCALE:
3704 property = &mNode->mWorldScale;
3707 case Dali::Actor::Property::VISIBLE:
3708 property = &mNode->mVisible;
3711 case Dali::Actor::Property::COLOR:
3712 property = &mNode->mColor;
3715 case Dali::Actor::Property::COLOR_RED:
3716 property = &mNode->mColor;
3719 case Dali::Actor::Property::COLOR_GREEN:
3720 property = &mNode->mColor;
3723 case Dali::Actor::Property::COLOR_BLUE:
3724 property = &mNode->mColor;
3727 case Dali::Actor::Property::COLOR_ALPHA:
3728 property = &mNode->mColor;
3731 case Dali::Actor::Property::WORLD_COLOR:
3732 property = &mNode->mWorldColor;
3735 case Dali::Actor::Property::WORLD_MATRIX:
3736 property = &mNode->mWorldMatrix;
3747 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3749 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3751 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3753 // check whether the animatable property is registered already, if not then register one.
3754 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3755 if( animatableProperty )
3757 componentIndex = animatableProperty->componentIndex;
3764 case Dali::Actor::Property::PARENT_ORIGIN_X:
3765 case Dali::Actor::Property::ANCHOR_POINT_X:
3766 case Dali::Actor::Property::SIZE_WIDTH:
3767 case Dali::Actor::Property::POSITION_X:
3768 case Dali::Actor::Property::WORLD_POSITION_X:
3769 case Dali::Actor::Property::SCALE_X:
3770 case Dali::Actor::Property::COLOR_RED:
3776 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3777 case Dali::Actor::Property::ANCHOR_POINT_Y:
3778 case Dali::Actor::Property::SIZE_HEIGHT:
3779 case Dali::Actor::Property::POSITION_Y:
3780 case Dali::Actor::Property::WORLD_POSITION_Y:
3781 case Dali::Actor::Property::SCALE_Y:
3782 case Dali::Actor::Property::COLOR_GREEN:
3788 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3789 case Dali::Actor::Property::ANCHOR_POINT_Z:
3790 case Dali::Actor::Property::SIZE_DEPTH:
3791 case Dali::Actor::Property::POSITION_Z:
3792 case Dali::Actor::Property::WORLD_POSITION_Z:
3793 case Dali::Actor::Property::SCALE_Z:
3794 case Dali::Actor::Property::COLOR_BLUE:
3800 case Dali::Actor::Property::COLOR_ALPHA:
3814 return componentIndex;
3817 void Actor::SetParent( Actor* parent, int index )
3821 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3825 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3828 // Instruct each actor to create a corresponding node in the scene graph
3829 ConnectToStage( index );
3832 else // parent being set to NULL
3834 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3838 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3841 DALI_ASSERT_ALWAYS( mNode != NULL );
3845 // Disconnect the Node & its children from the scene-graph.
3846 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3849 // Instruct each actor to discard pointers to the scene-graph
3850 DisconnectFromStage();
3855 SceneGraph::Node* Actor::CreateNode() const
3860 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3863 Actor* actor = dynamic_cast< Actor* >( object );
3867 if( 0 == actionName.compare( ACTION_SHOW ) )
3869 actor->SetVisible( true );
3872 else if( 0 == actionName.compare( ACTION_HIDE ) )
3874 actor->SetVisible( false );
3882 void Actor::EnsureRelayoutData() const
3884 // Assign relayout data.
3885 if( !mRelayoutData )
3887 mRelayoutData = new RelayoutData();
3891 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3893 // Check if actor is dependent on parent
3894 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3896 if( ( dimension & ( 1 << i ) ) )
3898 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3899 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3909 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3911 // Check if actor is dependent on children
3912 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3914 if( ( dimension & ( 1 << i ) ) )
3916 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3917 switch( resizePolicy )
3919 case ResizePolicy::FIT_TO_CHILDREN:
3920 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3936 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3938 return Actor::RelayoutDependentOnChildren( dimension );
3941 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3943 // Check each possible dimension and see if it is dependent on the input one
3944 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3946 if( dimension & ( 1 << i ) )
3948 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3955 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3957 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3959 if( dimension & ( 1 << i ) )
3961 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3966 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3968 // If more than one dimension is requested, just return the first one found
3969 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3971 if( ( dimension & ( 1 << i ) ) )
3973 return mRelayoutData->negotiatedDimensions[ i ];
3977 return 0.0f; // Default
3980 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3982 EnsureRelayoutData();
3984 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3986 if( dimension & ( 1 << i ) )
3988 mRelayoutData->dimensionPadding[ i ] = padding;
3993 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3995 EnsureRelayoutData();
3997 // If more than one dimension is requested, just return the first one found
3998 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4000 if( ( dimension & ( 1 << i ) ) )
4002 return mRelayoutData->dimensionPadding[ i ];
4006 return Vector2( 0.0f, 0.0f ); // Default
4009 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4011 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4013 if( dimension & ( 1 << i ) )
4015 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4020 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4022 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4024 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4033 float Actor::GetHeightForWidthBase( float width )
4035 float height = 0.0f;
4037 const Vector3 naturalSize = GetNaturalSize();
4038 if( naturalSize.width > 0.0f )
4040 height = naturalSize.height * width / naturalSize.width;
4042 else // we treat 0 as 1:1 aspect ratio
4050 float Actor::GetWidthForHeightBase( float height )
4054 const Vector3 naturalSize = GetNaturalSize();
4055 if( naturalSize.height > 0.0f )
4057 width = naturalSize.width * height / naturalSize.height;
4059 else // we treat 0 as 1:1 aspect ratio
4067 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4069 // Fill to parent, taking size mode factor into account
4070 switch( child.GetResizePolicy( dimension ) )
4072 case ResizePolicy::FILL_TO_PARENT:
4074 return GetLatestSize( dimension );
4077 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4079 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4082 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4084 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4089 return GetLatestSize( dimension );
4094 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4096 // Can be overridden in derived class
4097 return CalculateChildSizeBase( child, dimension );
4100 float Actor::GetHeightForWidth( float width )
4102 // Can be overridden in derived class
4103 return GetHeightForWidthBase( width );
4106 float Actor::GetWidthForHeight( float height )
4108 // Can be overridden in derived class
4109 return GetWidthForHeightBase( height );
4112 float Actor::GetLatestSize( Dimension::Type dimension ) const
4114 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4117 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4119 Vector2 padding = GetPadding( dimension );
4121 return GetLatestSize( dimension ) + padding.x + padding.y;
4124 float Actor::NegotiateFromParent( Dimension::Type dimension )
4126 Actor* parent = GetParent();
4129 Vector2 padding( GetPadding( dimension ) );
4130 Vector2 parentPadding( parent->GetPadding( dimension ) );
4131 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4137 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4139 float maxDimensionPoint = 0.0f;
4141 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4143 Dali::Actor child = GetChildAt( i );
4144 Actor& childImpl = GetImplementation( child );
4146 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4148 // Calculate the min and max points that the children range across
4149 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4150 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4151 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4155 return maxDimensionPoint;
4158 float Actor::GetSize( Dimension::Type dimension ) const
4160 return GetDimensionValue( GetTargetSize(), dimension );
4163 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4165 return GetDimensionValue( GetNaturalSize(), dimension );
4168 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4170 switch( GetResizePolicy( dimension ) )
4172 case ResizePolicy::USE_NATURAL_SIZE:
4174 return GetNaturalSize( dimension );
4177 case ResizePolicy::FIXED:
4179 return GetDimensionValue( GetPreferredSize(), dimension );
4182 case ResizePolicy::USE_ASSIGNED_SIZE:
4184 return GetDimensionValue( maximumSize, dimension );
4187 case ResizePolicy::FILL_TO_PARENT:
4188 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4189 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4191 return NegotiateFromParent( dimension );
4194 case ResizePolicy::FIT_TO_CHILDREN:
4196 return NegotiateFromChildren( dimension );
4199 case ResizePolicy::DIMENSION_DEPENDENCY:
4201 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4204 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4206 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4209 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4211 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4223 return 0.0f; // Default
4226 float Actor::ClampDimension( float size, Dimension::Type dimension )
4228 const float minSize = GetMinimumSize( dimension );
4229 const float maxSize = GetMaximumSize( dimension );
4231 return std::max( minSize, std::min( size, maxSize ) );
4234 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4236 // Check if it needs to be negotiated
4237 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4239 // Check that we havn't gotten into an infinite loop
4240 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4241 bool recursionFound = false;
4242 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4244 if( *it == searchActor )
4246 recursionFound = true;
4251 if( !recursionFound )
4253 // Record the path that we have taken
4254 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4256 // Dimension dependency check
4257 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4259 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4261 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4263 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4267 // Parent dependency check
4268 Actor* parent = GetParent();
4269 if( parent && RelayoutDependentOnParent( dimension ) )
4271 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4274 // Children dependency check
4275 if( RelayoutDependentOnChildren( dimension ) )
4277 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4279 Dali::Actor child = GetChildAt( i );
4280 Actor& childImpl = GetImplementation( child );
4282 // Only relayout child first if it is not dependent on this actor
4283 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4285 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4290 // For deriving classes
4291 OnCalculateRelayoutSize( dimension );
4293 // All dependencies checked, calculate the size and set negotiated flag
4294 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4296 SetNegotiatedDimension( newSize, dimension );
4297 SetLayoutNegotiated( true, dimension );
4299 // For deriving classes
4300 OnLayoutNegotiated( newSize, dimension );
4302 // This actor has been successfully processed, pop it off the recursion stack
4303 recursionStack.pop_back();
4307 // TODO: Break infinite loop
4308 SetLayoutNegotiated( true, dimension );
4313 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4315 // Negotiate all dimensions that require it
4316 ActorDimensionStack recursionStack;
4318 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4320 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4323 NegotiateDimension( dimension, allocatedSize, recursionStack );
4327 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4329 switch( mRelayoutData->sizeSetPolicy )
4331 case SizeScalePolicy::USE_SIZE_SET:
4336 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4338 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4339 const Vector3 naturalSize = GetNaturalSize();
4340 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4342 const float sizeRatio = size.width / size.height;
4343 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4345 if( naturalSizeRatio < sizeRatio )
4347 return Vector2( naturalSizeRatio * size.height, size.height );
4349 else if( naturalSizeRatio > sizeRatio )
4351 return Vector2( size.width, size.width / naturalSizeRatio );
4362 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4364 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4365 const Vector3 naturalSize = GetNaturalSize();
4366 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4368 const float sizeRatio = size.width / size.height;
4369 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4371 if( naturalSizeRatio < sizeRatio )
4373 return Vector2( size.width, size.width / naturalSizeRatio );
4375 else if( naturalSizeRatio > sizeRatio )
4377 return Vector2( naturalSizeRatio * size.height, size.height );
4395 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4397 // Do the set actor size
4398 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4400 // Adjust for size set policy
4401 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4403 // Lock the flag to stop recursive relayouts on set size
4404 mRelayoutData->insideRelayout = true;
4405 SetSize( negotiatedSize );
4406 mRelayoutData->insideRelayout = false;
4408 // Clear flags for all dimensions
4409 SetLayoutDirty( false );
4411 // Give deriving classes a chance to respond
4412 OnRelayout( negotiatedSize, container );
4414 if( !mOnRelayoutSignal.Empty() )
4416 Dali::Actor handle( this );
4417 mOnRelayoutSignal.Emit( handle );
4421 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4423 // Do the negotiation
4424 NegotiateDimensions( allocatedSize );
4426 // Set the actor size
4427 SetNegotiatedSize( container );
4429 // Negotiate down to children
4430 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4432 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4434 Dali::Actor child = GetChildAt( i );
4436 // Only relayout if required
4437 if( GetImplementation( child ).RelayoutRequired() )
4439 container.Add( child, newBounds );
4444 void Actor::RelayoutRequest( Dimension::Type dimension )
4446 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4447 if( relayoutController )
4449 Dali::Actor self( this );
4450 relayoutController->RequestRelayout( self, dimension );
4454 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4458 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4462 void Actor::SetPreferredSize( const Vector2& size )
4464 EnsureRelayoutData();
4466 if( size.width > 0.0f )
4468 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4471 if( size.height > 0.0f )
4473 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4476 mRelayoutData->preferredSize = size;
4481 Vector2 Actor::GetPreferredSize() const
4483 EnsureRelayoutData();
4485 return mRelayoutData->preferredSize;
4488 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4490 EnsureRelayoutData();
4492 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4494 if( dimension & ( 1 << i ) )
4496 mRelayoutData->minimumSize[ i ] = size;
4503 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4505 EnsureRelayoutData();
4507 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4509 if( dimension & ( 1 << i ) )
4511 return mRelayoutData->minimumSize[ i ];
4515 return 0.0f; // Default
4518 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4520 EnsureRelayoutData();
4522 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4524 if( dimension & ( 1 << i ) )
4526 mRelayoutData->maximumSize[ i ] = size;
4533 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4535 EnsureRelayoutData();
4537 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4539 if( dimension & ( 1 << i ) )
4541 return mRelayoutData->maximumSize[ i ];
4545 return 0.0f; // Default
4548 } // namespace Internal