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>
25 #include <cstring> // for strcmp
29 #include <dali/public-api/common/dali-common.h>
30 #include <dali/public-api/common/constants.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/actor-attachments/actor-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 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 )DALI_ENUM_TO_STRING( FIXED )
76 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
77 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
80 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
81 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
82 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
83 DALI_ENUM_TO_STRING_TABLE_END( Type )
85 } // unnamed namespace
88 namespace SizeScalePolicy
92 // Enumeration to / from string conversion tables
93 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
94 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
95 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING_TABLE_END( Type )
97 } // unnamed namespace
103 unsigned int Actor::mActorCounter = 0;
106 * Struct to collect relayout variables
108 struct Actor::RelayoutData
111 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
113 // Set size negotiation defaults
114 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
116 resizePolicies[ i ] = ResizePolicy::FIXED;
117 negotiatedDimensions[ i ] = 0.0f;
118 dimensionNegotiated[ i ] = false;
119 dimensionDirty[ i ] = false;
120 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
121 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
122 minimumSize[ i ] = 0.0f;
123 maximumSize[ i ] = FLT_MAX;
127 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
129 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
131 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
133 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
135 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
136 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
138 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
139 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
141 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
143 Vector2 preferredSize; ///< The preferred size of the actor
145 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
147 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
148 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
151 #ifdef DYNAMICS_SUPPORT
153 // Encapsulate actor related dynamics data
156 DynamicsData( Actor* slotOwner )
157 : slotDelegate( slotOwner )
161 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
162 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
164 DynamicsBodyPtr body;
165 JointContainer joints;
166 ReferencedJointContainer referencedJoints;
168 SlotDelegate< Actor > slotDelegate;
171 #endif // DYNAMICS_SUPPORT
173 namespace // unnamed namespace
179 * We want to discourage the use of property strings (minimize string comparisons),
180 * particularly for the default properties.
181 * Name Type writable animatable constraint-input enum for index-checking
183 DALI_PROPERTY_TABLE_BEGIN
184 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
185 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
186 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
187 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
188 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
189 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
190 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
191 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
192 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
193 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
194 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
195 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
196 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
197 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
198 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
199 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
200 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
201 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
202 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
203 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
204 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
205 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
206 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
207 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
208 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
209 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
210 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
211 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
212 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
213 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
214 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
215 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
216 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
217 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
218 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
219 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
220 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
221 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
222 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
223 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
224 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
225 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
226 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
227 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
228 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
229 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
230 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
231 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
232 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
233 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
234 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
235 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
236 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
240 const char* const SIGNAL_TOUCHED = "touched";
241 const char* const SIGNAL_HOVERED = "hovered";
242 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
243 const char* const SIGNAL_ON_STAGE = "on-stage";
244 const char* const SIGNAL_OFF_STAGE = "off-stage";
248 const char* const ACTION_SHOW = "show";
249 const char* const ACTION_HIDE = "hide";
251 BaseHandle CreateActor()
253 return Dali::Actor::New();
256 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
258 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
267 * @brief Extract a given dimension from a Vector2
269 * @param[in] values The values to extract from
270 * @param[in] dimension The dimension to extract
271 * @return Return the value for the dimension
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
277 case Dimension::WIDTH:
282 case Dimension::HEIGHT:
284 return values.height;
297 * @brief Extract a given dimension from a Vector3
299 * @param[in] values The values to extract from
300 * @param[in] dimension The dimension to extract
301 * @return Return the value for the dimension
303 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
305 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::SetInitialVolume( const Vector3& volume )
925 // mNode is being used in a separate thread; queue a message to set the value
926 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
930 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
934 // mNode is being used in a separate thread; queue a message to set the value
935 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
939 bool Actor::GetTransmitGeometryScaling() const
943 // mNode is being used in a separate thread; copy the value from the previous update
944 return mNode->GetTransmitGeometryScaling();
950 void Actor::ScaleBy( const Vector3& relativeScale )
954 // mNode is being used in a separate thread; queue a message to set the value & base value
955 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
959 const Vector3& Actor::GetCurrentScale() const
963 // mNode is being used in a separate thread; copy the value from the previous update
964 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
970 const Vector3& Actor::GetCurrentWorldScale() const
974 // mNode is being used in a separate thread; copy the value from the previous update
975 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
981 void Actor::SetInheritScale( bool inherit )
983 // non animateable so keep local copy
984 mInheritScale = inherit;
987 // mNode is being used in a separate thread; queue a message to set the value
988 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
992 bool Actor::IsScaleInherited() const
994 return mInheritScale;
997 Matrix Actor::GetCurrentWorldMatrix() const
1001 // World matrix is no longer updated unless there is something observing the node.
1002 // Need to calculate it from node's world position, orientation and scale:
1003 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1004 Matrix worldMatrix(false);
1005 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1006 mNode->GetWorldOrientation( updateBufferIndex ),
1007 mNode->GetWorldPosition( updateBufferIndex ) );
1011 return Matrix::IDENTITY;
1014 void Actor::SetVisible( bool visible )
1018 // mNode is being used in a separate thread; queue a message to set the value & base value
1019 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1023 bool Actor::IsVisible() const
1027 // mNode is being used in a separate thread; copy the value from the previous update
1028 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1034 void Actor::SetOpacity( float opacity )
1038 // mNode is being used in a separate thread; queue a message to set the value & base value
1039 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1043 float Actor::GetCurrentOpacity() const
1047 // mNode is being used in a separate thread; copy the value from the previous update
1048 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1054 const Vector4& Actor::GetCurrentWorldColor() const
1058 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1061 return Color::WHITE;
1064 void Actor::SetColor( const Vector4& color )
1068 // mNode is being used in a separate thread; queue a message to set the value & base value
1069 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1073 void Actor::SetColorRed( float red )
1077 // mNode is being used in a separate thread; queue a message to set the value & base value
1078 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1082 void Actor::SetColorGreen( float green )
1086 // mNode is being used in a separate thread; queue a message to set the value & base value
1087 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1091 void Actor::SetColorBlue( float blue )
1095 // mNode is being used in a separate thread; queue a message to set the value & base value
1096 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1100 const Vector4& Actor::GetCurrentColor() const
1104 // mNode is being used in a separate thread; copy the value from the previous update
1105 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1108 return Color::WHITE;
1111 void Actor::SetInheritOrientation( bool inherit )
1113 // non animateable so keep local copy
1114 mInheritOrientation = inherit;
1117 // mNode is being used in a separate thread; queue a message to set the value
1118 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1122 bool Actor::IsOrientationInherited() const
1124 return mInheritOrientation;
1127 void Actor::SetSizeModeFactor( const Vector3& factor )
1129 EnsureRelayoutData();
1131 mRelayoutData->sizeModeFactor = factor;
1134 const Vector3& Actor::GetSizeModeFactor() const
1136 EnsureRelayoutData();
1138 return mRelayoutData->sizeModeFactor;
1141 void Actor::SetColorMode( ColorMode colorMode )
1143 // non animateable so keep local copy
1144 mColorMode = colorMode;
1147 // mNode is being used in a separate thread; queue a message to set the value
1148 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1152 ColorMode Actor::GetColorMode() const
1154 // we have cached copy
1158 void Actor::SetSize( float width, float height )
1160 SetSize( Vector2( width, height ) );
1163 void Actor::SetSize( float width, float height, float depth )
1165 SetSize( Vector3( width, height, depth ) );
1168 void Actor::SetSize( const Vector2& size )
1170 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1173 void Actor::SetSizeInternal( const Vector2& size )
1175 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1178 float Actor::CalculateSizeZ( const Vector2& size ) const
1180 return std::min( size.width, size.height );
1183 void Actor::SetSize( const Vector3& size )
1185 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1187 SetPreferredSize( size.GetVectorXY() );
1191 SetSizeInternal( size );
1195 void Actor::SetSizeInternal( const Vector3& size )
1197 // dont allow recursive loop
1198 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1199 // 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
1200 if( ( NULL != mNode )&&
1201 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1202 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1203 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1207 // mNode is being used in a separate thread; queue a message to set the value & base value
1208 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1210 // Notification for derived classes
1211 mInsideOnSizeSet = true;
1212 OnSizeSet( mTargetSize );
1213 mInsideOnSizeSet = false;
1215 // Raise a relayout request if the flag is not locked
1216 if( mRelayoutData && !mRelayoutData->insideRelayout )
1223 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1225 mTargetSize = targetSize;
1227 // Notify deriving classes
1228 OnSizeAnimation( animation, mTargetSize );
1231 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1233 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1235 mTargetSize.width = targetSize;
1237 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1239 mTargetSize.height = targetSize;
1241 // Notify deriving classes
1242 OnSizeAnimation( animation, mTargetSize );
1245 void Actor::SetWidth( float width )
1249 // mNode is being used in a separate thread; queue a message to set the value & base value
1250 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1254 void Actor::SetHeight( float height )
1258 // mNode is being used in a separate thread; queue a message to set the value & base value
1259 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1263 void Actor::SetDepth( float depth )
1267 // mNode is being used in a separate thread; queue a message to set the value & base value
1268 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1272 const Vector3& Actor::GetTargetSize() const
1277 const Vector3& Actor::GetCurrentSize() const
1281 // mNode is being used in a separate thread; copy the value from the previous update
1282 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1285 return Vector3::ZERO;
1288 Vector3 Actor::GetNaturalSize() const
1290 // It is up to deriving classes to return the appropriate natural size
1291 return Vector3( 0.0f, 0.0f, 0.0f );
1294 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1296 EnsureRelayoutData();
1298 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1300 if( dimension & ( 1 << i ) )
1302 mRelayoutData->resizePolicies[ i ] = policy;
1306 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1308 if( dimension & Dimension::WIDTH )
1310 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1313 if( dimension & Dimension::HEIGHT )
1315 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1319 // If calling SetResizePolicy, assume we want relayout enabled
1320 SetRelayoutEnabled( true );
1322 OnSetResizePolicy( policy, dimension );
1324 // Trigger relayout on this control
1328 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1330 EnsureRelayoutData();
1332 // If more than one dimension is requested, just return the first one found
1333 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1335 if( ( dimension & ( 1 << i ) ) )
1337 return mRelayoutData->resizePolicies[ i ];
1341 return ResizePolicy::FIXED; // Default
1344 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1346 EnsureRelayoutData();
1348 mRelayoutData->sizeSetPolicy = policy;
1351 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1353 EnsureRelayoutData();
1355 return mRelayoutData->sizeSetPolicy;
1358 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1360 EnsureRelayoutData();
1362 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1364 if( dimension & ( 1 << i ) )
1366 mRelayoutData->dimensionDependencies[ i ] = dependency;
1371 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1373 EnsureRelayoutData();
1375 // If more than one dimension is requested, just return the first one found
1376 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1378 if( ( dimension & ( 1 << i ) ) )
1380 return mRelayoutData->dimensionDependencies[ i ];
1384 return Dimension::ALL_DIMENSIONS; // Default
1387 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1389 // If relayout data has not been allocated yet and the client is requesting
1390 // to disable it, do nothing
1391 if( mRelayoutData || relayoutEnabled )
1393 EnsureRelayoutData();
1395 mRelayoutData->relayoutEnabled = relayoutEnabled;
1399 bool Actor::IsRelayoutEnabled() const
1401 // Assume that if relayout data has not been allocated yet then
1402 // relayout is disabled
1403 return mRelayoutData && mRelayoutData->relayoutEnabled;
1406 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1408 EnsureRelayoutData();
1410 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1412 if( dimension & ( 1 << i ) )
1414 mRelayoutData->dimensionDirty[ i ] = dirty;
1419 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1421 EnsureRelayoutData();
1423 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1425 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1434 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1436 EnsureRelayoutData();
1438 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1441 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1443 EnsureRelayoutData();
1445 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1448 #ifdef DYNAMICS_SUPPORT
1450 //--------------- Dynamics ---------------
1452 void Actor::DisableDynamics()
1454 if( NULL != mDynamicsData )
1456 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1458 // ensure dynamics object are disconnected from scene
1459 DisconnectDynamics();
1461 // delete joint owned by this actor
1462 while( !mDynamicsData->joints.empty() )
1464 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1467 // delete other joints referencing this actor
1468 while( !mDynamicsData->referencedJoints.empty() )
1470 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1471 ActorPtr jointOwner( joint->GetActor( true ) );
1474 jointOwner->RemoveDynamicsJoint( joint );
1478 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1481 // delete the DynamicsBody object
1482 mDynamicsData->body.Reset();
1484 // Discard Dynamics data structure
1485 delete mDynamicsData;
1486 mDynamicsData = NULL;
1490 DynamicsBodyPtr Actor::GetDynamicsBody() const
1492 DynamicsBodyPtr body;
1494 if( NULL != mDynamicsData )
1496 body = mDynamicsData->body;
1502 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1504 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1506 if( NULL == mDynamicsData )
1508 mDynamicsData = new DynamicsData( this );
1511 if( !mDynamicsData->body )
1513 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1517 DynamicsWorldPtr world( DynamicsWorld::Get() );
1520 if( mParent == world->GetRootActor().Get() )
1522 mDynamicsData->body->Connect( GetEventThreadServices() );
1528 return mDynamicsData->body;
1531 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1533 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1534 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1537 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1539 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1540 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1542 DynamicsJointPtr joint;
1544 DynamicsWorldPtr world( DynamicsWorld::Get() );
1548 if( NULL != mDynamicsData )
1550 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1552 if( mDynamicsData->joints.end() != it )
1554 // use existing joint
1560 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1561 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1565 bodyA = EnableDynamics( new DynamicsBodyConfig );
1570 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1573 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1574 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1576 if( OnStage() && attachedActor->OnStage() )
1578 joint->Connect( GetEventThreadServices() );
1581 attachedActor->ReferenceJoint( joint );
1583 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1584 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1591 const int Actor::GetNumberOfJoints() const
1593 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1596 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1598 DynamicsJointPtr joint;
1600 if( NULL != mDynamicsData )
1602 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1604 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1606 for( int i = 0; i < index; ++i )
1618 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1620 DynamicsJointPtr joint;
1622 if( NULL != mDynamicsData )
1624 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1626 if( mDynamicsData->joints.end() != it )
1628 // use existing joint
1636 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1638 if( NULL != mDynamicsData )
1640 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1641 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1643 for(; it != endIt; ++it )
1645 if( it->second == joint.Get() )
1647 ActorPtr attachedActor( it->first );
1649 if( OnStage() && attachedActor && attachedActor->OnStage() )
1651 joint->Disconnect( GetEventThreadServices() );
1656 attachedActor->ReleaseJoint( joint );
1657 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1658 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1661 mDynamicsData->joints.erase(it);
1668 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1670 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1672 if( NULL != mDynamicsData )
1674 mDynamicsData->referencedJoints.push_back(joint);
1678 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1680 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1682 if( NULL != mDynamicsData )
1684 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1686 if( it != mDynamicsData->referencedJoints.end() )
1688 mDynamicsData->referencedJoints.erase( it );
1693 void Actor::SetDynamicsRoot(bool flag)
1695 if( mIsDynamicsRoot != flag )
1697 mIsDynamicsRoot = flag;
1699 if( OnStage() && mChildren )
1701 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1702 ActorIter end = mChildren->end();
1703 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1705 Actor& child = GetImplementation(*iter);
1707 if( child.GetDynamicsBody() )
1709 if( mIsDynamicsRoot )
1711 child.ConnectDynamics();
1715 child.DisconnectDynamics();
1723 bool Actor::IsDynamicsRoot() const
1725 return mIsDynamicsRoot;
1728 void Actor::AttachedActorOnStage( Dali::Actor actor )
1730 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1734 ActorPtr attachedActor( &GetImplementation(actor) );
1736 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1737 if( NULL != mDynamicsData )
1739 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1740 if( mDynamicsData->joints.end() != it )
1742 DynamicsJointPtr joint( it->second );
1743 joint->Connect( GetEventThreadServices() );
1749 void Actor::AttachedActorOffStage( Dali::Actor actor )
1751 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1755 ActorPtr attachedActor( &GetImplementation(actor) );
1757 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1758 if( NULL != mDynamicsData )
1760 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1761 if( mDynamicsData->joints.end() != it )
1763 DynamicsJointPtr joint( it->second );
1764 joint->Disconnect( GetEventThreadServices() );
1770 void Actor::ConnectDynamics()
1772 if( NULL != mDynamicsData && mDynamicsData->body )
1774 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1776 mDynamicsData->body->Connect( GetEventThreadServices() );
1778 // Connect all joints where attachedActor is also on stage
1779 if( !mDynamicsData->joints.empty() )
1781 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1782 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1784 for(; it != endIt; ++it )
1786 Actor* attachedActor( it->first );
1787 if( NULL != attachedActor && attachedActor->OnStage() )
1789 DynamicsJointPtr joint( it->second );
1791 joint->Connect( GetEventThreadServices() );
1799 void Actor::DisconnectDynamics()
1801 if( NULL != mDynamicsData && mDynamicsData->body )
1805 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1807 // Disconnect all joints
1808 if( !mDynamicsData->joints.empty() )
1810 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1811 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1813 for(; it != endIt; ++it )
1815 DynamicsJointPtr joint( it->second );
1817 joint->Disconnect( GetEventThreadServices() );
1824 #endif // DYNAMICS_SUPPORT
1826 void Actor::SetOverlay( bool enable )
1828 // Setting STENCIL will override OVERLAY
1829 if( DrawMode::STENCIL != mDrawMode )
1831 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1835 bool Actor::IsOverlay() const
1837 return ( DrawMode::OVERLAY == mDrawMode );
1840 void Actor::SetDrawMode( DrawMode::Type drawMode )
1842 // this flag is not animatable so keep the value
1843 mDrawMode = drawMode;
1846 // mNode is being used in a separate thread; queue a message to set the value
1847 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1851 DrawMode::Type Actor::GetDrawMode() const
1856 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1858 // only valid when on-stage
1861 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1863 Vector2 converted( screenX, screenY );
1865 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1866 const int taskCount = taskList.GetTaskCount();
1867 for( int i = taskCount - 1; i >= 0; --i )
1869 Dali::RenderTask task = taskList.GetTask( i );
1870 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1872 // found a task where this conversion was ok so return
1880 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1882 bool retval = false;
1883 // only valid when on-stage
1886 CameraActor* camera = renderTask.GetCameraActor();
1890 renderTask.GetViewport( viewport );
1892 // need to translate coordinates to render tasks coordinate space
1893 Vector2 converted( screenX, screenY );
1894 if( renderTask.TranslateCoordinates( converted ) )
1896 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1903 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1905 // Early-out if mNode is NULL
1911 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1913 // Calculate the ModelView matrix
1914 Matrix modelView( false/*don't init*/);
1915 // need to use the components as world matrix is only updated for actors that need it
1916 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1917 Matrix::Multiply( modelView, modelView, viewMatrix );
1919 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1920 Matrix invertedMvp( false/*don't init*/);
1921 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1922 bool success = invertedMvp.Invert();
1924 // Convert to GL coordinates
1925 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1930 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1937 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1943 if( XyPlaneIntersect( nearPos, farPos, local ) )
1945 Vector3 size = GetCurrentSize();
1946 localX = local.x + size.x * 0.5f;
1947 localY = local.y + size.y * 0.5f;
1958 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1961 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1963 Mathematical Formulation
1965 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1967 ( p - c ) dot ( p - c ) = r^2
1969 Given a ray with a point of origin 'o', and a direction vector 'd':
1971 ray(t) = o + td, t >= 0
1973 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1975 (o + td - c ) dot ( o + td - c ) = r^2
1977 To solve for t we first expand the above into a more recognisable quadratic equation form
1979 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1988 B = 2( o - c ) dot d
1989 C = ( o - c ) dot ( o - c ) - r^2
1991 which can be solved using a standard quadratic formula.
1993 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1995 Practical Simplification
1997 In a renderer, we often differentiate between world space and object space. In the object space
1998 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1999 into object space, the mathematical solution presented above can be simplified significantly.
2001 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2005 and we can find the t at which the (transformed) ray intersects the sphere by
2007 ( o + td ) dot ( o + td ) = r^2
2009 According to the reasoning above, we expand the above quadratic equation into the general form
2013 which now has coefficients:
2020 // Early out if mNode is NULL
2026 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2028 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2029 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2030 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2032 // Compute the radius is not needed, square radius it's enough.
2033 const Vector3& size( mNode->GetSize( bufferIndex ) );
2035 // Scale the sphere.
2036 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2038 const float width = size.width * scale.width;
2039 const float height = size.height * scale.height;
2041 float squareSphereRadius = 0.5f * ( width * width + height * height );
2043 float a = rayDir.Dot( rayDir ); // a
2044 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2045 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2047 return ( b2 * b2 - a * c ) >= 0.f;
2050 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2057 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2059 // Transforms the ray to the local reference system.
2061 // Calculate the inverse of Model matrix
2062 Matrix invModelMatrix( false/*don't init*/);
2063 // need to use the components as world matrix is only updated for actors that need it
2064 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2066 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2067 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2069 // Test with the actor's XY plane (Normal = 0 0 1 1).
2071 float a = -rayOriginLocal.z;
2072 float b = rayDirLocal.z;
2074 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2076 // Ray travels distance * rayDirLocal to intersect with plane.
2079 const Vector3& size = mNode->GetSize( bufferIndex );
2081 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2082 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2084 // Test with the actor's geometry.
2085 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2092 void Actor::SetLeaveRequired( bool required )
2094 mLeaveRequired = required;
2097 bool Actor::GetLeaveRequired() const
2099 return mLeaveRequired;
2102 void Actor::SetKeyboardFocusable( bool focusable )
2104 mKeyboardFocusable = focusable;
2107 bool Actor::IsKeyboardFocusable() const
2109 return mKeyboardFocusable;
2112 bool Actor::GetTouchRequired() const
2114 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2117 bool Actor::GetHoverRequired() const
2119 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2122 bool Actor::GetWheelEventRequired() const
2124 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2127 bool Actor::IsHittable() const
2129 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2132 ActorGestureData& Actor::GetGestureData()
2134 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2135 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2136 if( NULL == mGestureData )
2138 mGestureData = new ActorGestureData;
2140 return *mGestureData;
2143 bool Actor::IsGestureRequred( Gesture::Type type ) const
2145 return mGestureData && mGestureData->IsGestureRequred( type );
2148 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2150 bool consumed = false;
2152 if( !mTouchedSignal.Empty() )
2154 Dali::Actor handle( this );
2155 consumed = mTouchedSignal.Emit( handle, event );
2160 // Notification for derived classes
2161 consumed = OnTouchEvent( event );
2167 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2169 bool consumed = false;
2171 if( !mHoveredSignal.Empty() )
2173 Dali::Actor handle( this );
2174 consumed = mHoveredSignal.Emit( handle, event );
2179 // Notification for derived classes
2180 consumed = OnHoverEvent( event );
2186 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2188 bool consumed = false;
2190 if( !mWheelEventSignal.Empty() )
2192 Dali::Actor handle( this );
2193 consumed = mWheelEventSignal.Emit( handle, event );
2198 // Notification for derived classes
2199 consumed = OnWheelEvent( event );
2205 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2207 return mTouchedSignal;
2210 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2212 return mHoveredSignal;
2215 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2217 return mWheelEventSignal;
2220 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2222 return mOnStageSignal;
2225 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2227 return mOffStageSignal;
2230 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2232 return mOnRelayoutSignal;
2235 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2237 bool connected( true );
2238 Actor* actor = dynamic_cast< Actor* >( object );
2240 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2242 actor->TouchedSignal().Connect( tracker, functor );
2244 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2246 actor->HoveredSignal().Connect( tracker, functor );
2248 else if( 0 == strcmp( signalName.c_str(), SIGNAL_WHEEL_EVENT ) )
2250 actor->WheelEventSignal().Connect( tracker, functor );
2252 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2254 actor->OnStageSignal().Connect( tracker, functor );
2256 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2258 actor->OffStageSignal().Connect( tracker, functor );
2262 // signalName does not match any signal
2269 Actor::Actor( DerivedType derivedType )
2273 mParentOrigin( NULL ),
2274 mAnchorPoint( NULL ),
2275 mRelayoutData( NULL ),
2276 #ifdef DYNAMICS_SUPPORT
2277 mDynamicsData( NULL ),
2279 mGestureData( NULL ),
2281 mTargetSize( 0.0f, 0.0f, 0.0f ),
2283 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2284 mIsRoot( ROOT_LAYER == derivedType ),
2285 mIsRenderable( RENDERABLE == derivedType ),
2286 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2287 mIsOnStage( false ),
2288 mIsDynamicsRoot( false ),
2290 mLeaveRequired( false ),
2291 mKeyboardFocusable( false ),
2292 mDerivedRequiresTouch( false ),
2293 mDerivedRequiresHover( false ),
2294 mDerivedRequiresWheelEvent( false ),
2295 mOnStageSignalled( false ),
2296 mInsideOnSizeSet( false ),
2297 mInheritOrientation( true ),
2298 mInheritScale( true ),
2299 mDrawMode( DrawMode::NORMAL ),
2300 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2301 mColorMode( Node::DEFAULT_COLOR_MODE )
2305 void Actor::Initialize()
2308 SceneGraph::Node* node = CreateNode();
2310 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2311 mNode = node; // Keep raw-pointer to Node
2315 GetEventThreadServices().RegisterObject( this );
2320 // Remove mParent pointers from children even if we're destroying core,
2321 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2324 ActorConstIter endIter = mChildren->end();
2325 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2327 Actor& actor = GetImplementation( *iter );
2328 actor.SetParent( NULL );
2333 // Guard to allow handle destruction after Core has been destroyed
2334 if( EventThreadServices::IsCoreRunning() )
2338 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2339 mNode = NULL; // Node is about to be destroyed
2342 GetEventThreadServices().UnregisterObject( this );
2345 #ifdef DYNAMICS_SUPPORT
2347 delete mDynamicsData;
2350 // Cleanup optional gesture data
2351 delete mGestureData;
2353 // Cleanup optional parent origin and anchor
2354 delete mParentOrigin;
2355 delete mAnchorPoint;
2357 // Delete optional relayout data
2360 delete mRelayoutData;
2364 void Actor::ConnectToStage( int index )
2366 // This container is used instead of walking the Actor hierachy.
2367 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2368 ActorContainer connectionList;
2370 // This stage is atomic i.e. not interrupted by user callbacks
2371 RecursiveConnectToStage( connectionList, index );
2373 // Notify applications about the newly connected actors.
2374 const ActorIter endIter = connectionList.end();
2375 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2377 Actor& actor = GetImplementation( *iter );
2378 actor.NotifyStageConnection();
2384 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2386 DALI_ASSERT_ALWAYS( !OnStage() );
2390 ConnectToSceneGraph( index );
2392 // Notification for internal derived classes
2393 OnStageConnectionInternal();
2395 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2396 connectionList.push_back( Dali::Actor( this ) );
2398 // Recursively connect children
2401 ActorConstIter endIter = mChildren->end();
2402 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2404 Actor& actor = GetImplementation( *iter );
2405 actor.RecursiveConnectToStage( connectionList );
2411 * This method is called when the Actor is connected to the Stage.
2412 * The parent must have added its Node to the scene-graph.
2413 * The child must connect its Node to the parent's Node.
2414 * This is resursive; the child calls ConnectToStage() for its children.
2416 void Actor::ConnectToSceneGraph( int index )
2418 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2422 // Reparent Node in next Update
2423 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2426 // Notify attachment
2429 mAttachment->Connect();
2432 #ifdef DYNAMICS_SUPPORT
2434 if( NULL != mDynamicsData )
2440 // Request relayout on all actors that are added to the scenegraph
2443 // Notification for Object::Observers
2447 void Actor::NotifyStageConnection()
2449 // Actors can be removed (in a callback), before the on-stage stage is reported.
2450 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2451 if( OnStage() && !mOnStageSignalled )
2453 // Notification for external (CustomActor) derived classes
2454 OnStageConnectionExternal();
2456 if( !mOnStageSignal.Empty() )
2458 Dali::Actor handle( this );
2459 mOnStageSignal.Emit( handle );
2462 // Guard against Remove during callbacks
2465 mOnStageSignalled = true; // signal required next time Actor is removed
2470 void Actor::DisconnectFromStage()
2472 // This container is used instead of walking the Actor hierachy.
2473 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2474 ActorContainer disconnectionList;
2476 // This stage is atomic i.e. not interrupted by user callbacks
2477 RecursiveDisconnectFromStage( disconnectionList );
2479 // Notify applications about the newly disconnected actors.
2480 const ActorIter endIter = disconnectionList.end();
2481 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2483 Actor& actor = GetImplementation( *iter );
2484 actor.NotifyStageDisconnection();
2488 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2490 DALI_ASSERT_ALWAYS( OnStage() );
2492 // Recursively disconnect children
2495 ActorConstIter endIter = mChildren->end();
2496 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2498 Actor& actor = GetImplementation( *iter );
2499 actor.RecursiveDisconnectFromStage( disconnectionList );
2503 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2504 disconnectionList.push_back( Dali::Actor( this ) );
2506 // Notification for internal derived classes
2507 OnStageDisconnectionInternal();
2509 DisconnectFromSceneGraph();
2515 * This method is called by an actor or its parent, before a node removal message is sent.
2516 * This is recursive; the child calls DisconnectFromStage() for its children.
2518 void Actor::DisconnectFromSceneGraph()
2520 // Notification for Object::Observers
2521 OnSceneObjectRemove();
2523 // Notify attachment
2526 mAttachment->Disconnect();
2529 #ifdef DYNAMICS_SUPPORT
2531 if( NULL != mDynamicsData )
2533 DisconnectDynamics();
2538 void Actor::NotifyStageDisconnection()
2540 // Actors can be added (in a callback), before the off-stage state is reported.
2541 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2542 // only do this step if there is a stage, i.e. Core is not being shut down
2543 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2545 // Notification for external (CustomeActor) derived classes
2546 OnStageDisconnectionExternal();
2548 if( !mOffStageSignal.Empty() )
2550 Dali::Actor handle( this );
2551 mOffStageSignal.Emit( handle );
2554 // Guard against Add during callbacks
2557 mOnStageSignalled = false; // signal required next time Actor is added
2562 bool Actor::IsNodeConnected() const
2564 bool connected( false );
2569 if( mNode->IsRoot() || mNode->GetParent() )
2578 unsigned int Actor::GetDefaultPropertyCount() const
2580 return DEFAULT_PROPERTY_COUNT;
2583 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2585 indices.reserve( DEFAULT_PROPERTY_COUNT );
2587 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2589 indices.push_back( i );
2593 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2595 if( index < DEFAULT_PROPERTY_COUNT )
2597 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2603 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2605 Property::Index index = Property::INVALID_INDEX;
2607 // Look for name in default properties
2608 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2610 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2611 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2621 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2623 if( index < DEFAULT_PROPERTY_COUNT )
2625 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2631 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2633 if( index < DEFAULT_PROPERTY_COUNT )
2635 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2641 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2643 if( index < DEFAULT_PROPERTY_COUNT )
2645 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2651 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2653 if( index < DEFAULT_PROPERTY_COUNT )
2655 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2658 // index out of range...return Property::NONE
2659 return Property::NONE;
2662 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2666 case Dali::Actor::Property::PARENT_ORIGIN:
2668 SetParentOrigin( property.Get< Vector3 >() );
2672 case Dali::Actor::Property::PARENT_ORIGIN_X:
2674 SetParentOriginX( property.Get< float >() );
2678 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2680 SetParentOriginY( property.Get< float >() );
2684 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2686 SetParentOriginZ( property.Get< float >() );
2690 case Dali::Actor::Property::ANCHOR_POINT:
2692 SetAnchorPoint( property.Get< Vector3 >() );
2696 case Dali::Actor::Property::ANCHOR_POINT_X:
2698 SetAnchorPointX( property.Get< float >() );
2702 case Dali::Actor::Property::ANCHOR_POINT_Y:
2704 SetAnchorPointY( property.Get< float >() );
2708 case Dali::Actor::Property::ANCHOR_POINT_Z:
2710 SetAnchorPointZ( property.Get< float >() );
2714 case Dali::Actor::Property::SIZE:
2716 SetSize( property.Get< Vector3 >() );
2720 case Dali::Actor::Property::SIZE_WIDTH:
2722 SetWidth( property.Get< float >() );
2726 case Dali::Actor::Property::SIZE_HEIGHT:
2728 SetHeight( property.Get< float >() );
2732 case Dali::Actor::Property::SIZE_DEPTH:
2734 SetDepth( property.Get< float >() );
2738 case Dali::Actor::Property::POSITION:
2740 SetPosition( property.Get< Vector3 >() );
2744 case Dali::Actor::Property::POSITION_X:
2746 SetX( property.Get< float >() );
2750 case Dali::Actor::Property::POSITION_Y:
2752 SetY( property.Get< float >() );
2756 case Dali::Actor::Property::POSITION_Z:
2758 SetZ( property.Get< float >() );
2762 case Dali::Actor::Property::ORIENTATION:
2764 SetOrientation( property.Get< Quaternion >() );
2768 case Dali::Actor::Property::SCALE:
2770 SetScale( property.Get< Vector3 >() );
2774 case Dali::Actor::Property::SCALE_X:
2776 SetScaleX( property.Get< float >() );
2780 case Dali::Actor::Property::SCALE_Y:
2782 SetScaleY( property.Get< float >() );
2786 case Dali::Actor::Property::SCALE_Z:
2788 SetScaleZ( property.Get< float >() );
2792 case Dali::Actor::Property::VISIBLE:
2794 SetVisible( property.Get< bool >() );
2798 case Dali::Actor::Property::COLOR:
2800 SetColor( property.Get< Vector4 >() );
2804 case Dali::Actor::Property::COLOR_RED:
2806 SetColorRed( property.Get< float >() );
2810 case Dali::Actor::Property::COLOR_GREEN:
2812 SetColorGreen( property.Get< float >() );
2816 case Dali::Actor::Property::COLOR_BLUE:
2818 SetColorBlue( property.Get< float >() );
2822 case Dali::Actor::Property::COLOR_ALPHA:
2824 SetOpacity( property.Get< float >() );
2828 case Dali::Actor::Property::NAME:
2830 SetName( property.Get< std::string >() );
2834 case Dali::Actor::Property::SENSITIVE:
2836 SetSensitive( property.Get< bool >() );
2840 case Dali::Actor::Property::LEAVE_REQUIRED:
2842 SetLeaveRequired( property.Get< bool >() );
2846 case Dali::Actor::Property::INHERIT_ORIENTATION:
2848 SetInheritOrientation( property.Get< bool >() );
2852 case Dali::Actor::Property::INHERIT_SCALE:
2854 SetInheritScale( property.Get< bool >() );
2858 case Dali::Actor::Property::COLOR_MODE:
2860 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2864 case Dali::Actor::Property::POSITION_INHERITANCE:
2866 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2870 case Dali::Actor::Property::DRAW_MODE:
2872 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2876 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2878 SetSizeModeFactor( property.Get< Vector3 >() );
2882 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2884 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2888 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2890 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2894 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2896 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2900 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2902 if( property.Get< bool >() )
2904 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2909 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2911 if( property.Get< bool >() )
2913 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2918 case Dali::Actor::Property::PADDING:
2920 Vector4 padding = property.Get< Vector4 >();
2921 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2922 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2926 case Dali::Actor::Property::MINIMUM_SIZE:
2928 Vector2 size = property.Get< Vector2 >();
2929 SetMinimumSize( size.x, Dimension::WIDTH );
2930 SetMinimumSize( size.y, Dimension::HEIGHT );
2934 case Dali::Actor::Property::MAXIMUM_SIZE:
2936 Vector2 size = property.Get< Vector2 >();
2937 SetMaximumSize( size.x, Dimension::WIDTH );
2938 SetMaximumSize( size.y, Dimension::HEIGHT );
2944 // this can happen in the case of a non-animatable default property so just do nothing
2950 // TODO: This method needs to be removed
2951 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2953 switch( entry.type )
2955 case Property::BOOLEAN:
2957 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2958 DALI_ASSERT_DEBUG( NULL != property );
2960 // property is being used in a separate thread; queue a message to set the property
2961 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2966 case Property::INTEGER:
2968 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2969 DALI_ASSERT_DEBUG( NULL != property );
2971 // property is being used in a separate thread; queue a message to set the property
2972 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2977 case Property::UNSIGNED_INTEGER:
2979 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2980 DALI_ASSERT_DEBUG( NULL != property );
2982 // property is being used in a separate thread; queue a message to set the property
2983 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2988 case Property::FLOAT:
2990 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2991 DALI_ASSERT_DEBUG( NULL != property );
2993 // property is being used in a separate thread; queue a message to set the property
2994 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2999 case Property::VECTOR2:
3001 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3002 DALI_ASSERT_DEBUG( NULL != property );
3004 // property is being used in a separate thread; queue a message to set the property
3005 if(entry.componentIndex == 0)
3007 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3009 else if(entry.componentIndex == 1)
3011 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3015 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3021 case Property::VECTOR3:
3023 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3024 DALI_ASSERT_DEBUG( NULL != property );
3026 // property is being used in a separate thread; queue a message to set the property
3027 if(entry.componentIndex == 0)
3029 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3031 else if(entry.componentIndex == 1)
3033 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3035 else if(entry.componentIndex == 2)
3037 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3041 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3047 case Property::VECTOR4:
3049 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3050 DALI_ASSERT_DEBUG( NULL != property );
3052 // property is being used in a separate thread; queue a message to set the property
3053 if(entry.componentIndex == 0)
3055 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3057 else if(entry.componentIndex == 1)
3059 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3061 else if(entry.componentIndex == 2)
3063 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3065 else if(entry.componentIndex == 3)
3067 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3071 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3077 case Property::ROTATION:
3079 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( 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 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3088 case Property::MATRIX:
3090 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3091 DALI_ASSERT_DEBUG( NULL != property );
3093 // property is being used in a separate thread; queue a message to set the property
3094 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3099 case Property::MATRIX3:
3101 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3102 DALI_ASSERT_DEBUG( NULL != property );
3104 // property is being used in a separate thread; queue a message to set the property
3105 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3112 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3118 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3120 Property::Value value;
3124 case Dali::Actor::Property::PARENT_ORIGIN:
3126 value = GetCurrentParentOrigin();
3130 case Dali::Actor::Property::PARENT_ORIGIN_X:
3132 value = GetCurrentParentOrigin().x;
3136 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3138 value = GetCurrentParentOrigin().y;
3142 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3144 value = GetCurrentParentOrigin().z;
3148 case Dali::Actor::Property::ANCHOR_POINT:
3150 value = GetCurrentAnchorPoint();
3154 case Dali::Actor::Property::ANCHOR_POINT_X:
3156 value = GetCurrentAnchorPoint().x;
3160 case Dali::Actor::Property::ANCHOR_POINT_Y:
3162 value = GetCurrentAnchorPoint().y;
3166 case Dali::Actor::Property::ANCHOR_POINT_Z:
3168 value = GetCurrentAnchorPoint().z;
3172 case Dali::Actor::Property::SIZE:
3174 value = GetCurrentSize();
3178 case Dali::Actor::Property::SIZE_WIDTH:
3180 value = GetCurrentSize().width;
3184 case Dali::Actor::Property::SIZE_HEIGHT:
3186 value = GetCurrentSize().height;
3190 case Dali::Actor::Property::SIZE_DEPTH:
3192 value = GetCurrentSize().depth;
3196 case Dali::Actor::Property::POSITION:
3198 value = GetCurrentPosition();
3202 case Dali::Actor::Property::POSITION_X:
3204 value = GetCurrentPosition().x;
3208 case Dali::Actor::Property::POSITION_Y:
3210 value = GetCurrentPosition().y;
3214 case Dali::Actor::Property::POSITION_Z:
3216 value = GetCurrentPosition().z;
3220 case Dali::Actor::Property::WORLD_POSITION:
3222 value = GetCurrentWorldPosition();
3226 case Dali::Actor::Property::WORLD_POSITION_X:
3228 value = GetCurrentWorldPosition().x;
3232 case Dali::Actor::Property::WORLD_POSITION_Y:
3234 value = GetCurrentWorldPosition().y;
3238 case Dali::Actor::Property::WORLD_POSITION_Z:
3240 value = GetCurrentWorldPosition().z;
3244 case Dali::Actor::Property::ORIENTATION:
3246 value = GetCurrentOrientation();
3250 case Dali::Actor::Property::WORLD_ORIENTATION:
3252 value = GetCurrentWorldOrientation();
3256 case Dali::Actor::Property::SCALE:
3258 value = GetCurrentScale();
3262 case Dali::Actor::Property::SCALE_X:
3264 value = GetCurrentScale().x;
3268 case Dali::Actor::Property::SCALE_Y:
3270 value = GetCurrentScale().y;
3274 case Dali::Actor::Property::SCALE_Z:
3276 value = GetCurrentScale().z;
3280 case Dali::Actor::Property::WORLD_SCALE:
3282 value = GetCurrentWorldScale();
3286 case Dali::Actor::Property::VISIBLE:
3288 value = IsVisible();
3292 case Dali::Actor::Property::COLOR:
3294 value = GetCurrentColor();
3298 case Dali::Actor::Property::COLOR_RED:
3300 value = GetCurrentColor().r;
3304 case Dali::Actor::Property::COLOR_GREEN:
3306 value = GetCurrentColor().g;
3310 case Dali::Actor::Property::COLOR_BLUE:
3312 value = GetCurrentColor().b;
3316 case Dali::Actor::Property::COLOR_ALPHA:
3318 value = GetCurrentColor().a;
3322 case Dali::Actor::Property::WORLD_COLOR:
3324 value = GetCurrentWorldColor();
3328 case Dali::Actor::Property::WORLD_MATRIX:
3330 value = GetCurrentWorldMatrix();
3334 case Dali::Actor::Property::NAME:
3340 case Dali::Actor::Property::SENSITIVE:
3342 value = IsSensitive();
3346 case Dali::Actor::Property::LEAVE_REQUIRED:
3348 value = GetLeaveRequired();
3352 case Dali::Actor::Property::INHERIT_ORIENTATION:
3354 value = IsOrientationInherited();
3358 case Dali::Actor::Property::INHERIT_SCALE:
3360 value = IsScaleInherited();
3364 case Dali::Actor::Property::COLOR_MODE:
3366 value = Scripting::GetColorMode( GetColorMode() );
3370 case Dali::Actor::Property::POSITION_INHERITANCE:
3372 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3376 case Dali::Actor::Property::DRAW_MODE:
3378 value = Scripting::GetDrawMode( GetDrawMode() );
3382 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3384 value = GetSizeModeFactor();
3388 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3390 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3394 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3396 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3400 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3402 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3406 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3408 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3412 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3414 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3418 case Dali::Actor::Property::PADDING:
3420 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3421 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3422 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3426 case Dali::Actor::Property::MINIMUM_SIZE:
3428 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3432 case Dali::Actor::Property::MAXIMUM_SIZE:
3434 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3440 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3448 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3453 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3455 // This method should only return an object connected to the scene-graph
3456 return OnStage() ? mNode : NULL;
3459 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3461 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3463 const PropertyBase* property( NULL );
3465 // This method should only return a property of an object connected to the scene-graph
3471 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3473 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3474 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3476 property = animatable->GetSceneGraphProperty();
3478 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3480 CustomPropertyMetadata* custom = FindCustomProperty( index );
3481 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3483 property = custom->GetSceneGraphProperty();
3485 else if( NULL != mNode )
3489 case Dali::Actor::Property::SIZE:
3490 property = &mNode->mSize;
3493 case Dali::Actor::Property::SIZE_WIDTH:
3494 property = &mNode->mSize;
3497 case Dali::Actor::Property::SIZE_HEIGHT:
3498 property = &mNode->mSize;
3501 case Dali::Actor::Property::SIZE_DEPTH:
3502 property = &mNode->mSize;
3505 case Dali::Actor::Property::POSITION:
3506 property = &mNode->mPosition;
3509 case Dali::Actor::Property::POSITION_X:
3510 property = &mNode->mPosition;
3513 case Dali::Actor::Property::POSITION_Y:
3514 property = &mNode->mPosition;
3517 case Dali::Actor::Property::POSITION_Z:
3518 property = &mNode->mPosition;
3521 case Dali::Actor::Property::ORIENTATION:
3522 property = &mNode->mOrientation;
3525 case Dali::Actor::Property::SCALE:
3526 property = &mNode->mScale;
3529 case Dali::Actor::Property::SCALE_X:
3530 property = &mNode->mScale;
3533 case Dali::Actor::Property::SCALE_Y:
3534 property = &mNode->mScale;
3537 case Dali::Actor::Property::SCALE_Z:
3538 property = &mNode->mScale;
3541 case Dali::Actor::Property::VISIBLE:
3542 property = &mNode->mVisible;
3545 case Dali::Actor::Property::COLOR:
3546 property = &mNode->mColor;
3549 case Dali::Actor::Property::COLOR_RED:
3550 property = &mNode->mColor;
3553 case Dali::Actor::Property::COLOR_GREEN:
3554 property = &mNode->mColor;
3557 case Dali::Actor::Property::COLOR_BLUE:
3558 property = &mNode->mColor;
3561 case Dali::Actor::Property::COLOR_ALPHA:
3562 property = &mNode->mColor;
3573 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3575 const PropertyInputImpl* property( NULL );
3577 // This method should only return a property of an object connected to the scene-graph
3583 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3585 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3586 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3588 property = animatable->GetSceneGraphProperty();
3590 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3592 CustomPropertyMetadata* custom = FindCustomProperty( index );
3593 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3594 property = custom->GetSceneGraphProperty();
3596 else if( NULL != mNode )
3600 case Dali::Actor::Property::PARENT_ORIGIN:
3601 property = &mNode->mParentOrigin;
3604 case Dali::Actor::Property::PARENT_ORIGIN_X:
3605 property = &mNode->mParentOrigin;
3608 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3609 property = &mNode->mParentOrigin;
3612 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3613 property = &mNode->mParentOrigin;
3616 case Dali::Actor::Property::ANCHOR_POINT:
3617 property = &mNode->mAnchorPoint;
3620 case Dali::Actor::Property::ANCHOR_POINT_X:
3621 property = &mNode->mAnchorPoint;
3624 case Dali::Actor::Property::ANCHOR_POINT_Y:
3625 property = &mNode->mAnchorPoint;
3628 case Dali::Actor::Property::ANCHOR_POINT_Z:
3629 property = &mNode->mAnchorPoint;
3632 case Dali::Actor::Property::SIZE:
3633 property = &mNode->mSize;
3636 case Dali::Actor::Property::SIZE_WIDTH:
3637 property = &mNode->mSize;
3640 case Dali::Actor::Property::SIZE_HEIGHT:
3641 property = &mNode->mSize;
3644 case Dali::Actor::Property::SIZE_DEPTH:
3645 property = &mNode->mSize;
3648 case Dali::Actor::Property::POSITION:
3649 property = &mNode->mPosition;
3652 case Dali::Actor::Property::POSITION_X:
3653 property = &mNode->mPosition;
3656 case Dali::Actor::Property::POSITION_Y:
3657 property = &mNode->mPosition;
3660 case Dali::Actor::Property::POSITION_Z:
3661 property = &mNode->mPosition;
3664 case Dali::Actor::Property::WORLD_POSITION:
3665 property = &mNode->mWorldPosition;
3668 case Dali::Actor::Property::WORLD_POSITION_X:
3669 property = &mNode->mWorldPosition;
3672 case Dali::Actor::Property::WORLD_POSITION_Y:
3673 property = &mNode->mWorldPosition;
3676 case Dali::Actor::Property::WORLD_POSITION_Z:
3677 property = &mNode->mWorldPosition;
3680 case Dali::Actor::Property::ORIENTATION:
3681 property = &mNode->mOrientation;
3684 case Dali::Actor::Property::WORLD_ORIENTATION:
3685 property = &mNode->mWorldOrientation;
3688 case Dali::Actor::Property::SCALE:
3689 property = &mNode->mScale;
3692 case Dali::Actor::Property::SCALE_X:
3693 property = &mNode->mScale;
3696 case Dali::Actor::Property::SCALE_Y:
3697 property = &mNode->mScale;
3700 case Dali::Actor::Property::SCALE_Z:
3701 property = &mNode->mScale;
3704 case Dali::Actor::Property::WORLD_SCALE:
3705 property = &mNode->mWorldScale;
3708 case Dali::Actor::Property::VISIBLE:
3709 property = &mNode->mVisible;
3712 case Dali::Actor::Property::COLOR:
3713 property = &mNode->mColor;
3716 case Dali::Actor::Property::COLOR_RED:
3717 property = &mNode->mColor;
3720 case Dali::Actor::Property::COLOR_GREEN:
3721 property = &mNode->mColor;
3724 case Dali::Actor::Property::COLOR_BLUE:
3725 property = &mNode->mColor;
3728 case Dali::Actor::Property::COLOR_ALPHA:
3729 property = &mNode->mColor;
3732 case Dali::Actor::Property::WORLD_COLOR:
3733 property = &mNode->mWorldColor;
3736 case Dali::Actor::Property::WORLD_MATRIX:
3737 property = &mNode->mWorldMatrix;
3748 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3750 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3752 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3754 // check whether the animatable property is registered already, if not then register one.
3755 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3756 if( animatableProperty )
3758 componentIndex = animatableProperty->componentIndex;
3765 case Dali::Actor::Property::PARENT_ORIGIN_X:
3766 case Dali::Actor::Property::ANCHOR_POINT_X:
3767 case Dali::Actor::Property::SIZE_WIDTH:
3768 case Dali::Actor::Property::POSITION_X:
3769 case Dali::Actor::Property::WORLD_POSITION_X:
3770 case Dali::Actor::Property::SCALE_X:
3771 case Dali::Actor::Property::COLOR_RED:
3777 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3778 case Dali::Actor::Property::ANCHOR_POINT_Y:
3779 case Dali::Actor::Property::SIZE_HEIGHT:
3780 case Dali::Actor::Property::POSITION_Y:
3781 case Dali::Actor::Property::WORLD_POSITION_Y:
3782 case Dali::Actor::Property::SCALE_Y:
3783 case Dali::Actor::Property::COLOR_GREEN:
3789 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3790 case Dali::Actor::Property::ANCHOR_POINT_Z:
3791 case Dali::Actor::Property::SIZE_DEPTH:
3792 case Dali::Actor::Property::POSITION_Z:
3793 case Dali::Actor::Property::WORLD_POSITION_Z:
3794 case Dali::Actor::Property::SCALE_Z:
3795 case Dali::Actor::Property::COLOR_BLUE:
3801 case Dali::Actor::Property::COLOR_ALPHA:
3815 return componentIndex;
3818 void Actor::SetParent( Actor* parent, int index )
3822 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3826 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3829 // Instruct each actor to create a corresponding node in the scene graph
3830 ConnectToStage( index );
3833 else // parent being set to NULL
3835 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3839 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3842 DALI_ASSERT_ALWAYS( mNode != NULL );
3846 // Disconnect the Node & its children from the scene-graph.
3847 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3850 // Instruct each actor to discard pointers to the scene-graph
3851 DisconnectFromStage();
3856 SceneGraph::Node* Actor::CreateNode() const
3861 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3864 Actor* actor = dynamic_cast< Actor* >( object );
3868 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3870 actor->SetVisible( true );
3873 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3875 actor->SetVisible( false );
3883 void Actor::EnsureRelayoutData() const
3885 // Assign relayout data.
3886 if( !mRelayoutData )
3888 mRelayoutData = new RelayoutData();
3892 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3894 // Check if actor is dependent on parent
3895 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3897 if( ( dimension & ( 1 << i ) ) )
3899 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3900 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3910 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3912 // Check if actor is dependent on children
3913 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3915 if( ( dimension & ( 1 << i ) ) )
3917 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3918 switch( resizePolicy )
3920 case ResizePolicy::FIT_TO_CHILDREN:
3921 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3937 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3939 return Actor::RelayoutDependentOnChildren( dimension );
3942 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3944 // Check each possible dimension and see if it is dependent on the input one
3945 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3947 if( dimension & ( 1 << i ) )
3949 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3956 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3958 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3960 if( dimension & ( 1 << i ) )
3962 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3967 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3969 // If more than one dimension is requested, just return the first one found
3970 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3972 if( ( dimension & ( 1 << i ) ) )
3974 return mRelayoutData->negotiatedDimensions[ i ];
3978 return 0.0f; // Default
3981 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3983 EnsureRelayoutData();
3985 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3987 if( dimension & ( 1 << i ) )
3989 mRelayoutData->dimensionPadding[ i ] = padding;
3994 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3996 EnsureRelayoutData();
3998 // If more than one dimension is requested, just return the first one found
3999 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4001 if( ( dimension & ( 1 << i ) ) )
4003 return mRelayoutData->dimensionPadding[ i ];
4007 return Vector2( 0.0f, 0.0f ); // Default
4010 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4012 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4014 if( dimension & ( 1 << i ) )
4016 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4021 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4023 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4025 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4034 float Actor::GetHeightForWidthBase( float width )
4036 float height = 0.0f;
4038 const Vector3 naturalSize = GetNaturalSize();
4039 if( naturalSize.width > 0.0f )
4041 height = naturalSize.height * width / naturalSize.width;
4043 else // we treat 0 as 1:1 aspect ratio
4051 float Actor::GetWidthForHeightBase( float height )
4055 const Vector3 naturalSize = GetNaturalSize();
4056 if( naturalSize.height > 0.0f )
4058 width = naturalSize.width * height / naturalSize.height;
4060 else // we treat 0 as 1:1 aspect ratio
4068 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4070 // Fill to parent, taking size mode factor into account
4071 switch( child.GetResizePolicy( dimension ) )
4073 case ResizePolicy::FILL_TO_PARENT:
4075 return GetLatestSize( dimension );
4078 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4080 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4083 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4085 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4090 return GetLatestSize( dimension );
4095 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4097 // Can be overridden in derived class
4098 return CalculateChildSizeBase( child, dimension );
4101 float Actor::GetHeightForWidth( float width )
4103 // Can be overridden in derived class
4104 return GetHeightForWidthBase( width );
4107 float Actor::GetWidthForHeight( float height )
4109 // Can be overridden in derived class
4110 return GetWidthForHeightBase( height );
4113 float Actor::GetLatestSize( Dimension::Type dimension ) const
4115 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4118 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4120 Vector2 padding = GetPadding( dimension );
4122 return GetLatestSize( dimension ) + padding.x + padding.y;
4125 float Actor::NegotiateFromParent( Dimension::Type dimension )
4127 Actor* parent = GetParent();
4130 Vector2 padding( GetPadding( dimension ) );
4131 Vector2 parentPadding( parent->GetPadding( dimension ) );
4132 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4138 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4140 float maxDimensionPoint = 0.0f;
4142 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4144 Dali::Actor child = GetChildAt( i );
4145 Actor& childImpl = GetImplementation( child );
4147 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4149 // Calculate the min and max points that the children range across
4150 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4151 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4152 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4156 return maxDimensionPoint;
4159 float Actor::GetSize( Dimension::Type dimension ) const
4161 return GetDimensionValue( GetTargetSize(), dimension );
4164 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4166 return GetDimensionValue( GetNaturalSize(), dimension );
4169 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4171 switch( GetResizePolicy( dimension ) )
4173 case ResizePolicy::USE_NATURAL_SIZE:
4175 return GetNaturalSize( dimension );
4178 case ResizePolicy::FIXED:
4180 return GetDimensionValue( GetPreferredSize(), dimension );
4183 case ResizePolicy::USE_ASSIGNED_SIZE:
4185 return GetDimensionValue( maximumSize, dimension );
4188 case ResizePolicy::FILL_TO_PARENT:
4189 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4190 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4192 return NegotiateFromParent( dimension );
4195 case ResizePolicy::FIT_TO_CHILDREN:
4197 return NegotiateFromChildren( dimension );
4200 case ResizePolicy::DIMENSION_DEPENDENCY:
4202 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4205 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4207 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4210 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4212 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4224 return 0.0f; // Default
4227 float Actor::ClampDimension( float size, Dimension::Type dimension )
4229 const float minSize = GetMinimumSize( dimension );
4230 const float maxSize = GetMaximumSize( dimension );
4232 return std::max( minSize, std::min( size, maxSize ) );
4235 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4237 // Check if it needs to be negotiated
4238 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4240 // Check that we havn't gotten into an infinite loop
4241 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4242 bool recursionFound = false;
4243 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4245 if( *it == searchActor )
4247 recursionFound = true;
4252 if( !recursionFound )
4254 // Record the path that we have taken
4255 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4257 // Dimension dependency check
4258 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4260 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4262 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4264 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4268 // Parent dependency check
4269 Actor* parent = GetParent();
4270 if( parent && RelayoutDependentOnParent( dimension ) )
4272 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4275 // Children dependency check
4276 if( RelayoutDependentOnChildren( dimension ) )
4278 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4280 Dali::Actor child = GetChildAt( i );
4281 Actor& childImpl = GetImplementation( child );
4283 // Only relayout child first if it is not dependent on this actor
4284 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4286 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4291 // For deriving classes
4292 OnCalculateRelayoutSize( dimension );
4294 // All dependencies checked, calculate the size and set negotiated flag
4295 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4297 SetNegotiatedDimension( newSize, dimension );
4298 SetLayoutNegotiated( true, dimension );
4300 // For deriving classes
4301 OnLayoutNegotiated( newSize, dimension );
4303 // This actor has been successfully processed, pop it off the recursion stack
4304 recursionStack.pop_back();
4308 // TODO: Break infinite loop
4309 SetLayoutNegotiated( true, dimension );
4314 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4316 // Negotiate all dimensions that require it
4317 ActorDimensionStack recursionStack;
4319 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4321 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4324 NegotiateDimension( dimension, allocatedSize, recursionStack );
4328 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4330 switch( mRelayoutData->sizeSetPolicy )
4332 case SizeScalePolicy::USE_SIZE_SET:
4337 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4339 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4340 const Vector3 naturalSize = GetNaturalSize();
4341 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4343 const float sizeRatio = size.width / size.height;
4344 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4346 if( naturalSizeRatio < sizeRatio )
4348 return Vector2( naturalSizeRatio * size.height, size.height );
4350 else if( naturalSizeRatio > sizeRatio )
4352 return Vector2( size.width, size.width / naturalSizeRatio );
4363 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4365 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4366 const Vector3 naturalSize = GetNaturalSize();
4367 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4369 const float sizeRatio = size.width / size.height;
4370 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4372 if( naturalSizeRatio < sizeRatio )
4374 return Vector2( size.width, size.width / naturalSizeRatio );
4376 else if( naturalSizeRatio > sizeRatio )
4378 return Vector2( naturalSizeRatio * size.height, size.height );
4396 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4398 // Do the set actor size
4399 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4401 // Adjust for size set policy
4402 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4404 // Lock the flag to stop recursive relayouts on set size
4405 mRelayoutData->insideRelayout = true;
4406 SetSize( negotiatedSize );
4407 mRelayoutData->insideRelayout = false;
4409 // Clear flags for all dimensions
4410 SetLayoutDirty( false );
4412 // Give deriving classes a chance to respond
4413 OnRelayout( negotiatedSize, container );
4415 if( !mOnRelayoutSignal.Empty() )
4417 Dali::Actor handle( this );
4418 mOnRelayoutSignal.Emit( handle );
4422 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4424 // Do the negotiation
4425 NegotiateDimensions( allocatedSize );
4427 // Set the actor size
4428 SetNegotiatedSize( container );
4430 // Negotiate down to children
4431 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4433 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4435 Dali::Actor child = GetChildAt( i );
4437 // Only relayout if required
4438 if( GetImplementation( child ).RelayoutRequired() )
4440 container.Add( child, newBounds );
4445 void Actor::RelayoutRequest( Dimension::Type dimension )
4447 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4448 if( relayoutController )
4450 Dali::Actor self( this );
4451 relayoutController->RequestRelayout( self, dimension );
4455 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4459 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4463 void Actor::SetPreferredSize( const Vector2& size )
4465 EnsureRelayoutData();
4467 if( size.width > 0.0f )
4469 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4472 if( size.height > 0.0f )
4474 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4477 mRelayoutData->preferredSize = size;
4482 Vector2 Actor::GetPreferredSize() const
4484 EnsureRelayoutData();
4486 return mRelayoutData->preferredSize;
4489 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4491 EnsureRelayoutData();
4493 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4495 if( dimension & ( 1 << i ) )
4497 mRelayoutData->minimumSize[ i ] = size;
4504 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4506 EnsureRelayoutData();
4508 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4510 if( dimension & ( 1 << i ) )
4512 return mRelayoutData->minimumSize[ i ];
4516 return 0.0f; // Default
4519 void Actor::SetMaximumSize( 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->maximumSize[ i ] = size;
4534 float Actor::GetMaximumSize( 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->maximumSize[ i ];
4546 return 0.0f; // Default
4549 } // namespace Internal