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/actor-attachments/renderer-attachment-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 #ifdef DALI_DYNAMICS_SUPPORT
58 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
61 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
64 using Dali::Internal::SceneGraph::Node;
65 using Dali::Internal::SceneGraph::AnimatableProperty;
66 using Dali::Internal::SceneGraph::PropertyBase;
70 namespace ResizePolicy
75 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
76 DALI_ENUM_TO_STRING( FIXED )
77 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
78 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
80 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
81 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
82 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
83 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
84 DALI_ENUM_TO_STRING_TABLE_END( Type )
86 } // unnamed namespace
89 namespace SizeScalePolicy
93 // Enumeration to / from string conversion tables
94 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
95 DALI_ENUM_TO_STRING( USE_SIZE_SET )
96 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
97 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
98 DALI_ENUM_TO_STRING_TABLE_END( Type )
99 } // unnamed namespace
105 unsigned int Actor::mActorCounter = 0;
108 * Struct to collect relayout variables
110 struct Actor::RelayoutData
113 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
115 // Set size negotiation defaults
116 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
118 resizePolicies[ i ] = ResizePolicy::DEFAULT;
119 negotiatedDimensions[ i ] = 0.0f;
120 dimensionNegotiated[ i ] = false;
121 dimensionDirty[ i ] = false;
122 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
123 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
124 minimumSize[ i ] = 0.0f;
125 maximumSize[ i ] = FLT_MAX;
129 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
131 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
133 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
135 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
137 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
138 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
140 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
141 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
143 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
145 Vector2 preferredSize; ///< The preferred size of the actor
147 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
149 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
150 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
153 #ifdef DALI_DYNAMICS_SUPPORT
155 // Encapsulate actor related dynamics data
158 DynamicsData( Actor* slotOwner )
159 : slotDelegate( slotOwner )
163 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
164 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
166 DynamicsBodyPtr body;
167 JointContainer joints;
168 ReferencedJointContainer referencedJoints;
170 SlotDelegate< Actor > slotDelegate;
173 #endif // DALI_DYNAMICS_SUPPORT
175 namespace // unnamed namespace
181 * We want to discourage the use of property strings (minimize string comparisons),
182 * particularly for the default properties.
183 * Name Type writable animatable constraint-input enum for index-checking
185 DALI_PROPERTY_TABLE_BEGIN
186 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
187 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
188 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
189 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
190 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
191 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
192 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
193 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
194 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
195 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
196 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
197 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
198 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
199 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
200 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
201 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
202 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
203 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
204 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
205 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
206 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
207 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
208 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
209 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
210 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
211 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
212 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
213 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
214 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
215 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
216 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
217 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
218 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
219 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
220 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
221 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
222 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
223 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
224 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
225 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
226 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
227 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
228 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
229 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
230 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
231 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
232 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
233 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
234 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
235 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
236 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
237 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
238 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
242 const char* const SIGNAL_TOUCHED = "touched";
243 const char* const SIGNAL_HOVERED = "hovered";
244 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
245 const char* const SIGNAL_ON_STAGE = "on-stage";
246 const char* const SIGNAL_OFF_STAGE = "off-stage";
250 const char* const ACTION_SHOW = "show";
251 const char* const ACTION_HIDE = "hide";
253 BaseHandle CreateActor()
255 return Dali::Actor::New();
258 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
260 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
263 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
265 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
266 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
269 * @brief Extract a given dimension from a Vector2
271 * @param[in] values The values to extract from
272 * @param[in] dimension The dimension to extract
273 * @return Return the value for the dimension
275 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
279 case Dimension::WIDTH:
283 case Dimension::HEIGHT:
285 return values.height;
296 * @brief Extract a given dimension from a Vector3
298 * @param[in] values The values to extract from
299 * @param[in] dimension The dimension to extract
300 * @return Return the value for the dimension
302 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
304 return GetDimensionValue( values.GetVectorXY(), dimension );
308 } // unnamed namespace
310 ActorPtr Actor::New()
312 ActorPtr actor( new Actor( BASIC ) );
314 // Second-phase construction
320 const std::string& Actor::GetName() const
325 void Actor::SetName( const std::string& name )
331 // ATTENTION: string for debug purposes is not thread safe.
332 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
336 unsigned int Actor::GetId() const
341 void Actor::Attach( ActorAttachment& attachment )
343 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
347 attachment.Connect();
350 mAttachment = ActorAttachmentPtr( &attachment );
353 ActorAttachmentPtr Actor::GetAttachment()
358 bool Actor::OnStage() const
363 Dali::Layer Actor::GetLayer()
367 // Short-circuit for Layer derived actors
370 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
373 // Find the immediate Layer parent
374 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
376 if( parent->IsLayer() )
378 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
385 void Actor::Add( Actor& child )
387 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
388 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
392 mChildren = new ActorContainer;
395 Actor* const oldParent( child.mParent );
397 // child might already be ours
398 if( this != oldParent )
400 // if we already have parent, unparent us first
403 oldParent->Remove( child ); // This causes OnChildRemove callback
405 // Old parent may need to readjust to missing child
406 if( oldParent->RelayoutDependentOnChildren() )
408 oldParent->RelayoutRequest();
412 // Guard against Add() during previous OnChildRemove callback
415 // Do this first, since user callbacks from within SetParent() may need to remove child
416 mChildren->push_back( Dali::Actor( &child ) );
418 // SetParent asserts that child can be added
419 child.SetParent( this );
421 // Notification for derived classes
424 // Only put in a relayout request if there is a suitable dependency
425 if( RelayoutDependentOnChildren() )
433 void Actor::Insert( unsigned int index, Actor& child )
435 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
436 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
440 mChildren = new ActorContainer;
443 Actor* const oldParent( child.mParent );
445 // since an explicit position has been given, always insert, even if already a child
448 oldParent->Remove( child ); // This causes OnChildRemove callback
450 // Old parent may need to readjust to missing child
451 if( oldParent->RelayoutDependentOnChildren() )
453 oldParent->RelayoutRequest();
457 // Guard against Add() during previous OnChildRemove callback
460 // Do this first, since user callbacks from within SetParent() may need to remove child
461 if( index < GetChildCount() )
463 ActorIter it = mChildren->begin();
464 std::advance( it, index );
465 mChildren->insert( it, Dali::Actor( &child ) );
469 mChildren->push_back( Dali::Actor( &child ) );
471 // SetParent asserts that child can be added
472 child.SetParent( this, index );
474 // Notification for derived classes
477 // Only put in a relayout request if there is a suitable dependency
478 if( RelayoutDependentOnChildren() )
483 if( child.RelayoutDependentOnParent() )
485 child.RelayoutRequest();
490 void Actor::Remove( Actor& child )
492 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
502 // Find the child in mChildren, and unparent it
503 ActorIter end = mChildren->end();
504 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
506 Actor& actor = GetImplementation( *iter );
508 if( &actor == &child )
510 // Keep handle for OnChildRemove notification
511 removed = Dali::Actor( &actor );
513 // Do this first, since user callbacks from within SetParent() may need to add the child
514 mChildren->erase( iter );
516 DALI_ASSERT_DEBUG( actor.GetParent() == this );
517 actor.SetParent( NULL );
525 // Notification for derived classes
526 OnChildRemove( GetImplementation( removed ) );
528 // Only put in a relayout request if there is a suitable dependency
529 if( RelayoutDependentOnChildren() )
536 void Actor::Unparent()
540 // Remove this actor from the parent. The remove will put a relayout request in for
541 // the parent if required
542 mParent->Remove( *this );
543 // mParent is now NULL!
547 unsigned int Actor::GetChildCount() const
549 return ( NULL != mChildren ) ? mChildren->size() : 0;
552 Dali::Actor Actor::GetChildAt( unsigned int index ) const
554 DALI_ASSERT_ALWAYS( index < GetChildCount() );
556 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
559 ActorPtr Actor::FindChildByName( const std::string& actorName )
562 if( actorName == mName )
568 ActorIter end = mChildren->end();
569 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
571 child = GetImplementation( *iter ).FindChildByName( actorName );
582 ActorPtr Actor::FindChildById( const unsigned int id )
591 ActorIter end = mChildren->end();
592 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
594 child = GetImplementation( *iter ).FindChildById( id );
605 void Actor::SetParentOrigin( const Vector3& origin )
609 // mNode is being used in a separate thread; queue a message to set the value & base value
610 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
613 // Cache for event-thread access
616 // not allocated, check if different from default
617 if( ParentOrigin::DEFAULT != origin )
619 mParentOrigin = new Vector3( origin );
624 // check if different from current costs more than just set
625 *mParentOrigin = origin;
629 void Actor::SetParentOriginX( float x )
631 const Vector3& current = GetCurrentParentOrigin();
633 SetParentOrigin( Vector3( x, current.y, current.z ) );
636 void Actor::SetParentOriginY( float y )
638 const Vector3& current = GetCurrentParentOrigin();
640 SetParentOrigin( Vector3( current.x, y, current.z ) );
643 void Actor::SetParentOriginZ( float z )
645 const Vector3& current = GetCurrentParentOrigin();
647 SetParentOrigin( Vector3( current.x, current.y, z ) );
650 const Vector3& Actor::GetCurrentParentOrigin() const
652 // Cached for event-thread access
653 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
656 void Actor::SetAnchorPoint( const Vector3& anchor )
660 // mNode is being used in a separate thread; queue a message to set the value & base value
661 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
664 // Cache for event-thread access
667 // not allocated, check if different from default
668 if( AnchorPoint::DEFAULT != anchor )
670 mAnchorPoint = new Vector3( anchor );
675 // check if different from current costs more than just set
676 *mAnchorPoint = anchor;
680 void Actor::SetAnchorPointX( float x )
682 const Vector3& current = GetCurrentAnchorPoint();
684 SetAnchorPoint( Vector3( x, current.y, current.z ) );
687 void Actor::SetAnchorPointY( float y )
689 const Vector3& current = GetCurrentAnchorPoint();
691 SetAnchorPoint( Vector3( current.x, y, current.z ) );
694 void Actor::SetAnchorPointZ( float z )
696 const Vector3& current = GetCurrentAnchorPoint();
698 SetAnchorPoint( Vector3( current.x, current.y, z ) );
701 const Vector3& Actor::GetCurrentAnchorPoint() const
703 // Cached for event-thread access
704 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
707 void Actor::SetPosition( float x, float y )
709 SetPosition( Vector3( x, y, 0.0f ) );
712 void Actor::SetPosition( float x, float y, float z )
714 SetPosition( Vector3( x, y, z ) );
717 void Actor::SetPosition( const Vector3& position )
719 mTargetPosition = position;
723 // mNode is being used in a separate thread; queue a message to set the value & base value
724 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
728 void Actor::SetX( float x )
730 mTargetPosition.x = x;
734 // mNode is being used in a separate thread; queue a message to set the value & base value
735 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
739 void Actor::SetY( float y )
741 mTargetPosition.y = y;
745 // mNode is being used in a separate thread; queue a message to set the value & base value
746 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
750 void Actor::SetZ( float z )
752 mTargetPosition.z = z;
756 // mNode is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
761 void Actor::TranslateBy( const Vector3& distance )
763 mTargetPosition += distance;
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
772 const Vector3& Actor::GetCurrentPosition() const
776 // mNode is being used in a separate thread; copy the value from the previous update
777 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
780 return Vector3::ZERO;
783 const Vector3& Actor::GetTargetPosition() const
785 return mTargetPosition;
788 const Vector3& Actor::GetCurrentWorldPosition() const
792 // mNode is being used in a separate thread; copy the value from the previous update
793 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
796 return Vector3::ZERO;
799 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
801 // this flag is not animatable so keep the value
802 mPositionInheritanceMode = mode;
805 // mNode is being used in a separate thread; queue a message to set the value
806 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
810 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
812 // Cached for event-thread access
813 return mPositionInheritanceMode;
816 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
818 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
819 normalizedAxis.Normalize();
821 Quaternion orientation( angle, normalizedAxis );
823 SetOrientation( orientation );
826 void Actor::SetOrientation( const Quaternion& orientation )
830 // mNode is being used in a separate thread; queue a message to set the value & base value
831 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
835 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
839 // mNode is being used in a separate thread; queue a message to set the value & base value
840 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
844 void Actor::RotateBy( const Quaternion& relativeRotation )
848 // mNode is being used in a separate thread; queue a message to set the value & base value
849 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
853 const Quaternion& Actor::GetCurrentOrientation() const
857 // mNode is being used in a separate thread; copy the value from the previous update
858 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
861 return Quaternion::IDENTITY;
864 const Quaternion& Actor::GetCurrentWorldOrientation() const
868 // mNode is being used in a separate thread; copy the value from the previous update
869 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
872 return Quaternion::IDENTITY;
875 void Actor::SetScale( float scale )
877 SetScale( Vector3( scale, scale, scale ) );
880 void Actor::SetScale( float x, float y, float z )
882 SetScale( Vector3( x, y, z ) );
885 void Actor::SetScale( const Vector3& scale )
889 // mNode is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
894 void Actor::SetScaleX( float x )
898 // mNode is being used in a separate thread; queue a message to set the value & base value
899 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
903 void Actor::SetScaleY( float y )
907 // mNode is being used in a separate thread; queue a message to set the value & base value
908 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
912 void Actor::SetScaleZ( float z )
916 // mNode is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
921 void Actor::ScaleBy(const Vector3& relativeScale)
925 // mNode is being used in a separate thread; queue a message to set the value & base value
926 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
930 const Vector3& Actor::GetCurrentScale() const
934 // mNode is being used in a separate thread; copy the value from the previous update
935 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
941 const Vector3& Actor::GetCurrentWorldScale() const
945 // mNode is being used in a separate thread; copy the value from the previous update
946 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
952 void Actor::SetInheritScale( bool inherit )
954 // non animateable so keep local copy
955 mInheritScale = inherit;
958 // mNode is being used in a separate thread; queue a message to set the value
959 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
963 bool Actor::IsScaleInherited() const
965 return mInheritScale;
968 Matrix Actor::GetCurrentWorldMatrix() const
972 // World matrix is no longer updated unless there is something observing the node.
973 // Need to calculate it from node's world position, orientation and scale:
974 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
975 Matrix worldMatrix(false);
976 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
977 mNode->GetWorldOrientation( updateBufferIndex ),
978 mNode->GetWorldPosition( updateBufferIndex ) );
982 return Matrix::IDENTITY;
985 void Actor::SetVisible( bool visible )
989 // mNode is being used in a separate thread; queue a message to set the value & base value
990 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
994 bool Actor::IsVisible() const
998 // mNode is being used in a separate thread; copy the value from the previous update
999 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1005 void Actor::SetOpacity( float opacity )
1009 // mNode is being used in a separate thread; queue a message to set the value & base value
1010 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1014 float Actor::GetCurrentOpacity() const
1018 // mNode is being used in a separate thread; copy the value from the previous update
1019 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1025 const Vector4& Actor::GetCurrentWorldColor() const
1029 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1032 return Color::WHITE;
1035 void Actor::SetColor( const Vector4& color )
1039 // mNode is being used in a separate thread; queue a message to set the value & base value
1040 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1044 void Actor::SetColorRed( float red )
1048 // mNode is being used in a separate thread; queue a message to set the value & base value
1049 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1053 void Actor::SetColorGreen( float green )
1057 // mNode is being used in a separate thread; queue a message to set the value & base value
1058 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1062 void Actor::SetColorBlue( float blue )
1066 // mNode is being used in a separate thread; queue a message to set the value & base value
1067 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1071 const Vector4& Actor::GetCurrentColor() const
1075 // mNode is being used in a separate thread; copy the value from the previous update
1076 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1079 return Color::WHITE;
1082 void Actor::SetInheritOrientation( bool inherit )
1084 // non animateable so keep local copy
1085 mInheritOrientation = inherit;
1088 // mNode is being used in a separate thread; queue a message to set the value
1089 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1093 bool Actor::IsOrientationInherited() const
1095 return mInheritOrientation;
1098 void Actor::SetSizeModeFactor( const Vector3& factor )
1100 EnsureRelayoutData();
1102 mRelayoutData->sizeModeFactor = factor;
1105 const Vector3& Actor::GetSizeModeFactor() const
1107 EnsureRelayoutData();
1109 return mRelayoutData->sizeModeFactor;
1112 void Actor::SetColorMode( ColorMode colorMode )
1114 // non animateable so keep local copy
1115 mColorMode = colorMode;
1118 // mNode is being used in a separate thread; queue a message to set the value
1119 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1123 ColorMode Actor::GetColorMode() const
1125 // we have cached copy
1129 void Actor::SetSize( float width, float height )
1131 SetSize( Vector2( width, height ) );
1134 void Actor::SetSize( float width, float height, float depth )
1136 SetSize( Vector3( width, height, depth ) );
1139 void Actor::SetSize( const Vector2& size )
1141 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1144 void Actor::SetSizeInternal( const Vector2& size )
1146 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1149 float Actor::CalculateSizeZ( const Vector2& size ) const
1151 return std::min( size.width, size.height );
1154 void Actor::SetSize( const Vector3& size )
1156 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1158 SetPreferredSize( size.GetVectorXY() );
1162 SetSizeInternal( size );
1166 void Actor::SetSizeInternal( const Vector3& size )
1168 // dont allow recursive loop
1169 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1170 // 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
1171 if( ( NULL != mNode )&&
1172 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1173 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1174 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1178 // mNode is being used in a separate thread; queue a message to set the value & base value
1179 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1181 // Notification for derived classes
1182 mInsideOnSizeSet = true;
1183 OnSizeSet( mTargetSize );
1184 mInsideOnSizeSet = false;
1186 // Raise a relayout request if the flag is not locked
1187 if( mRelayoutData && !mRelayoutData->insideRelayout )
1194 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1196 mTargetSize = targetSize;
1198 // Notify deriving classes
1199 OnSizeAnimation( animation, mTargetSize );
1202 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1204 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1206 mTargetSize.width = targetSize;
1208 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1210 mTargetSize.height = targetSize;
1212 // Notify deriving classes
1213 OnSizeAnimation( animation, mTargetSize );
1216 void Actor::SetWidth( float width )
1220 // mNode is being used in a separate thread; queue a message to set the value & base value
1221 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1225 void Actor::SetHeight( float height )
1229 // mNode is being used in a separate thread; queue a message to set the value & base value
1230 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1234 void Actor::SetDepth( float depth )
1238 // mNode is being used in a separate thread; queue a message to set the value & base value
1239 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1243 const Vector3& Actor::GetTargetSize() const
1248 const Vector3& Actor::GetCurrentSize() const
1252 // mNode is being used in a separate thread; copy the value from the previous update
1253 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1256 return Vector3::ZERO;
1259 Vector3 Actor::GetNaturalSize() const
1261 // It is up to deriving classes to return the appropriate natural size
1262 return Vector3( 0.0f, 0.0f, 0.0f );
1265 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1267 EnsureRelayoutData();
1269 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1271 if( dimension & ( 1 << i ) )
1273 mRelayoutData->resizePolicies[ i ] = policy;
1277 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1279 if( dimension & Dimension::WIDTH )
1281 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1284 if( dimension & Dimension::HEIGHT )
1286 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1290 // If calling SetResizePolicy, assume we want relayout enabled
1291 SetRelayoutEnabled( true );
1293 OnSetResizePolicy( policy, dimension );
1295 // Trigger relayout on this control
1299 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1301 EnsureRelayoutData();
1303 // If more than one dimension is requested, just return the first one found
1304 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1306 if( ( dimension & ( 1 << i ) ) )
1308 return mRelayoutData->resizePolicies[ i ];
1312 return ResizePolicy::DEFAULT;
1315 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1317 EnsureRelayoutData();
1319 mRelayoutData->sizeSetPolicy = policy;
1322 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1324 EnsureRelayoutData();
1326 return mRelayoutData->sizeSetPolicy;
1329 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1331 EnsureRelayoutData();
1333 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1335 if( dimension & ( 1 << i ) )
1337 mRelayoutData->dimensionDependencies[ i ] = dependency;
1342 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1344 EnsureRelayoutData();
1346 // If more than one dimension is requested, just return the first one found
1347 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1349 if( ( dimension & ( 1 << i ) ) )
1351 return mRelayoutData->dimensionDependencies[ i ];
1355 return Dimension::ALL_DIMENSIONS; // Default
1358 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1360 // If relayout data has not been allocated yet and the client is requesting
1361 // to disable it, do nothing
1362 if( mRelayoutData || relayoutEnabled )
1364 EnsureRelayoutData();
1366 mRelayoutData->relayoutEnabled = relayoutEnabled;
1370 bool Actor::IsRelayoutEnabled() const
1372 // Assume that if relayout data has not been allocated yet then
1373 // relayout is disabled
1374 return mRelayoutData && mRelayoutData->relayoutEnabled;
1377 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1379 EnsureRelayoutData();
1381 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1383 if( dimension & ( 1 << i ) )
1385 mRelayoutData->dimensionDirty[ i ] = dirty;
1390 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1392 EnsureRelayoutData();
1394 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1396 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1405 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1407 EnsureRelayoutData();
1409 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1412 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1414 EnsureRelayoutData();
1416 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1419 unsigned int Actor::AddRenderer( Renderer& renderer )
1421 //TODO: MESH_REWORK : Add support for multiple renderers
1422 if ( ! mAttachment )
1424 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1430 unsigned int Actor::GetRendererCount() const
1432 //TODO: MESH_REWORK : Add support for multiple renderers
1433 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1434 return attachment ? 1u : 0u;
1437 Renderer& Actor::GetRendererAt( unsigned int index )
1439 //TODO: MESH_REWORK : Add support for multiple renderers
1440 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1442 //TODO: MESH_REWORK : Temporary code
1443 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1444 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1446 return attachment->GetRenderer();
1449 void Actor::RemoveRenderer( Renderer& renderer )
1451 //TODO: MESH_REWORK : Add support for multiple renderers
1455 void Actor::RemoveRenderer( unsigned int index )
1457 //TODO: MESH_REWORK : Add support for multiple renderers
1462 #ifdef DALI_DYNAMICS_SUPPORT
1464 //--------------- Dynamics ---------------
1466 void Actor::DisableDynamics()
1468 if( NULL != mDynamicsData )
1470 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1472 // ensure dynamics object are disconnected from scene
1473 DisconnectDynamics();
1475 // delete joint owned by this actor
1476 while( !mDynamicsData->joints.empty() )
1478 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1481 // delete other joints referencing this actor
1482 while( !mDynamicsData->referencedJoints.empty() )
1484 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1485 ActorPtr jointOwner( joint->GetActor( true ) );
1488 jointOwner->RemoveDynamicsJoint( joint );
1492 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1495 // delete the DynamicsBody object
1496 mDynamicsData->body.Reset();
1498 // Discard Dynamics data structure
1499 delete mDynamicsData;
1500 mDynamicsData = NULL;
1504 DynamicsBodyPtr Actor::GetDynamicsBody() const
1506 DynamicsBodyPtr body;
1508 if( NULL != mDynamicsData )
1510 body = mDynamicsData->body;
1516 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1518 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1520 if( NULL == mDynamicsData )
1522 mDynamicsData = new DynamicsData( this );
1525 if( !mDynamicsData->body )
1527 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1531 DynamicsWorldPtr world( DynamicsWorld::Get() );
1534 if( mParent == world->GetRootActor().Get() )
1536 mDynamicsData->body->Connect( GetEventThreadServices() );
1542 return mDynamicsData->body;
1545 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1547 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1548 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1551 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1553 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1554 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1556 DynamicsJointPtr joint;
1558 DynamicsWorldPtr world( DynamicsWorld::Get() );
1562 if( NULL != mDynamicsData )
1564 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1566 if( mDynamicsData->joints.end() != it )
1568 // use existing joint
1574 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1575 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1579 bodyA = EnableDynamics( new DynamicsBodyConfig );
1584 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1587 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1588 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1590 if( OnStage() && attachedActor->OnStage() )
1592 joint->Connect( GetEventThreadServices() );
1595 attachedActor->ReferenceJoint( joint );
1597 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1598 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1605 const int Actor::GetNumberOfJoints() const
1607 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1610 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1612 DynamicsJointPtr joint;
1614 if( NULL != mDynamicsData )
1616 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1618 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1620 for( int i = 0; i < index; ++i )
1632 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1634 DynamicsJointPtr joint;
1636 if( NULL != mDynamicsData )
1638 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1640 if( mDynamicsData->joints.end() != it )
1642 // use existing joint
1650 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1652 if( NULL != mDynamicsData )
1654 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1655 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1657 for(; it != endIt; ++it )
1659 if( it->second == joint.Get() )
1661 ActorPtr attachedActor( it->first );
1663 if( OnStage() && attachedActor && attachedActor->OnStage() )
1665 joint->Disconnect( GetEventThreadServices() );
1670 attachedActor->ReleaseJoint( joint );
1671 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1672 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1675 mDynamicsData->joints.erase(it);
1682 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1684 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1686 if( NULL != mDynamicsData )
1688 mDynamicsData->referencedJoints.push_back(joint);
1692 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1694 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1696 if( NULL != mDynamicsData )
1698 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1700 if( it != mDynamicsData->referencedJoints.end() )
1702 mDynamicsData->referencedJoints.erase( it );
1707 void Actor::SetDynamicsRoot(bool flag)
1709 if( mIsDynamicsRoot != flag )
1711 mIsDynamicsRoot = flag;
1713 if( OnStage() && mChildren )
1715 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1716 ActorIter end = mChildren->end();
1717 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1719 Actor& child = GetImplementation(*iter);
1721 if( child.GetDynamicsBody() )
1723 if( mIsDynamicsRoot )
1725 child.ConnectDynamics();
1729 child.DisconnectDynamics();
1737 bool Actor::IsDynamicsRoot() const
1739 return mIsDynamicsRoot;
1742 void Actor::AttachedActorOnStage( Dali::Actor actor )
1744 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1748 ActorPtr attachedActor( &GetImplementation(actor) );
1750 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1751 if( NULL != mDynamicsData )
1753 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1754 if( mDynamicsData->joints.end() != it )
1756 DynamicsJointPtr joint( it->second );
1757 joint->Connect( GetEventThreadServices() );
1763 void Actor::AttachedActorOffStage( Dali::Actor actor )
1765 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1769 ActorPtr attachedActor( &GetImplementation(actor) );
1771 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1772 if( NULL != mDynamicsData )
1774 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1775 if( mDynamicsData->joints.end() != it )
1777 DynamicsJointPtr joint( it->second );
1778 joint->Disconnect( GetEventThreadServices() );
1784 void Actor::ConnectDynamics()
1786 if( NULL != mDynamicsData && mDynamicsData->body )
1788 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1790 mDynamicsData->body->Connect( GetEventThreadServices() );
1792 // Connect all joints where attachedActor is also on stage
1793 if( !mDynamicsData->joints.empty() )
1795 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1796 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1798 for(; it != endIt; ++it )
1800 Actor* attachedActor( it->first );
1801 if( NULL != attachedActor && attachedActor->OnStage() )
1803 DynamicsJointPtr joint( it->second );
1805 joint->Connect( GetEventThreadServices() );
1813 void Actor::DisconnectDynamics()
1815 if( NULL != mDynamicsData && mDynamicsData->body )
1819 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1821 // Disconnect all joints
1822 if( !mDynamicsData->joints.empty() )
1824 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1825 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1827 for(; it != endIt; ++it )
1829 DynamicsJointPtr joint( it->second );
1831 joint->Disconnect( GetEventThreadServices() );
1838 #endif // DALI_DYNAMICS_SUPPORT
1840 void Actor::SetOverlay( bool enable )
1842 // Setting STENCIL will override OVERLAY
1843 if( DrawMode::STENCIL != mDrawMode )
1845 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1849 bool Actor::IsOverlay() const
1851 return ( DrawMode::OVERLAY == mDrawMode );
1854 void Actor::SetDrawMode( DrawMode::Type drawMode )
1856 // this flag is not animatable so keep the value
1857 mDrawMode = drawMode;
1860 // mNode is being used in a separate thread; queue a message to set the value
1861 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1865 DrawMode::Type Actor::GetDrawMode() const
1870 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1872 // only valid when on-stage
1873 StagePtr stage = Stage::GetCurrent();
1874 if( stage && OnStage() )
1876 const RenderTaskList& taskList = stage->GetRenderTaskList();
1878 Vector2 converted( screenX, screenY );
1880 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1881 const int taskCount = taskList.GetTaskCount();
1882 for( int i = taskCount - 1; i >= 0; --i )
1884 Dali::RenderTask task = taskList.GetTask( i );
1885 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1887 // found a task where this conversion was ok so return
1895 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1897 bool retval = false;
1898 // only valid when on-stage
1901 CameraActor* camera = renderTask.GetCameraActor();
1905 renderTask.GetViewport( viewport );
1907 // need to translate coordinates to render tasks coordinate space
1908 Vector2 converted( screenX, screenY );
1909 if( renderTask.TranslateCoordinates( converted ) )
1911 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1918 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1920 // Early-out if mNode is NULL
1926 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1928 // Calculate the ModelView matrix
1929 Matrix modelView( false/*don't init*/);
1930 // need to use the components as world matrix is only updated for actors that need it
1931 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1932 Matrix::Multiply( modelView, modelView, viewMatrix );
1934 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1935 Matrix invertedMvp( false/*don't init*/);
1936 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1937 bool success = invertedMvp.Invert();
1939 // Convert to GL coordinates
1940 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1945 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1952 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1958 if( XyPlaneIntersect( nearPos, farPos, local ) )
1960 Vector3 size = GetCurrentSize();
1961 localX = local.x + size.x * 0.5f;
1962 localY = local.y + size.y * 0.5f;
1973 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1976 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1978 Mathematical Formulation
1980 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1982 ( p - c ) dot ( p - c ) = r^2
1984 Given a ray with a point of origin 'o', and a direction vector 'd':
1986 ray(t) = o + td, t >= 0
1988 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1990 (o + td - c ) dot ( o + td - c ) = r^2
1992 To solve for t we first expand the above into a more recognisable quadratic equation form
1994 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
2003 B = 2( o - c ) dot d
2004 C = ( o - c ) dot ( o - c ) - r^2
2006 which can be solved using a standard quadratic formula.
2008 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
2010 Practical Simplification
2012 In a renderer, we often differentiate between world space and object space. In the object space
2013 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2014 into object space, the mathematical solution presented above can be simplified significantly.
2016 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2020 and we can find the t at which the (transformed) ray intersects the sphere by
2022 ( o + td ) dot ( o + td ) = r^2
2024 According to the reasoning above, we expand the above quadratic equation into the general form
2028 which now has coefficients:
2035 // Early out if mNode is NULL
2041 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2043 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2044 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2045 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2047 // Compute the radius is not needed, square radius it's enough.
2048 const Vector3& size( mNode->GetSize( bufferIndex ) );
2050 // Scale the sphere.
2051 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2053 const float width = size.width * scale.width;
2054 const float height = size.height * scale.height;
2056 float squareSphereRadius = 0.5f * ( width * width + height * height );
2058 float a = rayDir.Dot( rayDir ); // a
2059 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2060 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2062 return ( b2 * b2 - a * c ) >= 0.f;
2065 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2072 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2074 // Transforms the ray to the local reference system.
2076 // Calculate the inverse of Model matrix
2077 Matrix invModelMatrix( false/*don't init*/);
2078 // need to use the components as world matrix is only updated for actors that need it
2079 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2081 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2082 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2084 // Test with the actor's XY plane (Normal = 0 0 1 1).
2086 float a = -rayOriginLocal.z;
2087 float b = rayDirLocal.z;
2089 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2091 // Ray travels distance * rayDirLocal to intersect with plane.
2094 const Vector3& size = mNode->GetSize( bufferIndex );
2096 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2097 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2099 // Test with the actor's geometry.
2100 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2107 void Actor::SetLeaveRequired( bool required )
2109 mLeaveRequired = required;
2112 bool Actor::GetLeaveRequired() const
2114 return mLeaveRequired;
2117 void Actor::SetKeyboardFocusable( bool focusable )
2119 mKeyboardFocusable = focusable;
2122 bool Actor::IsKeyboardFocusable() const
2124 return mKeyboardFocusable;
2127 bool Actor::GetTouchRequired() const
2129 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2132 bool Actor::GetHoverRequired() const
2134 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2137 bool Actor::GetWheelEventRequired() const
2139 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2142 bool Actor::IsHittable() const
2144 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2147 ActorGestureData& Actor::GetGestureData()
2149 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2150 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2151 if( NULL == mGestureData )
2153 mGestureData = new ActorGestureData;
2155 return *mGestureData;
2158 bool Actor::IsGestureRequred( Gesture::Type type ) const
2160 return mGestureData && mGestureData->IsGestureRequred( type );
2163 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2165 bool consumed = false;
2167 if( !mTouchedSignal.Empty() )
2169 Dali::Actor handle( this );
2170 consumed = mTouchedSignal.Emit( handle, event );
2175 // Notification for derived classes
2176 consumed = OnTouchEvent( event );
2182 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2184 bool consumed = false;
2186 if( !mHoveredSignal.Empty() )
2188 Dali::Actor handle( this );
2189 consumed = mHoveredSignal.Emit( handle, event );
2194 // Notification for derived classes
2195 consumed = OnHoverEvent( event );
2201 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2203 bool consumed = false;
2205 if( !mWheelEventSignal.Empty() )
2207 Dali::Actor handle( this );
2208 consumed = mWheelEventSignal.Emit( handle, event );
2213 // Notification for derived classes
2214 consumed = OnWheelEvent( event );
2220 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2222 return mTouchedSignal;
2225 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2227 return mHoveredSignal;
2230 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2232 return mWheelEventSignal;
2235 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2237 return mOnStageSignal;
2240 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2242 return mOffStageSignal;
2245 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2247 return mOnRelayoutSignal;
2250 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2252 bool connected( true );
2253 Actor* actor = dynamic_cast< Actor* >( object );
2255 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2257 actor->TouchedSignal().Connect( tracker, functor );
2259 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2261 actor->HoveredSignal().Connect( tracker, functor );
2263 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2265 actor->WheelEventSignal().Connect( tracker, functor );
2267 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2269 actor->OnStageSignal().Connect( tracker, functor );
2271 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2273 actor->OffStageSignal().Connect( tracker, functor );
2277 // signalName does not match any signal
2284 Actor::Actor( DerivedType derivedType )
2288 mParentOrigin( NULL ),
2289 mAnchorPoint( NULL ),
2290 mRelayoutData( NULL ),
2291 #ifdef DALI_DYNAMICS_SUPPORT
2292 mDynamicsData( NULL ),
2294 mGestureData( NULL ),
2296 mTargetSize( 0.0f, 0.0f, 0.0f ),
2298 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2300 mIsRoot( ROOT_LAYER == derivedType ),
2301 mIsRenderable( RENDERABLE == derivedType ),
2302 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2303 mIsOnStage( false ),
2304 mIsDynamicsRoot( false ),
2306 mLeaveRequired( false ),
2307 mKeyboardFocusable( false ),
2308 mDerivedRequiresTouch( false ),
2309 mDerivedRequiresHover( false ),
2310 mDerivedRequiresWheelEvent( false ),
2311 mOnStageSignalled( false ),
2312 mInsideOnSizeSet( false ),
2313 mInheritOrientation( true ),
2314 mInheritScale( true ),
2315 mDrawMode( DrawMode::NORMAL ),
2316 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2317 mColorMode( Node::DEFAULT_COLOR_MODE )
2321 void Actor::Initialize()
2324 SceneGraph::Node* node = CreateNode();
2326 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2327 mNode = node; // Keep raw-pointer to Node
2331 GetEventThreadServices().RegisterObject( this );
2336 // Remove mParent pointers from children even if we're destroying core,
2337 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2340 ActorConstIter endIter = mChildren->end();
2341 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2343 Actor& actor = GetImplementation( *iter );
2344 actor.SetParent( NULL );
2349 // Guard to allow handle destruction after Core has been destroyed
2350 if( EventThreadServices::IsCoreRunning() )
2354 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2355 mNode = NULL; // Node is about to be destroyed
2358 GetEventThreadServices().UnregisterObject( this );
2361 #ifdef DALI_DYNAMICS_SUPPORT
2363 delete mDynamicsData;
2366 // Cleanup optional gesture data
2367 delete mGestureData;
2369 // Cleanup optional parent origin and anchor
2370 delete mParentOrigin;
2371 delete mAnchorPoint;
2373 // Delete optional relayout data
2376 delete mRelayoutData;
2380 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2382 // This container is used instead of walking the Actor hierachy.
2383 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2384 ActorContainer connectionList;
2387 // This stage is atomic i.e. not interrupted by user callbacks
2388 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2390 // Notify applications about the newly connected actors.
2391 const ActorIter endIter = connectionList.end();
2392 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2394 Actor& actor = GetImplementation( *iter );
2395 actor.NotifyStageConnection();
2401 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2403 DALI_ASSERT_ALWAYS( !OnStage() );
2408 ConnectToSceneGraph( index );
2410 // Notification for internal derived classes
2411 OnStageConnectionInternal();
2413 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2414 connectionList.push_back( Dali::Actor( this ) );
2416 // Recursively connect children
2419 ActorConstIter endIter = mChildren->end();
2420 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2422 Actor& actor = GetImplementation( *iter );
2423 actor.RecursiveConnectToStage( connectionList, depth+1 );
2429 * This method is called when the Actor is connected to the Stage.
2430 * The parent must have added its Node to the scene-graph.
2431 * The child must connect its Node to the parent's Node.
2432 * This is resursive; the child calls ConnectToStage() for its children.
2434 void Actor::ConnectToSceneGraph( int index )
2436 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2440 // Reparent Node in next Update
2441 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2444 // Notify attachment
2447 mAttachment->Connect();
2450 #ifdef DALI_DYNAMICS_SUPPORT
2452 if( NULL != mDynamicsData )
2458 // Request relayout on all actors that are added to the scenegraph
2461 // Notification for Object::Observers
2465 void Actor::NotifyStageConnection()
2467 // Actors can be removed (in a callback), before the on-stage stage is reported.
2468 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2469 if( OnStage() && !mOnStageSignalled )
2471 // Notification for external (CustomActor) derived classes
2472 OnStageConnectionExternal( mDepth );
2474 if( !mOnStageSignal.Empty() )
2476 Dali::Actor handle( this );
2477 mOnStageSignal.Emit( handle );
2480 // Guard against Remove during callbacks
2483 mOnStageSignalled = true; // signal required next time Actor is removed
2488 void Actor::DisconnectFromStage()
2490 // This container is used instead of walking the Actor hierachy.
2491 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2492 ActorContainer disconnectionList;
2494 // This stage is atomic i.e. not interrupted by user callbacks
2495 RecursiveDisconnectFromStage( disconnectionList );
2497 // Notify applications about the newly disconnected actors.
2498 const ActorIter endIter = disconnectionList.end();
2499 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2501 Actor& actor = GetImplementation( *iter );
2502 actor.NotifyStageDisconnection();
2506 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2508 DALI_ASSERT_ALWAYS( OnStage() );
2510 // Recursively disconnect children
2513 ActorConstIter endIter = mChildren->end();
2514 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2516 Actor& actor = GetImplementation( *iter );
2517 actor.RecursiveDisconnectFromStage( disconnectionList );
2521 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2522 disconnectionList.push_back( Dali::Actor( this ) );
2524 // Notification for internal derived classes
2525 OnStageDisconnectionInternal();
2527 DisconnectFromSceneGraph();
2533 * This method is called by an actor or its parent, before a node removal message is sent.
2534 * This is recursive; the child calls DisconnectFromStage() for its children.
2536 void Actor::DisconnectFromSceneGraph()
2538 // Notification for Object::Observers
2539 OnSceneObjectRemove();
2541 // Notify attachment
2544 mAttachment->Disconnect();
2547 #ifdef DALI_DYNAMICS_SUPPORT
2549 if( NULL != mDynamicsData )
2551 DisconnectDynamics();
2556 void Actor::NotifyStageDisconnection()
2558 // Actors can be added (in a callback), before the off-stage state is reported.
2559 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2560 // only do this step if there is a stage, i.e. Core is not being shut down
2561 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2563 // Notification for external (CustomeActor) derived classes
2564 OnStageDisconnectionExternal();
2566 if( !mOffStageSignal.Empty() )
2568 Dali::Actor handle( this );
2569 mOffStageSignal.Emit( handle );
2572 // Guard against Add during callbacks
2575 mOnStageSignalled = false; // signal required next time Actor is added
2580 bool Actor::IsNodeConnected() const
2582 bool connected( false );
2587 if( mNode->IsRoot() || mNode->GetParent() )
2596 unsigned int Actor::GetDefaultPropertyCount() const
2598 return DEFAULT_PROPERTY_COUNT;
2601 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2603 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2605 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2607 indices.PushBack( i );
2611 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2613 if( index < DEFAULT_PROPERTY_COUNT )
2615 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2621 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2623 Property::Index index = Property::INVALID_INDEX;
2625 // Look for name in default properties
2626 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2628 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2629 if( 0 == name.compare( property->name ) )
2639 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2641 if( index < DEFAULT_PROPERTY_COUNT )
2643 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2649 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2651 if( index < DEFAULT_PROPERTY_COUNT )
2653 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2659 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2661 if( index < DEFAULT_PROPERTY_COUNT )
2663 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2669 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2671 if( index < DEFAULT_PROPERTY_COUNT )
2673 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2676 // index out of range...return Property::NONE
2677 return Property::NONE;
2680 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2684 case Dali::Actor::Property::PARENT_ORIGIN:
2686 SetParentOrigin( property.Get< Vector3 >() );
2690 case Dali::Actor::Property::PARENT_ORIGIN_X:
2692 SetParentOriginX( property.Get< float >() );
2696 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2698 SetParentOriginY( property.Get< float >() );
2702 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2704 SetParentOriginZ( property.Get< float >() );
2708 case Dali::Actor::Property::ANCHOR_POINT:
2710 SetAnchorPoint( property.Get< Vector3 >() );
2714 case Dali::Actor::Property::ANCHOR_POINT_X:
2716 SetAnchorPointX( property.Get< float >() );
2720 case Dali::Actor::Property::ANCHOR_POINT_Y:
2722 SetAnchorPointY( property.Get< float >() );
2726 case Dali::Actor::Property::ANCHOR_POINT_Z:
2728 SetAnchorPointZ( property.Get< float >() );
2732 case Dali::Actor::Property::SIZE:
2734 SetSize( property.Get< Vector3 >() );
2738 case Dali::Actor::Property::SIZE_WIDTH:
2740 SetWidth( property.Get< float >() );
2744 case Dali::Actor::Property::SIZE_HEIGHT:
2746 SetHeight( property.Get< float >() );
2750 case Dali::Actor::Property::SIZE_DEPTH:
2752 SetDepth( property.Get< float >() );
2756 case Dali::Actor::Property::POSITION:
2758 SetPosition( property.Get< Vector3 >() );
2762 case Dali::Actor::Property::POSITION_X:
2764 SetX( property.Get< float >() );
2768 case Dali::Actor::Property::POSITION_Y:
2770 SetY( property.Get< float >() );
2774 case Dali::Actor::Property::POSITION_Z:
2776 SetZ( property.Get< float >() );
2780 case Dali::Actor::Property::ORIENTATION:
2782 SetOrientation( property.Get< Quaternion >() );
2786 case Dali::Actor::Property::SCALE:
2788 SetScale( property.Get< Vector3 >() );
2792 case Dali::Actor::Property::SCALE_X:
2794 SetScaleX( property.Get< float >() );
2798 case Dali::Actor::Property::SCALE_Y:
2800 SetScaleY( property.Get< float >() );
2804 case Dali::Actor::Property::SCALE_Z:
2806 SetScaleZ( property.Get< float >() );
2810 case Dali::Actor::Property::VISIBLE:
2812 SetVisible( property.Get< bool >() );
2816 case Dali::Actor::Property::COLOR:
2818 SetColor( property.Get< Vector4 >() );
2822 case Dali::Actor::Property::COLOR_RED:
2824 SetColorRed( property.Get< float >() );
2828 case Dali::Actor::Property::COLOR_GREEN:
2830 SetColorGreen( property.Get< float >() );
2834 case Dali::Actor::Property::COLOR_BLUE:
2836 SetColorBlue( property.Get< float >() );
2840 case Dali::Actor::Property::COLOR_ALPHA:
2842 SetOpacity( property.Get< float >() );
2846 case Dali::Actor::Property::NAME:
2848 SetName( property.Get< std::string >() );
2852 case Dali::Actor::Property::SENSITIVE:
2854 SetSensitive( property.Get< bool >() );
2858 case Dali::Actor::Property::LEAVE_REQUIRED:
2860 SetLeaveRequired( property.Get< bool >() );
2864 case Dali::Actor::Property::INHERIT_ORIENTATION:
2866 SetInheritOrientation( property.Get< bool >() );
2870 case Dali::Actor::Property::INHERIT_SCALE:
2872 SetInheritScale( property.Get< bool >() );
2876 case Dali::Actor::Property::COLOR_MODE:
2878 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2882 case Dali::Actor::Property::POSITION_INHERITANCE:
2884 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2888 case Dali::Actor::Property::DRAW_MODE:
2890 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2894 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2896 SetSizeModeFactor( property.Get< Vector3 >() );
2900 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2902 ResizePolicy::Type type;
2903 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2905 SetResizePolicy( type, Dimension::WIDTH );
2910 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2912 ResizePolicy::Type type;
2913 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2915 SetResizePolicy( type, Dimension::HEIGHT );
2920 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2922 SizeScalePolicy::Type type;
2923 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2925 SetSizeScalePolicy( type );
2930 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2932 if( property.Get< bool >() )
2934 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2939 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2941 if( property.Get< bool >() )
2943 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2948 case Dali::Actor::Property::PADDING:
2950 Vector4 padding = property.Get< Vector4 >();
2951 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2952 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2956 case Dali::Actor::Property::MINIMUM_SIZE:
2958 Vector2 size = property.Get< Vector2 >();
2959 SetMinimumSize( size.x, Dimension::WIDTH );
2960 SetMinimumSize( size.y, Dimension::HEIGHT );
2964 case Dali::Actor::Property::MAXIMUM_SIZE:
2966 Vector2 size = property.Get< Vector2 >();
2967 SetMaximumSize( size.x, Dimension::WIDTH );
2968 SetMaximumSize( size.y, Dimension::HEIGHT );
2974 // this can happen in the case of a non-animatable default property so just do nothing
2980 // TODO: This method needs to be removed
2981 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2983 switch( entry.type )
2985 case Property::BOOLEAN:
2987 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2988 DALI_ASSERT_DEBUG( NULL != property );
2990 // property is being used in a separate thread; queue a message to set the property
2991 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2996 case Property::INTEGER:
2998 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2999 DALI_ASSERT_DEBUG( NULL != property );
3001 // property is being used in a separate thread; queue a message to set the property
3002 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3007 case Property::UNSIGNED_INTEGER:
3009 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
3010 DALI_ASSERT_DEBUG( NULL != property );
3012 // property is being used in a separate thread; queue a message to set the property
3013 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3018 case Property::FLOAT:
3020 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3021 DALI_ASSERT_DEBUG( NULL != property );
3023 // property is being used in a separate thread; queue a message to set the property
3024 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3029 case Property::VECTOR2:
3031 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3032 DALI_ASSERT_DEBUG( NULL != property );
3034 // property is being used in a separate thread; queue a message to set the property
3035 if(entry.componentIndex == 0)
3037 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3039 else if(entry.componentIndex == 1)
3041 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3045 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3051 case Property::VECTOR3:
3053 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3054 DALI_ASSERT_DEBUG( NULL != property );
3056 // property is being used in a separate thread; queue a message to set the property
3057 if(entry.componentIndex == 0)
3059 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3061 else if(entry.componentIndex == 1)
3063 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3065 else if(entry.componentIndex == 2)
3067 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3071 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3077 case Property::VECTOR4:
3079 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3080 DALI_ASSERT_DEBUG( NULL != property );
3082 // property is being used in a separate thread; queue a message to set the property
3083 if(entry.componentIndex == 0)
3085 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3087 else if(entry.componentIndex == 1)
3089 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3091 else if(entry.componentIndex == 2)
3093 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3095 else if(entry.componentIndex == 3)
3097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3101 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3107 case Property::ROTATION:
3109 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3110 DALI_ASSERT_DEBUG( NULL != property );
3112 // property is being used in a separate thread; queue a message to set the property
3113 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3118 case Property::MATRIX:
3120 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3121 DALI_ASSERT_DEBUG( NULL != property );
3123 // property is being used in a separate thread; queue a message to set the property
3124 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3129 case Property::MATRIX3:
3131 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3132 DALI_ASSERT_DEBUG( NULL != property );
3134 // property is being used in a separate thread; queue a message to set the property
3135 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3142 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3148 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3150 Property::Value value;
3154 case Dali::Actor::Property::PARENT_ORIGIN:
3156 value = GetCurrentParentOrigin();
3160 case Dali::Actor::Property::PARENT_ORIGIN_X:
3162 value = GetCurrentParentOrigin().x;
3166 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3168 value = GetCurrentParentOrigin().y;
3172 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3174 value = GetCurrentParentOrigin().z;
3178 case Dali::Actor::Property::ANCHOR_POINT:
3180 value = GetCurrentAnchorPoint();
3184 case Dali::Actor::Property::ANCHOR_POINT_X:
3186 value = GetCurrentAnchorPoint().x;
3190 case Dali::Actor::Property::ANCHOR_POINT_Y:
3192 value = GetCurrentAnchorPoint().y;
3196 case Dali::Actor::Property::ANCHOR_POINT_Z:
3198 value = GetCurrentAnchorPoint().z;
3202 case Dali::Actor::Property::SIZE:
3204 value = GetCurrentSize();
3208 case Dali::Actor::Property::SIZE_WIDTH:
3210 value = GetCurrentSize().width;
3214 case Dali::Actor::Property::SIZE_HEIGHT:
3216 value = GetCurrentSize().height;
3220 case Dali::Actor::Property::SIZE_DEPTH:
3222 value = GetCurrentSize().depth;
3226 case Dali::Actor::Property::POSITION:
3228 value = GetCurrentPosition();
3232 case Dali::Actor::Property::POSITION_X:
3234 value = GetCurrentPosition().x;
3238 case Dali::Actor::Property::POSITION_Y:
3240 value = GetCurrentPosition().y;
3244 case Dali::Actor::Property::POSITION_Z:
3246 value = GetCurrentPosition().z;
3250 case Dali::Actor::Property::WORLD_POSITION:
3252 value = GetCurrentWorldPosition();
3256 case Dali::Actor::Property::WORLD_POSITION_X:
3258 value = GetCurrentWorldPosition().x;
3262 case Dali::Actor::Property::WORLD_POSITION_Y:
3264 value = GetCurrentWorldPosition().y;
3268 case Dali::Actor::Property::WORLD_POSITION_Z:
3270 value = GetCurrentWorldPosition().z;
3274 case Dali::Actor::Property::ORIENTATION:
3276 value = GetCurrentOrientation();
3280 case Dali::Actor::Property::WORLD_ORIENTATION:
3282 value = GetCurrentWorldOrientation();
3286 case Dali::Actor::Property::SCALE:
3288 value = GetCurrentScale();
3292 case Dali::Actor::Property::SCALE_X:
3294 value = GetCurrentScale().x;
3298 case Dali::Actor::Property::SCALE_Y:
3300 value = GetCurrentScale().y;
3304 case Dali::Actor::Property::SCALE_Z:
3306 value = GetCurrentScale().z;
3310 case Dali::Actor::Property::WORLD_SCALE:
3312 value = GetCurrentWorldScale();
3316 case Dali::Actor::Property::VISIBLE:
3318 value = IsVisible();
3322 case Dali::Actor::Property::COLOR:
3324 value = GetCurrentColor();
3328 case Dali::Actor::Property::COLOR_RED:
3330 value = GetCurrentColor().r;
3334 case Dali::Actor::Property::COLOR_GREEN:
3336 value = GetCurrentColor().g;
3340 case Dali::Actor::Property::COLOR_BLUE:
3342 value = GetCurrentColor().b;
3346 case Dali::Actor::Property::COLOR_ALPHA:
3348 value = GetCurrentColor().a;
3352 case Dali::Actor::Property::WORLD_COLOR:
3354 value = GetCurrentWorldColor();
3358 case Dali::Actor::Property::WORLD_MATRIX:
3360 value = GetCurrentWorldMatrix();
3364 case Dali::Actor::Property::NAME:
3370 case Dali::Actor::Property::SENSITIVE:
3372 value = IsSensitive();
3376 case Dali::Actor::Property::LEAVE_REQUIRED:
3378 value = GetLeaveRequired();
3382 case Dali::Actor::Property::INHERIT_ORIENTATION:
3384 value = IsOrientationInherited();
3388 case Dali::Actor::Property::INHERIT_SCALE:
3390 value = IsScaleInherited();
3394 case Dali::Actor::Property::COLOR_MODE:
3396 value = Scripting::GetColorMode( GetColorMode() );
3400 case Dali::Actor::Property::POSITION_INHERITANCE:
3402 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3406 case Dali::Actor::Property::DRAW_MODE:
3408 value = Scripting::GetDrawMode( GetDrawMode() );
3412 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3414 value = GetSizeModeFactor();
3418 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3420 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3424 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3426 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3430 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3432 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3436 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3438 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3442 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3444 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3448 case Dali::Actor::Property::PADDING:
3450 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3451 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3452 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3456 case Dali::Actor::Property::MINIMUM_SIZE:
3458 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3462 case Dali::Actor::Property::MAXIMUM_SIZE:
3464 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3470 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3478 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3483 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3485 // This method should only return an object connected to the scene-graph
3486 return OnStage() ? mNode : NULL;
3489 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3491 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3493 const PropertyBase* property( NULL );
3495 // This method should only return a property of an object connected to the scene-graph
3501 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3503 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3504 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3506 property = animatable->GetSceneGraphProperty();
3508 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3510 CustomPropertyMetadata* custom = FindCustomProperty( index );
3511 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3513 property = custom->GetSceneGraphProperty();
3515 else if( NULL != mNode )
3519 case Dali::Actor::Property::SIZE:
3520 property = &mNode->mSize;
3523 case Dali::Actor::Property::SIZE_WIDTH:
3524 property = &mNode->mSize;
3527 case Dali::Actor::Property::SIZE_HEIGHT:
3528 property = &mNode->mSize;
3531 case Dali::Actor::Property::SIZE_DEPTH:
3532 property = &mNode->mSize;
3535 case Dali::Actor::Property::POSITION:
3536 property = &mNode->mPosition;
3539 case Dali::Actor::Property::POSITION_X:
3540 property = &mNode->mPosition;
3543 case Dali::Actor::Property::POSITION_Y:
3544 property = &mNode->mPosition;
3547 case Dali::Actor::Property::POSITION_Z:
3548 property = &mNode->mPosition;
3551 case Dali::Actor::Property::ORIENTATION:
3552 property = &mNode->mOrientation;
3555 case Dali::Actor::Property::SCALE:
3556 property = &mNode->mScale;
3559 case Dali::Actor::Property::SCALE_X:
3560 property = &mNode->mScale;
3563 case Dali::Actor::Property::SCALE_Y:
3564 property = &mNode->mScale;
3567 case Dali::Actor::Property::SCALE_Z:
3568 property = &mNode->mScale;
3571 case Dali::Actor::Property::VISIBLE:
3572 property = &mNode->mVisible;
3575 case Dali::Actor::Property::COLOR:
3576 property = &mNode->mColor;
3579 case Dali::Actor::Property::COLOR_RED:
3580 property = &mNode->mColor;
3583 case Dali::Actor::Property::COLOR_GREEN:
3584 property = &mNode->mColor;
3587 case Dali::Actor::Property::COLOR_BLUE:
3588 property = &mNode->mColor;
3591 case Dali::Actor::Property::COLOR_ALPHA:
3592 property = &mNode->mColor;
3603 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3605 const PropertyInputImpl* property( NULL );
3607 // This method should only return a property of an object connected to the scene-graph
3613 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3615 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3616 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3618 property = animatable->GetSceneGraphProperty();
3620 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3622 CustomPropertyMetadata* custom = FindCustomProperty( index );
3623 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3624 property = custom->GetSceneGraphProperty();
3626 else if( NULL != mNode )
3630 case Dali::Actor::Property::PARENT_ORIGIN:
3631 property = &mNode->mParentOrigin;
3634 case Dali::Actor::Property::PARENT_ORIGIN_X:
3635 property = &mNode->mParentOrigin;
3638 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3639 property = &mNode->mParentOrigin;
3642 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3643 property = &mNode->mParentOrigin;
3646 case Dali::Actor::Property::ANCHOR_POINT:
3647 property = &mNode->mAnchorPoint;
3650 case Dali::Actor::Property::ANCHOR_POINT_X:
3651 property = &mNode->mAnchorPoint;
3654 case Dali::Actor::Property::ANCHOR_POINT_Y:
3655 property = &mNode->mAnchorPoint;
3658 case Dali::Actor::Property::ANCHOR_POINT_Z:
3659 property = &mNode->mAnchorPoint;
3662 case Dali::Actor::Property::SIZE:
3663 property = &mNode->mSize;
3666 case Dali::Actor::Property::SIZE_WIDTH:
3667 property = &mNode->mSize;
3670 case Dali::Actor::Property::SIZE_HEIGHT:
3671 property = &mNode->mSize;
3674 case Dali::Actor::Property::SIZE_DEPTH:
3675 property = &mNode->mSize;
3678 case Dali::Actor::Property::POSITION:
3679 property = &mNode->mPosition;
3682 case Dali::Actor::Property::POSITION_X:
3683 property = &mNode->mPosition;
3686 case Dali::Actor::Property::POSITION_Y:
3687 property = &mNode->mPosition;
3690 case Dali::Actor::Property::POSITION_Z:
3691 property = &mNode->mPosition;
3694 case Dali::Actor::Property::WORLD_POSITION:
3695 property = &mNode->mWorldPosition;
3698 case Dali::Actor::Property::WORLD_POSITION_X:
3699 property = &mNode->mWorldPosition;
3702 case Dali::Actor::Property::WORLD_POSITION_Y:
3703 property = &mNode->mWorldPosition;
3706 case Dali::Actor::Property::WORLD_POSITION_Z:
3707 property = &mNode->mWorldPosition;
3710 case Dali::Actor::Property::ORIENTATION:
3711 property = &mNode->mOrientation;
3714 case Dali::Actor::Property::WORLD_ORIENTATION:
3715 property = &mNode->mWorldOrientation;
3718 case Dali::Actor::Property::SCALE:
3719 property = &mNode->mScale;
3722 case Dali::Actor::Property::SCALE_X:
3723 property = &mNode->mScale;
3726 case Dali::Actor::Property::SCALE_Y:
3727 property = &mNode->mScale;
3730 case Dali::Actor::Property::SCALE_Z:
3731 property = &mNode->mScale;
3734 case Dali::Actor::Property::WORLD_SCALE:
3735 property = &mNode->mWorldScale;
3738 case Dali::Actor::Property::VISIBLE:
3739 property = &mNode->mVisible;
3742 case Dali::Actor::Property::COLOR:
3743 property = &mNode->mColor;
3746 case Dali::Actor::Property::COLOR_RED:
3747 property = &mNode->mColor;
3750 case Dali::Actor::Property::COLOR_GREEN:
3751 property = &mNode->mColor;
3754 case Dali::Actor::Property::COLOR_BLUE:
3755 property = &mNode->mColor;
3758 case Dali::Actor::Property::COLOR_ALPHA:
3759 property = &mNode->mColor;
3762 case Dali::Actor::Property::WORLD_COLOR:
3763 property = &mNode->mWorldColor;
3766 case Dali::Actor::Property::WORLD_MATRIX:
3767 property = &mNode->mWorldMatrix;
3778 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3780 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3782 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3784 // check whether the animatable property is registered already, if not then register one.
3785 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3786 if( animatableProperty )
3788 componentIndex = animatableProperty->componentIndex;
3795 case Dali::Actor::Property::PARENT_ORIGIN_X:
3796 case Dali::Actor::Property::ANCHOR_POINT_X:
3797 case Dali::Actor::Property::SIZE_WIDTH:
3798 case Dali::Actor::Property::POSITION_X:
3799 case Dali::Actor::Property::WORLD_POSITION_X:
3800 case Dali::Actor::Property::SCALE_X:
3801 case Dali::Actor::Property::COLOR_RED:
3807 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3808 case Dali::Actor::Property::ANCHOR_POINT_Y:
3809 case Dali::Actor::Property::SIZE_HEIGHT:
3810 case Dali::Actor::Property::POSITION_Y:
3811 case Dali::Actor::Property::WORLD_POSITION_Y:
3812 case Dali::Actor::Property::SCALE_Y:
3813 case Dali::Actor::Property::COLOR_GREEN:
3819 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3820 case Dali::Actor::Property::ANCHOR_POINT_Z:
3821 case Dali::Actor::Property::SIZE_DEPTH:
3822 case Dali::Actor::Property::POSITION_Z:
3823 case Dali::Actor::Property::WORLD_POSITION_Z:
3824 case Dali::Actor::Property::SCALE_Z:
3825 case Dali::Actor::Property::COLOR_BLUE:
3831 case Dali::Actor::Property::COLOR_ALPHA:
3845 return componentIndex;
3848 void Actor::SetParent( Actor* parent, int index )
3852 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3856 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3859 // Instruct each actor to create a corresponding node in the scene graph
3860 ConnectToStage( parent->GetDepth(), index );
3863 else // parent being set to NULL
3865 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3869 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3872 DALI_ASSERT_ALWAYS( mNode != NULL );
3876 // Disconnect the Node & its children from the scene-graph.
3877 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3880 // Instruct each actor to discard pointers to the scene-graph
3881 DisconnectFromStage();
3886 SceneGraph::Node* Actor::CreateNode() const
3891 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3894 Actor* actor = dynamic_cast< Actor* >( object );
3898 if( 0 == actionName.compare( ACTION_SHOW ) )
3900 actor->SetVisible( true );
3903 else if( 0 == actionName.compare( ACTION_HIDE ) )
3905 actor->SetVisible( false );
3913 void Actor::EnsureRelayoutData() const
3915 // Assign relayout data.
3916 if( !mRelayoutData )
3918 mRelayoutData = new RelayoutData();
3922 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3924 // Check if actor is dependent on parent
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 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3940 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3942 // Check if actor is dependent on children
3943 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3945 if( ( dimension & ( 1 << i ) ) )
3947 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3948 switch( resizePolicy )
3950 case ResizePolicy::FIT_TO_CHILDREN:
3951 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3967 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3969 return Actor::RelayoutDependentOnChildren( dimension );
3972 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3974 // Check each possible dimension and see if it is dependent on the input one
3975 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3977 if( dimension & ( 1 << i ) )
3979 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3986 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3988 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3990 if( dimension & ( 1 << i ) )
3992 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3997 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3999 // If more than one dimension is requested, just return the first one found
4000 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4002 if( ( dimension & ( 1 << i ) ) )
4004 return mRelayoutData->negotiatedDimensions[ i ];
4008 return 0.0f; // Default
4011 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4013 EnsureRelayoutData();
4015 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4017 if( dimension & ( 1 << i ) )
4019 mRelayoutData->dimensionPadding[ i ] = padding;
4024 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4026 EnsureRelayoutData();
4028 // If more than one dimension is requested, just return the first one found
4029 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4031 if( ( dimension & ( 1 << i ) ) )
4033 return mRelayoutData->dimensionPadding[ i ];
4037 return Vector2( 0.0f, 0.0f ); // Default
4040 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4042 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4044 if( dimension & ( 1 << i ) )
4046 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4051 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4053 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4055 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4064 float Actor::GetHeightForWidthBase( float width )
4066 float height = 0.0f;
4068 const Vector3 naturalSize = GetNaturalSize();
4069 if( naturalSize.width > 0.0f )
4071 height = naturalSize.height * width / naturalSize.width;
4073 else // we treat 0 as 1:1 aspect ratio
4081 float Actor::GetWidthForHeightBase( float height )
4085 const Vector3 naturalSize = GetNaturalSize();
4086 if( naturalSize.height > 0.0f )
4088 width = naturalSize.width * height / naturalSize.height;
4090 else // we treat 0 as 1:1 aspect ratio
4098 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4100 // Fill to parent, taking size mode factor into account
4101 switch( child.GetResizePolicy( dimension ) )
4103 case ResizePolicy::FILL_TO_PARENT:
4105 return GetLatestSize( dimension );
4108 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4110 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4113 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4115 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4120 return GetLatestSize( dimension );
4125 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4127 // Can be overridden in derived class
4128 return CalculateChildSizeBase( child, dimension );
4131 float Actor::GetHeightForWidth( float width )
4133 // Can be overridden in derived class
4134 return GetHeightForWidthBase( width );
4137 float Actor::GetWidthForHeight( float height )
4139 // Can be overridden in derived class
4140 return GetWidthForHeightBase( height );
4143 float Actor::GetLatestSize( Dimension::Type dimension ) const
4145 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4148 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4150 Vector2 padding = GetPadding( dimension );
4152 return GetLatestSize( dimension ) + padding.x + padding.y;
4155 float Actor::NegotiateFromParent( Dimension::Type dimension )
4157 Actor* parent = GetParent();
4160 Vector2 padding( GetPadding( dimension ) );
4161 Vector2 parentPadding( parent->GetPadding( dimension ) );
4162 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4168 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4170 float maxDimensionPoint = 0.0f;
4172 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4174 Dali::Actor child = GetChildAt( i );
4175 Actor& childImpl = GetImplementation( child );
4177 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4179 // Calculate the min and max points that the children range across
4180 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4181 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4182 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4186 return maxDimensionPoint;
4189 float Actor::GetSize( Dimension::Type dimension ) const
4191 return GetDimensionValue( GetTargetSize(), dimension );
4194 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4196 return GetDimensionValue( GetNaturalSize(), dimension );
4199 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4201 switch( GetResizePolicy( dimension ) )
4203 case ResizePolicy::USE_NATURAL_SIZE:
4205 return GetNaturalSize( dimension );
4208 case ResizePolicy::FIXED:
4210 return GetDimensionValue( GetPreferredSize(), dimension );
4213 case ResizePolicy::USE_ASSIGNED_SIZE:
4215 return GetDimensionValue( maximumSize, dimension );
4218 case ResizePolicy::FILL_TO_PARENT:
4219 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4220 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4222 return NegotiateFromParent( dimension );
4225 case ResizePolicy::FIT_TO_CHILDREN:
4227 return NegotiateFromChildren( dimension );
4230 case ResizePolicy::DIMENSION_DEPENDENCY:
4232 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4235 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4237 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4240 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4242 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4254 return 0.0f; // Default
4257 float Actor::ClampDimension( float size, Dimension::Type dimension )
4259 const float minSize = GetMinimumSize( dimension );
4260 const float maxSize = GetMaximumSize( dimension );
4262 return std::max( minSize, std::min( size, maxSize ) );
4265 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4267 // Check if it needs to be negotiated
4268 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4270 // Check that we havn't gotten into an infinite loop
4271 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4272 bool recursionFound = false;
4273 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4275 if( *it == searchActor )
4277 recursionFound = true;
4282 if( !recursionFound )
4284 // Record the path that we have taken
4285 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4287 // Dimension dependency check
4288 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4290 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4292 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4294 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4298 // Parent dependency check
4299 Actor* parent = GetParent();
4300 if( parent && RelayoutDependentOnParent( dimension ) )
4302 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4305 // Children dependency check
4306 if( RelayoutDependentOnChildren( dimension ) )
4308 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4310 Dali::Actor child = GetChildAt( i );
4311 Actor& childImpl = GetImplementation( child );
4313 // Only relayout child first if it is not dependent on this actor
4314 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4316 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4321 // For deriving classes
4322 OnCalculateRelayoutSize( dimension );
4324 // All dependencies checked, calculate the size and set negotiated flag
4325 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4327 SetNegotiatedDimension( newSize, dimension );
4328 SetLayoutNegotiated( true, dimension );
4330 // For deriving classes
4331 OnLayoutNegotiated( newSize, dimension );
4333 // This actor has been successfully processed, pop it off the recursion stack
4334 recursionStack.pop_back();
4338 // TODO: Break infinite loop
4339 SetLayoutNegotiated( true, dimension );
4344 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4346 // Negotiate all dimensions that require it
4347 ActorDimensionStack recursionStack;
4349 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4351 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4354 NegotiateDimension( dimension, allocatedSize, recursionStack );
4358 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4360 switch( mRelayoutData->sizeSetPolicy )
4362 case SizeScalePolicy::USE_SIZE_SET:
4367 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4369 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4370 const Vector3 naturalSize = GetNaturalSize();
4371 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4373 const float sizeRatio = size.width / size.height;
4374 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4376 if( naturalSizeRatio < sizeRatio )
4378 return Vector2( naturalSizeRatio * size.height, size.height );
4380 else if( naturalSizeRatio > sizeRatio )
4382 return Vector2( size.width, size.width / naturalSizeRatio );
4393 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4395 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4396 const Vector3 naturalSize = GetNaturalSize();
4397 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4399 const float sizeRatio = size.width / size.height;
4400 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4402 if( naturalSizeRatio < sizeRatio )
4404 return Vector2( size.width, size.width / naturalSizeRatio );
4406 else if( naturalSizeRatio > sizeRatio )
4408 return Vector2( naturalSizeRatio * size.height, size.height );
4426 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4428 // Do the set actor size
4429 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4431 // Adjust for size set policy
4432 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4434 // Lock the flag to stop recursive relayouts on set size
4435 mRelayoutData->insideRelayout = true;
4436 SetSize( negotiatedSize );
4437 mRelayoutData->insideRelayout = false;
4439 // Clear flags for all dimensions
4440 SetLayoutDirty( false );
4442 // Give deriving classes a chance to respond
4443 OnRelayout( negotiatedSize, container );
4445 if( !mOnRelayoutSignal.Empty() )
4447 Dali::Actor handle( this );
4448 mOnRelayoutSignal.Emit( handle );
4452 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4454 // Do the negotiation
4455 NegotiateDimensions( allocatedSize );
4457 // Set the actor size
4458 SetNegotiatedSize( container );
4460 // Negotiate down to children
4461 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4463 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4465 Dali::Actor child = GetChildAt( i );
4467 // Only relayout if required
4468 if( GetImplementation( child ).RelayoutRequired() )
4470 container.Add( child, newBounds );
4475 void Actor::RelayoutRequest( Dimension::Type dimension )
4477 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4478 if( relayoutController )
4480 Dali::Actor self( this );
4481 relayoutController->RequestRelayout( self, dimension );
4485 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4489 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4493 void Actor::SetPreferredSize( const Vector2& size )
4495 EnsureRelayoutData();
4497 if( size.width > 0.0f )
4499 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4502 if( size.height > 0.0f )
4504 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4507 mRelayoutData->preferredSize = size;
4512 Vector2 Actor::GetPreferredSize() const
4514 EnsureRelayoutData();
4516 return mRelayoutData->preferredSize;
4519 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4521 EnsureRelayoutData();
4523 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4525 if( dimension & ( 1 << i ) )
4527 mRelayoutData->minimumSize[ i ] = size;
4534 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4536 EnsureRelayoutData();
4538 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4540 if( dimension & ( 1 << i ) )
4542 return mRelayoutData->minimumSize[ i ];
4546 return 0.0f; // Default
4549 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4551 EnsureRelayoutData();
4553 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4555 if( dimension & ( 1 << i ) )
4557 mRelayoutData->maximumSize[ i ] = size;
4564 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4566 EnsureRelayoutData();
4568 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4570 if( dimension & ( 1 << i ) )
4572 return mRelayoutData->maximumSize[ i ];
4576 return 0.0f; // Default
4579 } // namespace Internal