2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 #ifdef DALI_DYNAMICS_SUPPORT
57 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
58 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
63 using Dali::Internal::SceneGraph::Node;
64 using Dali::Internal::SceneGraph::AnimatableProperty;
65 using Dali::Internal::SceneGraph::PropertyBase;
69 namespace ResizePolicy
74 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
75 DALI_ENUM_TO_STRING( FIXED )
76 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
77 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
80 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
81 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
82 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
83 DALI_ENUM_TO_STRING_TABLE_END( Type )
85 } // unnamed namespace
88 namespace SizeScalePolicy
92 // Enumeration to / from string conversion tables
93 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
94 DALI_ENUM_TO_STRING( USE_SIZE_SET )
95 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
97 DALI_ENUM_TO_STRING_TABLE_END( Type )
98 } // unnamed namespace
104 unsigned int Actor::mActorCounter = 0;
107 * Struct to collect relayout variables
109 struct Actor::RelayoutData
112 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
114 // Set size negotiation defaults
115 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
117 resizePolicies[ i ] = ResizePolicy::DEFAULT;
118 negotiatedDimensions[ i ] = 0.0f;
119 dimensionNegotiated[ i ] = false;
120 dimensionDirty[ i ] = false;
121 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
122 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
123 minimumSize[ i ] = 0.0f;
124 maximumSize[ i ] = FLT_MAX;
128 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
130 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
132 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
134 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
136 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
137 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
139 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
140 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
142 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
144 Vector2 preferredSize; ///< The preferred size of the actor
146 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
148 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
149 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
152 #ifdef DALI_DYNAMICS_SUPPORT
154 // Encapsulate actor related dynamics data
157 DynamicsData( Actor* slotOwner )
158 : slotDelegate( slotOwner )
162 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
163 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
165 DynamicsBodyPtr body;
166 JointContainer joints;
167 ReferencedJointContainer referencedJoints;
169 SlotDelegate< Actor > slotDelegate;
172 #endif // DALI_DYNAMICS_SUPPORT
174 namespace // unnamed namespace
180 * We want to discourage the use of property strings (minimize string comparisons),
181 * particularly for the default properties.
182 * Name Type writable animatable constraint-input enum for index-checking
184 DALI_PROPERTY_TABLE_BEGIN
185 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
186 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
187 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
188 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
189 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
190 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
191 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
192 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
193 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
194 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
195 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
196 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
197 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
198 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
199 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
200 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
201 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
202 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
203 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
204 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
205 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
206 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
207 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
208 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
209 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
210 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
211 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
212 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
213 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
214 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
215 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
216 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
217 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
218 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
219 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
220 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
221 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
222 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
223 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
224 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
225 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
226 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
227 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
228 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
229 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
230 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
231 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
232 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
233 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
234 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
235 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
236 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
237 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
241 const char* const SIGNAL_TOUCHED = "touched";
242 const char* const SIGNAL_HOVERED = "hovered";
243 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
244 const char* const SIGNAL_ON_STAGE = "on-stage";
245 const char* const SIGNAL_OFF_STAGE = "off-stage";
249 const char* const ACTION_SHOW = "show";
250 const char* const ACTION_HIDE = "hide";
252 BaseHandle CreateActor()
254 return Dali::Actor::New();
257 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
259 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
264 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
265 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
268 * @brief Extract a given dimension from a Vector2
270 * @param[in] values The values to extract from
271 * @param[in] dimension The dimension to extract
272 * @return Return the value for the dimension
274 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
278 case Dimension::WIDTH:
282 case Dimension::HEIGHT:
284 return values.height;
295 * @brief Extract a given dimension from a Vector3
297 * @param[in] values The values to extract from
298 * @param[in] dimension The dimension to extract
299 * @return Return the value for the dimension
301 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
303 return GetDimensionValue( values.GetVectorXY(), dimension );
307 } // unnamed namespace
309 ActorPtr Actor::New()
311 ActorPtr actor( new Actor( BASIC ) );
313 // Second-phase construction
319 const std::string& Actor::GetName() const
324 void Actor::SetName( const std::string& name )
330 // ATTENTION: string for debug purposes is not thread safe.
331 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
335 unsigned int Actor::GetId() const
340 void Actor::Attach( ActorAttachment& attachment )
342 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
346 attachment.Connect();
349 mAttachment = ActorAttachmentPtr( &attachment );
352 ActorAttachmentPtr Actor::GetAttachment()
357 bool Actor::OnStage() const
362 Dali::Layer Actor::GetLayer()
366 // Short-circuit for Layer derived actors
369 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
372 // Find the immediate Layer parent
373 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
375 if( parent->IsLayer() )
377 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
384 void Actor::Add( Actor& child )
386 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
387 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
391 mChildren = new ActorContainer;
394 Actor* const oldParent( child.mParent );
396 // child might already be ours
397 if( this != oldParent )
399 // if we already have parent, unparent us first
402 oldParent->Remove( child ); // This causes OnChildRemove callback
404 // Old parent may need to readjust to missing child
405 if( oldParent->RelayoutDependentOnChildren() )
407 oldParent->RelayoutRequest();
411 // Guard against Add() during previous OnChildRemove callback
414 // Do this first, since user callbacks from within SetParent() may need to remove child
415 mChildren->push_back( Dali::Actor( &child ) );
417 // SetParent asserts that child can be added
418 child.SetParent( this );
420 // Notification for derived classes
423 // Only put in a relayout request if there is a suitable dependency
424 if( RelayoutDependentOnChildren() )
432 void Actor::Insert( unsigned int index, Actor& child )
434 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
435 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
439 mChildren = new ActorContainer;
442 Actor* const oldParent( child.mParent );
444 // since an explicit position has been given, always insert, even if already a child
447 oldParent->Remove( child ); // This causes OnChildRemove callback
449 // Old parent may need to readjust to missing child
450 if( oldParent->RelayoutDependentOnChildren() )
452 oldParent->RelayoutRequest();
456 // Guard against Add() during previous OnChildRemove callback
459 // Do this first, since user callbacks from within SetParent() may need to remove child
460 if( index < GetChildCount() )
462 ActorIter it = mChildren->begin();
463 std::advance( it, index );
464 mChildren->insert( it, Dali::Actor( &child ) );
468 mChildren->push_back( Dali::Actor( &child ) );
470 // SetParent asserts that child can be added
471 child.SetParent( this, index );
473 // Notification for derived classes
476 // Only put in a relayout request if there is a suitable dependency
477 if( RelayoutDependentOnChildren() )
482 if( child.RelayoutDependentOnParent() )
484 child.RelayoutRequest();
489 void Actor::Remove( Actor& child )
491 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
501 // Find the child in mChildren, and unparent it
502 ActorIter end = mChildren->end();
503 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
505 Actor& actor = GetImplementation( *iter );
507 if( &actor == &child )
509 // Keep handle for OnChildRemove notification
510 removed = Dali::Actor( &actor );
512 // Do this first, since user callbacks from within SetParent() may need to add the child
513 mChildren->erase( iter );
515 DALI_ASSERT_DEBUG( actor.GetParent() == this );
516 actor.SetParent( NULL );
524 // Notification for derived classes
525 OnChildRemove( GetImplementation( removed ) );
527 // Only put in a relayout request if there is a suitable dependency
528 if( RelayoutDependentOnChildren() )
535 void Actor::Unparent()
539 // Remove this actor from the parent. The remove will put a relayout request in for
540 // the parent if required
541 mParent->Remove( *this );
542 // mParent is now NULL!
546 unsigned int Actor::GetChildCount() const
548 return ( NULL != mChildren ) ? mChildren->size() : 0;
551 Dali::Actor Actor::GetChildAt( unsigned int index ) const
553 DALI_ASSERT_ALWAYS( index < GetChildCount() );
555 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
558 ActorPtr Actor::FindChildByName( const std::string& actorName )
561 if( actorName == mName )
567 ActorIter end = mChildren->end();
568 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
570 child = GetImplementation( *iter ).FindChildByName( actorName );
581 ActorPtr Actor::FindChildById( const unsigned int id )
590 ActorIter end = mChildren->end();
591 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
593 child = GetImplementation( *iter ).FindChildById( id );
604 void Actor::SetParentOrigin( const Vector3& origin )
608 // mNode is being used in a separate thread; queue a message to set the value & base value
609 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
612 // Cache for event-thread access
615 // not allocated, check if different from default
616 if( ParentOrigin::DEFAULT != origin )
618 mParentOrigin = new Vector3( origin );
623 // check if different from current costs more than just set
624 *mParentOrigin = origin;
628 void Actor::SetParentOriginX( float x )
630 const Vector3& current = GetCurrentParentOrigin();
632 SetParentOrigin( Vector3( x, current.y, current.z ) );
635 void Actor::SetParentOriginY( float y )
637 const Vector3& current = GetCurrentParentOrigin();
639 SetParentOrigin( Vector3( current.x, y, current.z ) );
642 void Actor::SetParentOriginZ( float z )
644 const Vector3& current = GetCurrentParentOrigin();
646 SetParentOrigin( Vector3( current.x, current.y, z ) );
649 const Vector3& Actor::GetCurrentParentOrigin() const
651 // Cached for event-thread access
652 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
655 void Actor::SetAnchorPoint( const Vector3& anchor )
659 // mNode is being used in a separate thread; queue a message to set the value & base value
660 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
663 // Cache for event-thread access
666 // not allocated, check if different from default
667 if( AnchorPoint::DEFAULT != anchor )
669 mAnchorPoint = new Vector3( anchor );
674 // check if different from current costs more than just set
675 *mAnchorPoint = anchor;
679 void Actor::SetAnchorPointX( float x )
681 const Vector3& current = GetCurrentAnchorPoint();
683 SetAnchorPoint( Vector3( x, current.y, current.z ) );
686 void Actor::SetAnchorPointY( float y )
688 const Vector3& current = GetCurrentAnchorPoint();
690 SetAnchorPoint( Vector3( current.x, y, current.z ) );
693 void Actor::SetAnchorPointZ( float z )
695 const Vector3& current = GetCurrentAnchorPoint();
697 SetAnchorPoint( Vector3( current.x, current.y, z ) );
700 const Vector3& Actor::GetCurrentAnchorPoint() const
702 // Cached for event-thread access
703 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
706 void Actor::SetPosition( float x, float y )
708 SetPosition( Vector3( x, y, 0.0f ) );
711 void Actor::SetPosition( float x, float y, float z )
713 SetPosition( Vector3( x, y, z ) );
716 void Actor::SetPosition( const Vector3& position )
718 mTargetPosition = position;
722 // mNode is being used in a separate thread; queue a message to set the value & base value
723 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
727 void Actor::SetX( float x )
729 mTargetPosition.x = x;
733 // mNode is being used in a separate thread; queue a message to set the value & base value
734 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
738 void Actor::SetY( float y )
740 mTargetPosition.y = y;
744 // mNode is being used in a separate thread; queue a message to set the value & base value
745 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
749 void Actor::SetZ( float z )
751 mTargetPosition.z = z;
755 // mNode is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
760 void Actor::TranslateBy( const Vector3& distance )
762 mTargetPosition += distance;
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
771 const Vector3& Actor::GetCurrentPosition() const
775 // mNode is being used in a separate thread; copy the value from the previous update
776 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
779 return Vector3::ZERO;
782 const Vector3& Actor::GetTargetPosition() const
784 return mTargetPosition;
787 const Vector3& Actor::GetCurrentWorldPosition() const
791 // mNode is being used in a separate thread; copy the value from the previous update
792 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
795 return Vector3::ZERO;
798 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
800 // this flag is not animatable so keep the value
801 mPositionInheritanceMode = mode;
804 // mNode is being used in a separate thread; queue a message to set the value
805 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
809 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
811 // Cached for event-thread access
812 return mPositionInheritanceMode;
815 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
817 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
818 normalizedAxis.Normalize();
820 Quaternion orientation( angle, normalizedAxis );
822 SetOrientation( orientation );
825 void Actor::SetOrientation( const Quaternion& orientation )
829 // mNode is being used in a separate thread; queue a message to set the value & base value
830 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
834 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
838 // mNode is being used in a separate thread; queue a message to set the value & base value
839 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
843 void Actor::RotateBy( const Quaternion& relativeRotation )
847 // mNode is being used in a separate thread; queue a message to set the value & base value
848 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
852 const Quaternion& Actor::GetCurrentOrientation() const
856 // mNode is being used in a separate thread; copy the value from the previous update
857 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
860 return Quaternion::IDENTITY;
863 const Quaternion& Actor::GetCurrentWorldOrientation() const
867 // mNode is being used in a separate thread; copy the value from the previous update
868 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
871 return Quaternion::IDENTITY;
874 void Actor::SetScale( float scale )
876 SetScale( Vector3( scale, scale, scale ) );
879 void Actor::SetScale( float x, float y, float z )
881 SetScale( Vector3( x, y, z ) );
884 void Actor::SetScale( const Vector3& scale )
888 // mNode is being used in a separate thread; queue a message to set the value & base value
889 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
893 void Actor::SetScaleX( float x )
897 // mNode is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
902 void Actor::SetScaleY( float y )
906 // mNode is being used in a separate thread; queue a message to set the value & base value
907 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
911 void Actor::SetScaleZ( float z )
915 // mNode is being used in a separate thread; queue a message to set the value & base value
916 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
920 void Actor::SetInitialVolume( const Vector3& volume )
924 // mNode is being used in a separate thread; queue a message to set the value
925 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
929 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
933 // mNode is being used in a separate thread; queue a message to set the value
934 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
938 bool Actor::GetTransmitGeometryScaling() const
942 // mNode is being used in a separate thread; copy the value from the previous update
943 return mNode->GetTransmitGeometryScaling();
949 void Actor::ScaleBy( const Vector3& relativeScale )
953 // mNode is being used in a separate thread; queue a message to set the value & base value
954 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
958 const Vector3& Actor::GetCurrentScale() const
962 // mNode is being used in a separate thread; copy the value from the previous update
963 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
969 const Vector3& Actor::GetCurrentWorldScale() const
973 // mNode is being used in a separate thread; copy the value from the previous update
974 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
980 void Actor::SetInheritScale( bool inherit )
982 // non animateable so keep local copy
983 mInheritScale = inherit;
986 // mNode is being used in a separate thread; queue a message to set the value
987 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
991 bool Actor::IsScaleInherited() const
993 return mInheritScale;
996 Matrix Actor::GetCurrentWorldMatrix() const
1000 // World matrix is no longer updated unless there is something observing the node.
1001 // Need to calculate it from node's world position, orientation and scale:
1002 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1003 Matrix worldMatrix(false);
1004 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1005 mNode->GetWorldOrientation( updateBufferIndex ),
1006 mNode->GetWorldPosition( updateBufferIndex ) );
1010 return Matrix::IDENTITY;
1013 void Actor::SetVisible( bool visible )
1017 // mNode is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1022 bool Actor::IsVisible() const
1026 // mNode is being used in a separate thread; copy the value from the previous update
1027 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1033 void Actor::SetOpacity( float opacity )
1037 // mNode is being used in a separate thread; queue a message to set the value & base value
1038 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1042 float Actor::GetCurrentOpacity() const
1046 // mNode is being used in a separate thread; copy the value from the previous update
1047 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1053 const Vector4& Actor::GetCurrentWorldColor() const
1057 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1060 return Color::WHITE;
1063 void Actor::SetColor( const Vector4& color )
1067 // mNode is being used in a separate thread; queue a message to set the value & base value
1068 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1072 void Actor::SetColorRed( float red )
1076 // mNode is being used in a separate thread; queue a message to set the value & base value
1077 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1081 void Actor::SetColorGreen( float green )
1085 // mNode is being used in a separate thread; queue a message to set the value & base value
1086 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1090 void Actor::SetColorBlue( float blue )
1094 // mNode is being used in a separate thread; queue a message to set the value & base value
1095 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1099 const Vector4& Actor::GetCurrentColor() const
1103 // mNode is being used in a separate thread; copy the value from the previous update
1104 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1107 return Color::WHITE;
1110 void Actor::SetInheritOrientation( bool inherit )
1112 // non animateable so keep local copy
1113 mInheritOrientation = inherit;
1116 // mNode is being used in a separate thread; queue a message to set the value
1117 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1121 bool Actor::IsOrientationInherited() const
1123 return mInheritOrientation;
1126 void Actor::SetSizeModeFactor( const Vector3& factor )
1128 EnsureRelayoutData();
1130 mRelayoutData->sizeModeFactor = factor;
1133 const Vector3& Actor::GetSizeModeFactor() const
1135 EnsureRelayoutData();
1137 return mRelayoutData->sizeModeFactor;
1140 void Actor::SetColorMode( ColorMode colorMode )
1142 // non animateable so keep local copy
1143 mColorMode = colorMode;
1146 // mNode is being used in a separate thread; queue a message to set the value
1147 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1151 ColorMode Actor::GetColorMode() const
1153 // we have cached copy
1157 void Actor::SetSize( float width, float height )
1159 SetSize( Vector2( width, height ) );
1162 void Actor::SetSize( float width, float height, float depth )
1164 SetSize( Vector3( width, height, depth ) );
1167 void Actor::SetSize( const Vector2& size )
1169 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1172 void Actor::SetSizeInternal( const Vector2& size )
1174 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1177 float Actor::CalculateSizeZ( const Vector2& size ) const
1179 return std::min( size.width, size.height );
1182 void Actor::SetSize( const Vector3& size )
1184 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1186 SetPreferredSize( size.GetVectorXY() );
1190 SetSizeInternal( size );
1194 void Actor::SetSizeInternal( const Vector3& size )
1196 // dont allow recursive loop
1197 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1198 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1199 if( ( NULL != mNode )&&
1200 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1201 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1202 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1206 // mNode is being used in a separate thread; queue a message to set the value & base value
1207 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1209 // Notification for derived classes
1210 mInsideOnSizeSet = true;
1211 OnSizeSet( mTargetSize );
1212 mInsideOnSizeSet = false;
1214 // Raise a relayout request if the flag is not locked
1215 if( mRelayoutData && !mRelayoutData->insideRelayout )
1222 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1224 mTargetSize = targetSize;
1226 // Notify deriving classes
1227 OnSizeAnimation( animation, mTargetSize );
1230 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1232 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1234 mTargetSize.width = targetSize;
1236 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1238 mTargetSize.height = targetSize;
1240 // Notify deriving classes
1241 OnSizeAnimation( animation, mTargetSize );
1244 void Actor::SetWidth( float width )
1248 // mNode is being used in a separate thread; queue a message to set the value & base value
1249 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1253 void Actor::SetHeight( float height )
1257 // mNode is being used in a separate thread; queue a message to set the value & base value
1258 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1262 void Actor::SetDepth( float depth )
1266 // mNode is being used in a separate thread; queue a message to set the value & base value
1267 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1271 const Vector3& Actor::GetTargetSize() const
1276 const Vector3& Actor::GetCurrentSize() const
1280 // mNode is being used in a separate thread; copy the value from the previous update
1281 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1284 return Vector3::ZERO;
1287 Vector3 Actor::GetNaturalSize() const
1289 // It is up to deriving classes to return the appropriate natural size
1290 return Vector3( 0.0f, 0.0f, 0.0f );
1293 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1295 EnsureRelayoutData();
1297 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1299 if( dimension & ( 1 << i ) )
1301 mRelayoutData->resizePolicies[ i ] = policy;
1305 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1307 if( dimension & Dimension::WIDTH )
1309 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1312 if( dimension & Dimension::HEIGHT )
1314 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1318 // If calling SetResizePolicy, assume we want relayout enabled
1319 SetRelayoutEnabled( true );
1321 OnSetResizePolicy( policy, dimension );
1323 // Trigger relayout on this control
1327 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1329 EnsureRelayoutData();
1331 // If more than one dimension is requested, just return the first one found
1332 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1334 if( ( dimension & ( 1 << i ) ) )
1336 return mRelayoutData->resizePolicies[ i ];
1340 return ResizePolicy::DEFAULT;
1343 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1345 EnsureRelayoutData();
1347 mRelayoutData->sizeSetPolicy = policy;
1350 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1352 EnsureRelayoutData();
1354 return mRelayoutData->sizeSetPolicy;
1357 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1359 EnsureRelayoutData();
1361 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1363 if( dimension & ( 1 << i ) )
1365 mRelayoutData->dimensionDependencies[ i ] = dependency;
1370 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1372 EnsureRelayoutData();
1374 // If more than one dimension is requested, just return the first one found
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( ( dimension & ( 1 << i ) ) )
1379 return mRelayoutData->dimensionDependencies[ i ];
1383 return Dimension::ALL_DIMENSIONS; // Default
1386 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1388 // If relayout data has not been allocated yet and the client is requesting
1389 // to disable it, do nothing
1390 if( mRelayoutData || relayoutEnabled )
1392 EnsureRelayoutData();
1394 mRelayoutData->relayoutEnabled = relayoutEnabled;
1398 bool Actor::IsRelayoutEnabled() const
1400 // Assume that if relayout data has not been allocated yet then
1401 // relayout is disabled
1402 return mRelayoutData && mRelayoutData->relayoutEnabled;
1405 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1407 EnsureRelayoutData();
1409 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1411 if( dimension & ( 1 << i ) )
1413 mRelayoutData->dimensionDirty[ i ] = dirty;
1418 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1420 EnsureRelayoutData();
1422 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1424 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1433 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1435 EnsureRelayoutData();
1437 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1440 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1442 EnsureRelayoutData();
1444 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1447 #ifdef DALI_DYNAMICS_SUPPORT
1449 //--------------- Dynamics ---------------
1451 void Actor::DisableDynamics()
1453 if( NULL != mDynamicsData )
1455 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1457 // ensure dynamics object are disconnected from scene
1458 DisconnectDynamics();
1460 // delete joint owned by this actor
1461 while( !mDynamicsData->joints.empty() )
1463 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1466 // delete other joints referencing this actor
1467 while( !mDynamicsData->referencedJoints.empty() )
1469 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1470 ActorPtr jointOwner( joint->GetActor( true ) );
1473 jointOwner->RemoveDynamicsJoint( joint );
1477 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1480 // delete the DynamicsBody object
1481 mDynamicsData->body.Reset();
1483 // Discard Dynamics data structure
1484 delete mDynamicsData;
1485 mDynamicsData = NULL;
1489 DynamicsBodyPtr Actor::GetDynamicsBody() const
1491 DynamicsBodyPtr body;
1493 if( NULL != mDynamicsData )
1495 body = mDynamicsData->body;
1501 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1503 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1505 if( NULL == mDynamicsData )
1507 mDynamicsData = new DynamicsData( this );
1510 if( !mDynamicsData->body )
1512 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1516 DynamicsWorldPtr world( DynamicsWorld::Get() );
1519 if( mParent == world->GetRootActor().Get() )
1521 mDynamicsData->body->Connect( GetEventThreadServices() );
1527 return mDynamicsData->body;
1530 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1532 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1533 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1536 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1538 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1539 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1541 DynamicsJointPtr joint;
1543 DynamicsWorldPtr world( DynamicsWorld::Get() );
1547 if( NULL != mDynamicsData )
1549 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1551 if( mDynamicsData->joints.end() != it )
1553 // use existing joint
1559 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1560 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1564 bodyA = EnableDynamics( new DynamicsBodyConfig );
1569 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1572 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1573 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1575 if( OnStage() && attachedActor->OnStage() )
1577 joint->Connect( GetEventThreadServices() );
1580 attachedActor->ReferenceJoint( joint );
1582 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1583 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1590 const int Actor::GetNumberOfJoints() const
1592 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1595 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1597 DynamicsJointPtr joint;
1599 if( NULL != mDynamicsData )
1601 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1603 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1605 for( int i = 0; i < index; ++i )
1617 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1619 DynamicsJointPtr joint;
1621 if( NULL != mDynamicsData )
1623 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1625 if( mDynamicsData->joints.end() != it )
1627 // use existing joint
1635 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1637 if( NULL != mDynamicsData )
1639 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1640 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1642 for(; it != endIt; ++it )
1644 if( it->second == joint.Get() )
1646 ActorPtr attachedActor( it->first );
1648 if( OnStage() && attachedActor && attachedActor->OnStage() )
1650 joint->Disconnect( GetEventThreadServices() );
1655 attachedActor->ReleaseJoint( joint );
1656 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1657 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1660 mDynamicsData->joints.erase(it);
1667 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1669 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1671 if( NULL != mDynamicsData )
1673 mDynamicsData->referencedJoints.push_back(joint);
1677 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1679 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1681 if( NULL != mDynamicsData )
1683 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1685 if( it != mDynamicsData->referencedJoints.end() )
1687 mDynamicsData->referencedJoints.erase( it );
1692 void Actor::SetDynamicsRoot(bool flag)
1694 if( mIsDynamicsRoot != flag )
1696 mIsDynamicsRoot = flag;
1698 if( OnStage() && mChildren )
1700 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1701 ActorIter end = mChildren->end();
1702 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1704 Actor& child = GetImplementation(*iter);
1706 if( child.GetDynamicsBody() )
1708 if( mIsDynamicsRoot )
1710 child.ConnectDynamics();
1714 child.DisconnectDynamics();
1722 bool Actor::IsDynamicsRoot() const
1724 return mIsDynamicsRoot;
1727 void Actor::AttachedActorOnStage( Dali::Actor actor )
1729 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1733 ActorPtr attachedActor( &GetImplementation(actor) );
1735 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1736 if( NULL != mDynamicsData )
1738 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1739 if( mDynamicsData->joints.end() != it )
1741 DynamicsJointPtr joint( it->second );
1742 joint->Connect( GetEventThreadServices() );
1748 void Actor::AttachedActorOffStage( Dali::Actor actor )
1750 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1754 ActorPtr attachedActor( &GetImplementation(actor) );
1756 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1757 if( NULL != mDynamicsData )
1759 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1760 if( mDynamicsData->joints.end() != it )
1762 DynamicsJointPtr joint( it->second );
1763 joint->Disconnect( GetEventThreadServices() );
1769 void Actor::ConnectDynamics()
1771 if( NULL != mDynamicsData && mDynamicsData->body )
1773 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1775 mDynamicsData->body->Connect( GetEventThreadServices() );
1777 // Connect all joints where attachedActor is also on stage
1778 if( !mDynamicsData->joints.empty() )
1780 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1781 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1783 for(; it != endIt; ++it )
1785 Actor* attachedActor( it->first );
1786 if( NULL != attachedActor && attachedActor->OnStage() )
1788 DynamicsJointPtr joint( it->second );
1790 joint->Connect( GetEventThreadServices() );
1798 void Actor::DisconnectDynamics()
1800 if( NULL != mDynamicsData && mDynamicsData->body )
1804 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1806 // Disconnect all joints
1807 if( !mDynamicsData->joints.empty() )
1809 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1810 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1812 for(; it != endIt; ++it )
1814 DynamicsJointPtr joint( it->second );
1816 joint->Disconnect( GetEventThreadServices() );
1823 #endif // DALI_DYNAMICS_SUPPORT
1825 void Actor::SetOverlay( bool enable )
1827 // Setting STENCIL will override OVERLAY
1828 if( DrawMode::STENCIL != mDrawMode )
1830 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1834 bool Actor::IsOverlay() const
1836 return ( DrawMode::OVERLAY == mDrawMode );
1839 void Actor::SetDrawMode( DrawMode::Type drawMode )
1841 // this flag is not animatable so keep the value
1842 mDrawMode = drawMode;
1845 // mNode is being used in a separate thread; queue a message to set the value
1846 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1850 DrawMode::Type Actor::GetDrawMode() const
1855 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1857 // only valid when on-stage
1858 StagePtr stage = Stage::GetCurrent();
1859 if( stage && OnStage() )
1861 const RenderTaskList& taskList = stage->GetRenderTaskList();
1863 Vector2 converted( screenX, screenY );
1865 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1866 const int taskCount = taskList.GetTaskCount();
1867 for( int i = taskCount - 1; i >= 0; --i )
1869 Dali::RenderTask task = taskList.GetTask( i );
1870 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1872 // found a task where this conversion was ok so return
1880 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1882 bool retval = false;
1883 // only valid when on-stage
1886 CameraActor* camera = renderTask.GetCameraActor();
1890 renderTask.GetViewport( viewport );
1892 // need to translate coordinates to render tasks coordinate space
1893 Vector2 converted( screenX, screenY );
1894 if( renderTask.TranslateCoordinates( converted ) )
1896 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1903 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1905 // Early-out if mNode is NULL
1911 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1913 // Calculate the ModelView matrix
1914 Matrix modelView( false/*don't init*/);
1915 // need to use the components as world matrix is only updated for actors that need it
1916 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1917 Matrix::Multiply( modelView, modelView, viewMatrix );
1919 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1920 Matrix invertedMvp( false/*don't init*/);
1921 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1922 bool success = invertedMvp.Invert();
1924 // Convert to GL coordinates
1925 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1930 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1937 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1943 if( XyPlaneIntersect( nearPos, farPos, local ) )
1945 Vector3 size = GetCurrentSize();
1946 localX = local.x + size.x * 0.5f;
1947 localY = local.y + size.y * 0.5f;
1958 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1961 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1963 Mathematical Formulation
1965 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1967 ( p - c ) dot ( p - c ) = r^2
1969 Given a ray with a point of origin 'o', and a direction vector 'd':
1971 ray(t) = o + td, t >= 0
1973 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1975 (o + td - c ) dot ( o + td - c ) = r^2
1977 To solve for t we first expand the above into a more recognisable quadratic equation form
1979 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1988 B = 2( o - c ) dot d
1989 C = ( o - c ) dot ( o - c ) - r^2
1991 which can be solved using a standard quadratic formula.
1993 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1995 Practical Simplification
1997 In a renderer, we often differentiate between world space and object space. In the object space
1998 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1999 into object space, the mathematical solution presented above can be simplified significantly.
2001 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2005 and we can find the t at which the (transformed) ray intersects the sphere by
2007 ( o + td ) dot ( o + td ) = r^2
2009 According to the reasoning above, we expand the above quadratic equation into the general form
2013 which now has coefficients:
2020 // Early out if mNode is NULL
2026 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2028 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2029 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2030 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2032 // Compute the radius is not needed, square radius it's enough.
2033 const Vector3& size( mNode->GetSize( bufferIndex ) );
2035 // Scale the sphere.
2036 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2038 const float width = size.width * scale.width;
2039 const float height = size.height * scale.height;
2041 float squareSphereRadius = 0.5f * ( width * width + height * height );
2043 float a = rayDir.Dot( rayDir ); // a
2044 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2045 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2047 return ( b2 * b2 - a * c ) >= 0.f;
2050 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2057 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2059 // Transforms the ray to the local reference system.
2061 // Calculate the inverse of Model matrix
2062 Matrix invModelMatrix( false/*don't init*/);
2063 // need to use the components as world matrix is only updated for actors that need it
2064 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2066 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2067 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2069 // Test with the actor's XY plane (Normal = 0 0 1 1).
2071 float a = -rayOriginLocal.z;
2072 float b = rayDirLocal.z;
2074 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2076 // Ray travels distance * rayDirLocal to intersect with plane.
2079 const Vector3& size = mNode->GetSize( bufferIndex );
2081 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2082 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2084 // Test with the actor's geometry.
2085 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2092 void Actor::SetLeaveRequired( bool required )
2094 mLeaveRequired = required;
2097 bool Actor::GetLeaveRequired() const
2099 return mLeaveRequired;
2102 void Actor::SetKeyboardFocusable( bool focusable )
2104 mKeyboardFocusable = focusable;
2107 bool Actor::IsKeyboardFocusable() const
2109 return mKeyboardFocusable;
2112 bool Actor::GetTouchRequired() const
2114 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2117 bool Actor::GetHoverRequired() const
2119 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2122 bool Actor::GetWheelEventRequired() const
2124 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2127 bool Actor::IsHittable() const
2129 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2132 ActorGestureData& Actor::GetGestureData()
2134 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2135 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2136 if( NULL == mGestureData )
2138 mGestureData = new ActorGestureData;
2140 return *mGestureData;
2143 bool Actor::IsGestureRequred( Gesture::Type type ) const
2145 return mGestureData && mGestureData->IsGestureRequred( type );
2148 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2150 bool consumed = false;
2152 if( !mTouchedSignal.Empty() )
2154 Dali::Actor handle( this );
2155 consumed = mTouchedSignal.Emit( handle, event );
2160 // Notification for derived classes
2161 consumed = OnTouchEvent( event );
2167 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2169 bool consumed = false;
2171 if( !mHoveredSignal.Empty() )
2173 Dali::Actor handle( this );
2174 consumed = mHoveredSignal.Emit( handle, event );
2179 // Notification for derived classes
2180 consumed = OnHoverEvent( event );
2186 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2188 bool consumed = false;
2190 if( !mWheelEventSignal.Empty() )
2192 Dali::Actor handle( this );
2193 consumed = mWheelEventSignal.Emit( handle, event );
2198 // Notification for derived classes
2199 consumed = OnWheelEvent( event );
2205 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2207 return mTouchedSignal;
2210 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2212 return mHoveredSignal;
2215 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2217 return mWheelEventSignal;
2220 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2222 return mOnStageSignal;
2225 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2227 return mOffStageSignal;
2230 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2232 return mOnRelayoutSignal;
2235 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2237 bool connected( true );
2238 Actor* actor = dynamic_cast< Actor* >( object );
2240 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2242 actor->TouchedSignal().Connect( tracker, functor );
2244 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2246 actor->HoveredSignal().Connect( tracker, functor );
2248 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2250 actor->WheelEventSignal().Connect( tracker, functor );
2252 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2254 actor->OnStageSignal().Connect( tracker, functor );
2256 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2258 actor->OffStageSignal().Connect( tracker, functor );
2262 // signalName does not match any signal
2269 Actor::Actor( DerivedType derivedType )
2273 mParentOrigin( NULL ),
2274 mAnchorPoint( NULL ),
2275 mRelayoutData( NULL ),
2276 #ifdef DALI_DYNAMICS_SUPPORT
2277 mDynamicsData( NULL ),
2279 mGestureData( NULL ),
2281 mTargetSize( 0.0f, 0.0f, 0.0f ),
2283 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2284 mIsRoot( ROOT_LAYER == derivedType ),
2285 mIsRenderable( RENDERABLE == derivedType ),
2286 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2287 mIsOnStage( false ),
2288 mIsDynamicsRoot( false ),
2290 mLeaveRequired( false ),
2291 mKeyboardFocusable( false ),
2292 mDerivedRequiresTouch( false ),
2293 mDerivedRequiresHover( false ),
2294 mDerivedRequiresWheelEvent( false ),
2295 mOnStageSignalled( false ),
2296 mInsideOnSizeSet( false ),
2297 mInheritOrientation( true ),
2298 mInheritScale( true ),
2299 mDrawMode( DrawMode::NORMAL ),
2300 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2301 mColorMode( Node::DEFAULT_COLOR_MODE )
2305 void Actor::Initialize()
2308 SceneGraph::Node* node = CreateNode();
2310 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2311 mNode = node; // Keep raw-pointer to Node
2315 GetEventThreadServices().RegisterObject( this );
2320 // Remove mParent pointers from children even if we're destroying core,
2321 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2324 ActorConstIter endIter = mChildren->end();
2325 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2327 Actor& actor = GetImplementation( *iter );
2328 actor.SetParent( NULL );
2333 // Guard to allow handle destruction after Core has been destroyed
2334 if( EventThreadServices::IsCoreRunning() )
2338 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2339 mNode = NULL; // Node is about to be destroyed
2342 GetEventThreadServices().UnregisterObject( this );
2345 #ifdef DALI_DYNAMICS_SUPPORT
2347 delete mDynamicsData;
2350 // Cleanup optional gesture data
2351 delete mGestureData;
2353 // Cleanup optional parent origin and anchor
2354 delete mParentOrigin;
2355 delete mAnchorPoint;
2357 // Delete optional relayout data
2360 delete mRelayoutData;
2364 void Actor::ConnectToStage( int index )
2366 // This container is used instead of walking the Actor hierachy.
2367 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2368 ActorContainer connectionList;
2370 // This stage is atomic i.e. not interrupted by user callbacks
2371 RecursiveConnectToStage( connectionList, index );
2373 // Notify applications about the newly connected actors.
2374 const ActorIter endIter = connectionList.end();
2375 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2377 Actor& actor = GetImplementation( *iter );
2378 actor.NotifyStageConnection();
2384 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2386 DALI_ASSERT_ALWAYS( !OnStage() );
2390 ConnectToSceneGraph( index );
2392 // Notification for internal derived classes
2393 OnStageConnectionInternal();
2395 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2396 connectionList.push_back( Dali::Actor( this ) );
2398 // Recursively connect children
2401 ActorConstIter endIter = mChildren->end();
2402 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2404 Actor& actor = GetImplementation( *iter );
2405 actor.RecursiveConnectToStage( connectionList );
2411 * This method is called when the Actor is connected to the Stage.
2412 * The parent must have added its Node to the scene-graph.
2413 * The child must connect its Node to the parent's Node.
2414 * This is resursive; the child calls ConnectToStage() for its children.
2416 void Actor::ConnectToSceneGraph( int index )
2418 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2422 // Reparent Node in next Update
2423 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2426 // Notify attachment
2429 mAttachment->Connect();
2432 #ifdef DALI_DYNAMICS_SUPPORT
2434 if( NULL != mDynamicsData )
2440 // Request relayout on all actors that are added to the scenegraph
2443 // Notification for Object::Observers
2447 void Actor::NotifyStageConnection()
2449 // Actors can be removed (in a callback), before the on-stage stage is reported.
2450 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2451 if( OnStage() && !mOnStageSignalled )
2453 // Notification for external (CustomActor) derived classes
2454 OnStageConnectionExternal();
2456 if( !mOnStageSignal.Empty() )
2458 Dali::Actor handle( this );
2459 mOnStageSignal.Emit( handle );
2462 // Guard against Remove during callbacks
2465 mOnStageSignalled = true; // signal required next time Actor is removed
2470 void Actor::DisconnectFromStage()
2472 // This container is used instead of walking the Actor hierachy.
2473 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2474 ActorContainer disconnectionList;
2476 // This stage is atomic i.e. not interrupted by user callbacks
2477 RecursiveDisconnectFromStage( disconnectionList );
2479 // Notify applications about the newly disconnected actors.
2480 const ActorIter endIter = disconnectionList.end();
2481 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2483 Actor& actor = GetImplementation( *iter );
2484 actor.NotifyStageDisconnection();
2488 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2490 DALI_ASSERT_ALWAYS( OnStage() );
2492 // Recursively disconnect children
2495 ActorConstIter endIter = mChildren->end();
2496 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2498 Actor& actor = GetImplementation( *iter );
2499 actor.RecursiveDisconnectFromStage( disconnectionList );
2503 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2504 disconnectionList.push_back( Dali::Actor( this ) );
2506 // Notification for internal derived classes
2507 OnStageDisconnectionInternal();
2509 DisconnectFromSceneGraph();
2515 * This method is called by an actor or its parent, before a node removal message is sent.
2516 * This is recursive; the child calls DisconnectFromStage() for its children.
2518 void Actor::DisconnectFromSceneGraph()
2520 // Notification for Object::Observers
2521 OnSceneObjectRemove();
2523 // Notify attachment
2526 mAttachment->Disconnect();
2529 #ifdef DALI_DYNAMICS_SUPPORT
2531 if( NULL != mDynamicsData )
2533 DisconnectDynamics();
2538 void Actor::NotifyStageDisconnection()
2540 // Actors can be added (in a callback), before the off-stage state is reported.
2541 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2542 // only do this step if there is a stage, i.e. Core is not being shut down
2543 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2545 // Notification for external (CustomeActor) derived classes
2546 OnStageDisconnectionExternal();
2548 if( !mOffStageSignal.Empty() )
2550 Dali::Actor handle( this );
2551 mOffStageSignal.Emit( handle );
2554 // Guard against Add during callbacks
2557 mOnStageSignalled = false; // signal required next time Actor is added
2562 bool Actor::IsNodeConnected() const
2564 bool connected( false );
2569 if( mNode->IsRoot() || mNode->GetParent() )
2578 unsigned int Actor::GetDefaultPropertyCount() const
2580 return DEFAULT_PROPERTY_COUNT;
2583 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2585 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2587 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2589 indices.PushBack( i );
2593 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2595 if( index < DEFAULT_PROPERTY_COUNT )
2597 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2603 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2605 Property::Index index = Property::INVALID_INDEX;
2607 // Look for name in default properties
2608 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2610 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2611 if( 0 == name.compare( property->name ) )
2621 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2623 if( index < DEFAULT_PROPERTY_COUNT )
2625 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2631 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2633 if( index < DEFAULT_PROPERTY_COUNT )
2635 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2641 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2643 if( index < DEFAULT_PROPERTY_COUNT )
2645 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2651 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2653 if( index < DEFAULT_PROPERTY_COUNT )
2655 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2658 // index out of range...return Property::NONE
2659 return Property::NONE;
2662 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2666 case Dali::Actor::Property::PARENT_ORIGIN:
2668 SetParentOrigin( property.Get< Vector3 >() );
2672 case Dali::Actor::Property::PARENT_ORIGIN_X:
2674 SetParentOriginX( property.Get< float >() );
2678 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2680 SetParentOriginY( property.Get< float >() );
2684 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2686 SetParentOriginZ( property.Get< float >() );
2690 case Dali::Actor::Property::ANCHOR_POINT:
2692 SetAnchorPoint( property.Get< Vector3 >() );
2696 case Dali::Actor::Property::ANCHOR_POINT_X:
2698 SetAnchorPointX( property.Get< float >() );
2702 case Dali::Actor::Property::ANCHOR_POINT_Y:
2704 SetAnchorPointY( property.Get< float >() );
2708 case Dali::Actor::Property::ANCHOR_POINT_Z:
2710 SetAnchorPointZ( property.Get< float >() );
2714 case Dali::Actor::Property::SIZE:
2716 SetSize( property.Get< Vector3 >() );
2720 case Dali::Actor::Property::SIZE_WIDTH:
2722 SetWidth( property.Get< float >() );
2726 case Dali::Actor::Property::SIZE_HEIGHT:
2728 SetHeight( property.Get< float >() );
2732 case Dali::Actor::Property::SIZE_DEPTH:
2734 SetDepth( property.Get< float >() );
2738 case Dali::Actor::Property::POSITION:
2740 SetPosition( property.Get< Vector3 >() );
2744 case Dali::Actor::Property::POSITION_X:
2746 SetX( property.Get< float >() );
2750 case Dali::Actor::Property::POSITION_Y:
2752 SetY( property.Get< float >() );
2756 case Dali::Actor::Property::POSITION_Z:
2758 SetZ( property.Get< float >() );
2762 case Dali::Actor::Property::ORIENTATION:
2764 SetOrientation( property.Get< Quaternion >() );
2768 case Dali::Actor::Property::SCALE:
2770 SetScale( property.Get< Vector3 >() );
2774 case Dali::Actor::Property::SCALE_X:
2776 SetScaleX( property.Get< float >() );
2780 case Dali::Actor::Property::SCALE_Y:
2782 SetScaleY( property.Get< float >() );
2786 case Dali::Actor::Property::SCALE_Z:
2788 SetScaleZ( property.Get< float >() );
2792 case Dali::Actor::Property::VISIBLE:
2794 SetVisible( property.Get< bool >() );
2798 case Dali::Actor::Property::COLOR:
2800 SetColor( property.Get< Vector4 >() );
2804 case Dali::Actor::Property::COLOR_RED:
2806 SetColorRed( property.Get< float >() );
2810 case Dali::Actor::Property::COLOR_GREEN:
2812 SetColorGreen( property.Get< float >() );
2816 case Dali::Actor::Property::COLOR_BLUE:
2818 SetColorBlue( property.Get< float >() );
2822 case Dali::Actor::Property::COLOR_ALPHA:
2824 SetOpacity( property.Get< float >() );
2828 case Dali::Actor::Property::NAME:
2830 SetName( property.Get< std::string >() );
2834 case Dali::Actor::Property::SENSITIVE:
2836 SetSensitive( property.Get< bool >() );
2840 case Dali::Actor::Property::LEAVE_REQUIRED:
2842 SetLeaveRequired( property.Get< bool >() );
2846 case Dali::Actor::Property::INHERIT_ORIENTATION:
2848 SetInheritOrientation( property.Get< bool >() );
2852 case Dali::Actor::Property::INHERIT_SCALE:
2854 SetInheritScale( property.Get< bool >() );
2858 case Dali::Actor::Property::COLOR_MODE:
2860 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2864 case Dali::Actor::Property::POSITION_INHERITANCE:
2866 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2870 case Dali::Actor::Property::DRAW_MODE:
2872 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2876 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2878 SetSizeModeFactor( property.Get< Vector3 >() );
2882 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2884 ResizePolicy::Type type;
2885 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2887 SetResizePolicy( type, Dimension::WIDTH );
2892 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2894 ResizePolicy::Type type;
2895 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2897 SetResizePolicy( type, Dimension::HEIGHT );
2902 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2904 SizeScalePolicy::Type type;
2905 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2907 SetSizeScalePolicy( type );
2912 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2914 if( property.Get< bool >() )
2916 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2921 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2923 if( property.Get< bool >() )
2925 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2930 case Dali::Actor::Property::PADDING:
2932 Vector4 padding = property.Get< Vector4 >();
2933 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2934 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2938 case Dali::Actor::Property::MINIMUM_SIZE:
2940 Vector2 size = property.Get< Vector2 >();
2941 SetMinimumSize( size.x, Dimension::WIDTH );
2942 SetMinimumSize( size.y, Dimension::HEIGHT );
2946 case Dali::Actor::Property::MAXIMUM_SIZE:
2948 Vector2 size = property.Get< Vector2 >();
2949 SetMaximumSize( size.x, Dimension::WIDTH );
2950 SetMaximumSize( size.y, Dimension::HEIGHT );
2956 // this can happen in the case of a non-animatable default property so just do nothing
2962 // TODO: This method needs to be removed
2963 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2965 switch( entry.type )
2967 case Property::BOOLEAN:
2969 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2970 DALI_ASSERT_DEBUG( NULL != property );
2972 // property is being used in a separate thread; queue a message to set the property
2973 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2978 case Property::INTEGER:
2980 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2981 DALI_ASSERT_DEBUG( NULL != property );
2983 // property is being used in a separate thread; queue a message to set the property
2984 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2989 case Property::UNSIGNED_INTEGER:
2991 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2992 DALI_ASSERT_DEBUG( NULL != property );
2994 // property is being used in a separate thread; queue a message to set the property
2995 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3000 case Property::FLOAT:
3002 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3003 DALI_ASSERT_DEBUG( NULL != property );
3005 // property is being used in a separate thread; queue a message to set the property
3006 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3011 case Property::VECTOR2:
3013 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3014 DALI_ASSERT_DEBUG( NULL != property );
3016 // property is being used in a separate thread; queue a message to set the property
3017 if(entry.componentIndex == 0)
3019 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3021 else if(entry.componentIndex == 1)
3023 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3027 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3033 case Property::VECTOR3:
3035 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3036 DALI_ASSERT_DEBUG( NULL != property );
3038 // property is being used in a separate thread; queue a message to set the property
3039 if(entry.componentIndex == 0)
3041 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3043 else if(entry.componentIndex == 1)
3045 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3047 else if(entry.componentIndex == 2)
3049 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3053 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3059 case Property::VECTOR4:
3061 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3062 DALI_ASSERT_DEBUG( NULL != property );
3064 // property is being used in a separate thread; queue a message to set the property
3065 if(entry.componentIndex == 0)
3067 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3069 else if(entry.componentIndex == 1)
3071 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3073 else if(entry.componentIndex == 2)
3075 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3077 else if(entry.componentIndex == 3)
3079 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3083 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3089 case Property::ROTATION:
3091 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3092 DALI_ASSERT_DEBUG( NULL != property );
3094 // property is being used in a separate thread; queue a message to set the property
3095 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3100 case Property::MATRIX:
3102 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3103 DALI_ASSERT_DEBUG( NULL != property );
3105 // property is being used in a separate thread; queue a message to set the property
3106 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3111 case Property::MATRIX3:
3113 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3114 DALI_ASSERT_DEBUG( NULL != property );
3116 // property is being used in a separate thread; queue a message to set the property
3117 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3124 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3130 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3132 Property::Value value;
3136 case Dali::Actor::Property::PARENT_ORIGIN:
3138 value = GetCurrentParentOrigin();
3142 case Dali::Actor::Property::PARENT_ORIGIN_X:
3144 value = GetCurrentParentOrigin().x;
3148 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3150 value = GetCurrentParentOrigin().y;
3154 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3156 value = GetCurrentParentOrigin().z;
3160 case Dali::Actor::Property::ANCHOR_POINT:
3162 value = GetCurrentAnchorPoint();
3166 case Dali::Actor::Property::ANCHOR_POINT_X:
3168 value = GetCurrentAnchorPoint().x;
3172 case Dali::Actor::Property::ANCHOR_POINT_Y:
3174 value = GetCurrentAnchorPoint().y;
3178 case Dali::Actor::Property::ANCHOR_POINT_Z:
3180 value = GetCurrentAnchorPoint().z;
3184 case Dali::Actor::Property::SIZE:
3186 value = GetCurrentSize();
3190 case Dali::Actor::Property::SIZE_WIDTH:
3192 value = GetCurrentSize().width;
3196 case Dali::Actor::Property::SIZE_HEIGHT:
3198 value = GetCurrentSize().height;
3202 case Dali::Actor::Property::SIZE_DEPTH:
3204 value = GetCurrentSize().depth;
3208 case Dali::Actor::Property::POSITION:
3210 value = GetCurrentPosition();
3214 case Dali::Actor::Property::POSITION_X:
3216 value = GetCurrentPosition().x;
3220 case Dali::Actor::Property::POSITION_Y:
3222 value = GetCurrentPosition().y;
3226 case Dali::Actor::Property::POSITION_Z:
3228 value = GetCurrentPosition().z;
3232 case Dali::Actor::Property::WORLD_POSITION:
3234 value = GetCurrentWorldPosition();
3238 case Dali::Actor::Property::WORLD_POSITION_X:
3240 value = GetCurrentWorldPosition().x;
3244 case Dali::Actor::Property::WORLD_POSITION_Y:
3246 value = GetCurrentWorldPosition().y;
3250 case Dali::Actor::Property::WORLD_POSITION_Z:
3252 value = GetCurrentWorldPosition().z;
3256 case Dali::Actor::Property::ORIENTATION:
3258 value = GetCurrentOrientation();
3262 case Dali::Actor::Property::WORLD_ORIENTATION:
3264 value = GetCurrentWorldOrientation();
3268 case Dali::Actor::Property::SCALE:
3270 value = GetCurrentScale();
3274 case Dali::Actor::Property::SCALE_X:
3276 value = GetCurrentScale().x;
3280 case Dali::Actor::Property::SCALE_Y:
3282 value = GetCurrentScale().y;
3286 case Dali::Actor::Property::SCALE_Z:
3288 value = GetCurrentScale().z;
3292 case Dali::Actor::Property::WORLD_SCALE:
3294 value = GetCurrentWorldScale();
3298 case Dali::Actor::Property::VISIBLE:
3300 value = IsVisible();
3304 case Dali::Actor::Property::COLOR:
3306 value = GetCurrentColor();
3310 case Dali::Actor::Property::COLOR_RED:
3312 value = GetCurrentColor().r;
3316 case Dali::Actor::Property::COLOR_GREEN:
3318 value = GetCurrentColor().g;
3322 case Dali::Actor::Property::COLOR_BLUE:
3324 value = GetCurrentColor().b;
3328 case Dali::Actor::Property::COLOR_ALPHA:
3330 value = GetCurrentColor().a;
3334 case Dali::Actor::Property::WORLD_COLOR:
3336 value = GetCurrentWorldColor();
3340 case Dali::Actor::Property::WORLD_MATRIX:
3342 value = GetCurrentWorldMatrix();
3346 case Dali::Actor::Property::NAME:
3352 case Dali::Actor::Property::SENSITIVE:
3354 value = IsSensitive();
3358 case Dali::Actor::Property::LEAVE_REQUIRED:
3360 value = GetLeaveRequired();
3364 case Dali::Actor::Property::INHERIT_ORIENTATION:
3366 value = IsOrientationInherited();
3370 case Dali::Actor::Property::INHERIT_SCALE:
3372 value = IsScaleInherited();
3376 case Dali::Actor::Property::COLOR_MODE:
3378 value = Scripting::GetColorMode( GetColorMode() );
3382 case Dali::Actor::Property::POSITION_INHERITANCE:
3384 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3388 case Dali::Actor::Property::DRAW_MODE:
3390 value = Scripting::GetDrawMode( GetDrawMode() );
3394 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3396 value = GetSizeModeFactor();
3400 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3402 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3406 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3408 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3412 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3414 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3418 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3420 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3424 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3426 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3430 case Dali::Actor::Property::PADDING:
3432 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3433 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3434 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3438 case Dali::Actor::Property::MINIMUM_SIZE:
3440 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3444 case Dali::Actor::Property::MAXIMUM_SIZE:
3446 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3452 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3460 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3465 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3467 // This method should only return an object connected to the scene-graph
3468 return OnStage() ? mNode : NULL;
3471 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3473 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3475 const PropertyBase* property( NULL );
3477 // This method should only return a property of an object connected to the scene-graph
3483 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3485 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3486 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3488 property = animatable->GetSceneGraphProperty();
3490 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3492 CustomPropertyMetadata* custom = FindCustomProperty( index );
3493 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3495 property = custom->GetSceneGraphProperty();
3497 else if( NULL != mNode )
3501 case Dali::Actor::Property::SIZE:
3502 property = &mNode->mSize;
3505 case Dali::Actor::Property::SIZE_WIDTH:
3506 property = &mNode->mSize;
3509 case Dali::Actor::Property::SIZE_HEIGHT:
3510 property = &mNode->mSize;
3513 case Dali::Actor::Property::SIZE_DEPTH:
3514 property = &mNode->mSize;
3517 case Dali::Actor::Property::POSITION:
3518 property = &mNode->mPosition;
3521 case Dali::Actor::Property::POSITION_X:
3522 property = &mNode->mPosition;
3525 case Dali::Actor::Property::POSITION_Y:
3526 property = &mNode->mPosition;
3529 case Dali::Actor::Property::POSITION_Z:
3530 property = &mNode->mPosition;
3533 case Dali::Actor::Property::ORIENTATION:
3534 property = &mNode->mOrientation;
3537 case Dali::Actor::Property::SCALE:
3538 property = &mNode->mScale;
3541 case Dali::Actor::Property::SCALE_X:
3542 property = &mNode->mScale;
3545 case Dali::Actor::Property::SCALE_Y:
3546 property = &mNode->mScale;
3549 case Dali::Actor::Property::SCALE_Z:
3550 property = &mNode->mScale;
3553 case Dali::Actor::Property::VISIBLE:
3554 property = &mNode->mVisible;
3557 case Dali::Actor::Property::COLOR:
3558 property = &mNode->mColor;
3561 case Dali::Actor::Property::COLOR_RED:
3562 property = &mNode->mColor;
3565 case Dali::Actor::Property::COLOR_GREEN:
3566 property = &mNode->mColor;
3569 case Dali::Actor::Property::COLOR_BLUE:
3570 property = &mNode->mColor;
3573 case Dali::Actor::Property::COLOR_ALPHA:
3574 property = &mNode->mColor;
3585 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3587 const PropertyInputImpl* property( NULL );
3589 // This method should only return a property of an object connected to the scene-graph
3595 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3597 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3598 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3600 property = animatable->GetSceneGraphProperty();
3602 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3604 CustomPropertyMetadata* custom = FindCustomProperty( index );
3605 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3606 property = custom->GetSceneGraphProperty();
3608 else if( NULL != mNode )
3612 case Dali::Actor::Property::PARENT_ORIGIN:
3613 property = &mNode->mParentOrigin;
3616 case Dali::Actor::Property::PARENT_ORIGIN_X:
3617 property = &mNode->mParentOrigin;
3620 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3621 property = &mNode->mParentOrigin;
3624 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3625 property = &mNode->mParentOrigin;
3628 case Dali::Actor::Property::ANCHOR_POINT:
3629 property = &mNode->mAnchorPoint;
3632 case Dali::Actor::Property::ANCHOR_POINT_X:
3633 property = &mNode->mAnchorPoint;
3636 case Dali::Actor::Property::ANCHOR_POINT_Y:
3637 property = &mNode->mAnchorPoint;
3640 case Dali::Actor::Property::ANCHOR_POINT_Z:
3641 property = &mNode->mAnchorPoint;
3644 case Dali::Actor::Property::SIZE:
3645 property = &mNode->mSize;
3648 case Dali::Actor::Property::SIZE_WIDTH:
3649 property = &mNode->mSize;
3652 case Dali::Actor::Property::SIZE_HEIGHT:
3653 property = &mNode->mSize;
3656 case Dali::Actor::Property::SIZE_DEPTH:
3657 property = &mNode->mSize;
3660 case Dali::Actor::Property::POSITION:
3661 property = &mNode->mPosition;
3664 case Dali::Actor::Property::POSITION_X:
3665 property = &mNode->mPosition;
3668 case Dali::Actor::Property::POSITION_Y:
3669 property = &mNode->mPosition;
3672 case Dali::Actor::Property::POSITION_Z:
3673 property = &mNode->mPosition;
3676 case Dali::Actor::Property::WORLD_POSITION:
3677 property = &mNode->mWorldPosition;
3680 case Dali::Actor::Property::WORLD_POSITION_X:
3681 property = &mNode->mWorldPosition;
3684 case Dali::Actor::Property::WORLD_POSITION_Y:
3685 property = &mNode->mWorldPosition;
3688 case Dali::Actor::Property::WORLD_POSITION_Z:
3689 property = &mNode->mWorldPosition;
3692 case Dali::Actor::Property::ORIENTATION:
3693 property = &mNode->mOrientation;
3696 case Dali::Actor::Property::WORLD_ORIENTATION:
3697 property = &mNode->mWorldOrientation;
3700 case Dali::Actor::Property::SCALE:
3701 property = &mNode->mScale;
3704 case Dali::Actor::Property::SCALE_X:
3705 property = &mNode->mScale;
3708 case Dali::Actor::Property::SCALE_Y:
3709 property = &mNode->mScale;
3712 case Dali::Actor::Property::SCALE_Z:
3713 property = &mNode->mScale;
3716 case Dali::Actor::Property::WORLD_SCALE:
3717 property = &mNode->mWorldScale;
3720 case Dali::Actor::Property::VISIBLE:
3721 property = &mNode->mVisible;
3724 case Dali::Actor::Property::COLOR:
3725 property = &mNode->mColor;
3728 case Dali::Actor::Property::COLOR_RED:
3729 property = &mNode->mColor;
3732 case Dali::Actor::Property::COLOR_GREEN:
3733 property = &mNode->mColor;
3736 case Dali::Actor::Property::COLOR_BLUE:
3737 property = &mNode->mColor;
3740 case Dali::Actor::Property::COLOR_ALPHA:
3741 property = &mNode->mColor;
3744 case Dali::Actor::Property::WORLD_COLOR:
3745 property = &mNode->mWorldColor;
3748 case Dali::Actor::Property::WORLD_MATRIX:
3749 property = &mNode->mWorldMatrix;
3760 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3762 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3764 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3766 // check whether the animatable property is registered already, if not then register one.
3767 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3768 if( animatableProperty )
3770 componentIndex = animatableProperty->componentIndex;
3777 case Dali::Actor::Property::PARENT_ORIGIN_X:
3778 case Dali::Actor::Property::ANCHOR_POINT_X:
3779 case Dali::Actor::Property::SIZE_WIDTH:
3780 case Dali::Actor::Property::POSITION_X:
3781 case Dali::Actor::Property::WORLD_POSITION_X:
3782 case Dali::Actor::Property::SCALE_X:
3783 case Dali::Actor::Property::COLOR_RED:
3789 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3790 case Dali::Actor::Property::ANCHOR_POINT_Y:
3791 case Dali::Actor::Property::SIZE_HEIGHT:
3792 case Dali::Actor::Property::POSITION_Y:
3793 case Dali::Actor::Property::WORLD_POSITION_Y:
3794 case Dali::Actor::Property::SCALE_Y:
3795 case Dali::Actor::Property::COLOR_GREEN:
3801 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3802 case Dali::Actor::Property::ANCHOR_POINT_Z:
3803 case Dali::Actor::Property::SIZE_DEPTH:
3804 case Dali::Actor::Property::POSITION_Z:
3805 case Dali::Actor::Property::WORLD_POSITION_Z:
3806 case Dali::Actor::Property::SCALE_Z:
3807 case Dali::Actor::Property::COLOR_BLUE:
3813 case Dali::Actor::Property::COLOR_ALPHA:
3827 return componentIndex;
3830 void Actor::SetParent( Actor* parent, int index )
3834 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3838 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3841 // Instruct each actor to create a corresponding node in the scene graph
3842 ConnectToStage( index );
3845 else // parent being set to NULL
3847 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3851 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3854 DALI_ASSERT_ALWAYS( mNode != NULL );
3858 // Disconnect the Node & its children from the scene-graph.
3859 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3862 // Instruct each actor to discard pointers to the scene-graph
3863 DisconnectFromStage();
3868 SceneGraph::Node* Actor::CreateNode() const
3873 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3876 Actor* actor = dynamic_cast< Actor* >( object );
3880 if( 0 == actionName.compare( ACTION_SHOW ) )
3882 actor->SetVisible( true );
3885 else if( 0 == actionName.compare( ACTION_HIDE ) )
3887 actor->SetVisible( false );
3895 void Actor::EnsureRelayoutData() const
3897 // Assign relayout data.
3898 if( !mRelayoutData )
3900 mRelayoutData = new RelayoutData();
3904 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3906 // Check if actor is dependent on parent
3907 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3909 if( ( dimension & ( 1 << i ) ) )
3911 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3912 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3922 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3924 // Check if actor is dependent on children
3925 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3927 if( ( dimension & ( 1 << i ) ) )
3929 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3930 switch( resizePolicy )
3932 case ResizePolicy::FIT_TO_CHILDREN:
3933 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3949 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3951 return Actor::RelayoutDependentOnChildren( dimension );
3954 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3956 // Check each possible dimension and see if it is dependent on the input one
3957 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3959 if( dimension & ( 1 << i ) )
3961 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3968 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3970 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3972 if( dimension & ( 1 << i ) )
3974 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3979 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3981 // If more than one dimension is requested, just return the first one found
3982 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3984 if( ( dimension & ( 1 << i ) ) )
3986 return mRelayoutData->negotiatedDimensions[ i ];
3990 return 0.0f; // Default
3993 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3995 EnsureRelayoutData();
3997 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3999 if( dimension & ( 1 << i ) )
4001 mRelayoutData->dimensionPadding[ i ] = padding;
4006 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4008 EnsureRelayoutData();
4010 // If more than one dimension is requested, just return the first one found
4011 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4013 if( ( dimension & ( 1 << i ) ) )
4015 return mRelayoutData->dimensionPadding[ i ];
4019 return Vector2( 0.0f, 0.0f ); // Default
4022 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4024 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4026 if( dimension & ( 1 << i ) )
4028 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4033 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4035 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4037 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4046 float Actor::GetHeightForWidthBase( float width )
4048 float height = 0.0f;
4050 const Vector3 naturalSize = GetNaturalSize();
4051 if( naturalSize.width > 0.0f )
4053 height = naturalSize.height * width / naturalSize.width;
4055 else // we treat 0 as 1:1 aspect ratio
4063 float Actor::GetWidthForHeightBase( float height )
4067 const Vector3 naturalSize = GetNaturalSize();
4068 if( naturalSize.height > 0.0f )
4070 width = naturalSize.width * height / naturalSize.height;
4072 else // we treat 0 as 1:1 aspect ratio
4080 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4082 // Fill to parent, taking size mode factor into account
4083 switch( child.GetResizePolicy( dimension ) )
4085 case ResizePolicy::FILL_TO_PARENT:
4087 return GetLatestSize( dimension );
4090 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4092 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4095 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4097 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4102 return GetLatestSize( dimension );
4107 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4109 // Can be overridden in derived class
4110 return CalculateChildSizeBase( child, dimension );
4113 float Actor::GetHeightForWidth( float width )
4115 // Can be overridden in derived class
4116 return GetHeightForWidthBase( width );
4119 float Actor::GetWidthForHeight( float height )
4121 // Can be overridden in derived class
4122 return GetWidthForHeightBase( height );
4125 float Actor::GetLatestSize( Dimension::Type dimension ) const
4127 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4130 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4132 Vector2 padding = GetPadding( dimension );
4134 return GetLatestSize( dimension ) + padding.x + padding.y;
4137 float Actor::NegotiateFromParent( Dimension::Type dimension )
4139 Actor* parent = GetParent();
4142 Vector2 padding( GetPadding( dimension ) );
4143 Vector2 parentPadding( parent->GetPadding( dimension ) );
4144 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4150 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4152 float maxDimensionPoint = 0.0f;
4154 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4156 Dali::Actor child = GetChildAt( i );
4157 Actor& childImpl = GetImplementation( child );
4159 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4161 // Calculate the min and max points that the children range across
4162 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4163 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4164 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4168 return maxDimensionPoint;
4171 float Actor::GetSize( Dimension::Type dimension ) const
4173 return GetDimensionValue( GetTargetSize(), dimension );
4176 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4178 return GetDimensionValue( GetNaturalSize(), dimension );
4181 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4183 switch( GetResizePolicy( dimension ) )
4185 case ResizePolicy::USE_NATURAL_SIZE:
4187 return GetNaturalSize( dimension );
4190 case ResizePolicy::FIXED:
4192 return GetDimensionValue( GetPreferredSize(), dimension );
4195 case ResizePolicy::USE_ASSIGNED_SIZE:
4197 return GetDimensionValue( maximumSize, dimension );
4200 case ResizePolicy::FILL_TO_PARENT:
4201 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4202 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4204 return NegotiateFromParent( dimension );
4207 case ResizePolicy::FIT_TO_CHILDREN:
4209 return NegotiateFromChildren( dimension );
4212 case ResizePolicy::DIMENSION_DEPENDENCY:
4214 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4217 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4219 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4222 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4224 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4236 return 0.0f; // Default
4239 float Actor::ClampDimension( float size, Dimension::Type dimension )
4241 const float minSize = GetMinimumSize( dimension );
4242 const float maxSize = GetMaximumSize( dimension );
4244 return std::max( minSize, std::min( size, maxSize ) );
4247 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4249 // Check if it needs to be negotiated
4250 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4252 // Check that we havn't gotten into an infinite loop
4253 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4254 bool recursionFound = false;
4255 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4257 if( *it == searchActor )
4259 recursionFound = true;
4264 if( !recursionFound )
4266 // Record the path that we have taken
4267 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4269 // Dimension dependency check
4270 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4272 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4274 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4276 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4280 // Parent dependency check
4281 Actor* parent = GetParent();
4282 if( parent && RelayoutDependentOnParent( dimension ) )
4284 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4287 // Children dependency check
4288 if( RelayoutDependentOnChildren( dimension ) )
4290 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4292 Dali::Actor child = GetChildAt( i );
4293 Actor& childImpl = GetImplementation( child );
4295 // Only relayout child first if it is not dependent on this actor
4296 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4298 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4303 // For deriving classes
4304 OnCalculateRelayoutSize( dimension );
4306 // All dependencies checked, calculate the size and set negotiated flag
4307 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4309 SetNegotiatedDimension( newSize, dimension );
4310 SetLayoutNegotiated( true, dimension );
4312 // For deriving classes
4313 OnLayoutNegotiated( newSize, dimension );
4315 // This actor has been successfully processed, pop it off the recursion stack
4316 recursionStack.pop_back();
4320 // TODO: Break infinite loop
4321 SetLayoutNegotiated( true, dimension );
4326 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4328 // Negotiate all dimensions that require it
4329 ActorDimensionStack recursionStack;
4331 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4333 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4336 NegotiateDimension( dimension, allocatedSize, recursionStack );
4340 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4342 switch( mRelayoutData->sizeSetPolicy )
4344 case SizeScalePolicy::USE_SIZE_SET:
4349 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4351 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4352 const Vector3 naturalSize = GetNaturalSize();
4353 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4355 const float sizeRatio = size.width / size.height;
4356 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4358 if( naturalSizeRatio < sizeRatio )
4360 return Vector2( naturalSizeRatio * size.height, size.height );
4362 else if( naturalSizeRatio > sizeRatio )
4364 return Vector2( size.width, size.width / naturalSizeRatio );
4375 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4377 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4378 const Vector3 naturalSize = GetNaturalSize();
4379 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4381 const float sizeRatio = size.width / size.height;
4382 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4384 if( naturalSizeRatio < sizeRatio )
4386 return Vector2( size.width, size.width / naturalSizeRatio );
4388 else if( naturalSizeRatio > sizeRatio )
4390 return Vector2( naturalSizeRatio * size.height, size.height );
4408 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4410 // Do the set actor size
4411 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4413 // Adjust for size set policy
4414 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4416 // Lock the flag to stop recursive relayouts on set size
4417 mRelayoutData->insideRelayout = true;
4418 SetSize( negotiatedSize );
4419 mRelayoutData->insideRelayout = false;
4421 // Clear flags for all dimensions
4422 SetLayoutDirty( false );
4424 // Give deriving classes a chance to respond
4425 OnRelayout( negotiatedSize, container );
4427 if( !mOnRelayoutSignal.Empty() )
4429 Dali::Actor handle( this );
4430 mOnRelayoutSignal.Emit( handle );
4434 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4436 // Do the negotiation
4437 NegotiateDimensions( allocatedSize );
4439 // Set the actor size
4440 SetNegotiatedSize( container );
4442 // Negotiate down to children
4443 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4445 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4447 Dali::Actor child = GetChildAt( i );
4449 // Only relayout if required
4450 if( GetImplementation( child ).RelayoutRequired() )
4452 container.Add( child, newBounds );
4457 void Actor::RelayoutRequest( Dimension::Type dimension )
4459 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4460 if( relayoutController )
4462 Dali::Actor self( this );
4463 relayoutController->RequestRelayout( self, dimension );
4467 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4471 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4475 void Actor::SetPreferredSize( const Vector2& size )
4477 EnsureRelayoutData();
4479 if( size.width > 0.0f )
4481 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4484 if( size.height > 0.0f )
4486 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4489 mRelayoutData->preferredSize = size;
4494 Vector2 Actor::GetPreferredSize() const
4496 EnsureRelayoutData();
4498 return mRelayoutData->preferredSize;
4501 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4503 EnsureRelayoutData();
4505 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4507 if( dimension & ( 1 << i ) )
4509 mRelayoutData->minimumSize[ i ] = size;
4516 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4518 EnsureRelayoutData();
4520 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4522 if( dimension & ( 1 << i ) )
4524 return mRelayoutData->minimumSize[ i ];
4528 return 0.0f; // Default
4531 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4533 EnsureRelayoutData();
4535 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4537 if( dimension & ( 1 << i ) )
4539 mRelayoutData->maximumSize[ i ] = size;
4546 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4548 EnsureRelayoutData();
4550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4552 if( dimension & ( 1 << i ) )
4554 return mRelayoutData->maximumSize[ i ];
4558 return 0.0f; // Default
4561 } // namespace Internal