2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/actor-attachments/renderer-attachment-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 #ifdef DALI_DYNAMICS_SUPPORT
58 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
61 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
64 using Dali::Internal::SceneGraph::Node;
65 using Dali::Internal::SceneGraph::AnimatableProperty;
66 using Dali::Internal::SceneGraph::PropertyBase;
70 namespace ResizePolicy
75 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
76 DALI_ENUM_TO_STRING( FIXED )
77 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
78 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
80 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
81 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
82 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
83 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
84 DALI_ENUM_TO_STRING_TABLE_END( Type )
86 } // unnamed namespace
89 namespace SizeScalePolicy
93 // Enumeration to / from string conversion tables
94 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
95 DALI_ENUM_TO_STRING( USE_SIZE_SET )
96 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
97 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
98 DALI_ENUM_TO_STRING_TABLE_END( Type )
99 } // unnamed namespace
105 unsigned int Actor::mActorCounter = 0;
109 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
110 inline const Vector3& GetDefaultSizeModeFactor()
115 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
116 inline const Vector2& GetDefaultPreferredSize()
118 return Vector2::ZERO;
121 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
122 inline const Vector2& GetDefaultDimensionPadding()
124 return Vector2::ZERO;
127 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
129 } // unnamed namespace
132 * Struct to collect relayout variables
134 struct Actor::RelayoutData
137 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
139 // Set size negotiation defaults
140 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
142 resizePolicies[ i ] = ResizePolicy::DEFAULT;
143 negotiatedDimensions[ i ] = 0.0f;
144 dimensionNegotiated[ i ] = false;
145 dimensionDirty[ i ] = false;
146 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
147 dimensionPadding[ i ] = GetDefaultDimensionPadding();
148 minimumSize[ i ] = 0.0f;
149 maximumSize[ i ] = FLT_MAX;
153 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
155 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
157 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
159 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
161 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
162 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
164 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
165 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
167 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
169 Vector2 preferredSize; ///< The preferred size of the actor
171 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
173 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
174 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
177 #ifdef DALI_DYNAMICS_SUPPORT
179 // Encapsulate actor related dynamics data
182 DynamicsData( Actor* slotOwner )
183 : slotDelegate( slotOwner )
187 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
188 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
190 DynamicsBodyPtr body;
191 JointContainer joints;
192 ReferencedJointContainer referencedJoints;
194 SlotDelegate< Actor > slotDelegate;
197 #endif // DALI_DYNAMICS_SUPPORT
199 namespace // unnamed namespace
205 * We want to discourage the use of property strings (minimize string comparisons),
206 * particularly for the default properties.
207 * Name Type writable animatable constraint-input enum for index-checking
209 DALI_PROPERTY_TABLE_BEGIN
210 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
211 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
212 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
213 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
214 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
215 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
216 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
217 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
218 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
219 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
220 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
221 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
222 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
223 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
224 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
225 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
226 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
227 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
228 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
229 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
230 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
231 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
232 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
233 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
234 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
235 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
236 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
237 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
238 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
239 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
240 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
241 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
242 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
243 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
244 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
245 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
246 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
247 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
248 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
249 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
250 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
251 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
252 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
253 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
254 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
255 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
256 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
257 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
258 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
259 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
260 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
261 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
262 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
266 const char* const SIGNAL_TOUCHED = "touched";
267 const char* const SIGNAL_HOVERED = "hovered";
268 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
269 const char* const SIGNAL_ON_STAGE = "on-stage";
270 const char* const SIGNAL_OFF_STAGE = "off-stage";
274 const char* const ACTION_SHOW = "show";
275 const char* const ACTION_HIDE = "hide";
277 BaseHandle CreateActor()
279 return Dali::Actor::New();
282 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
284 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
285 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
286 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
287 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
289 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
290 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
293 * @brief Extract a given dimension from a Vector2
295 * @param[in] values The values to extract from
296 * @param[in] dimension The dimension to extract
297 * @return Return the value for the dimension
299 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
303 case Dimension::WIDTH:
307 case Dimension::HEIGHT:
309 return values.height;
320 * @brief Extract a given dimension from a Vector3
322 * @param[in] values The values to extract from
323 * @param[in] dimension The dimension to extract
324 * @return Return the value for the dimension
326 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
328 return GetDimensionValue( values.GetVectorXY(), dimension );
332 } // unnamed namespace
334 ActorPtr Actor::New()
336 ActorPtr actor( new Actor( BASIC ) );
338 // Second-phase construction
344 const std::string& Actor::GetName() const
349 void Actor::SetName( const std::string& name )
355 // ATTENTION: string for debug purposes is not thread safe.
356 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
360 unsigned int Actor::GetId() const
365 void Actor::Attach( ActorAttachment& attachment )
367 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
371 attachment.Connect();
374 mAttachment = ActorAttachmentPtr( &attachment );
377 ActorAttachmentPtr Actor::GetAttachment()
382 bool Actor::OnStage() const
387 Dali::Layer Actor::GetLayer()
391 // Short-circuit for Layer derived actors
394 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
397 // Find the immediate Layer parent
398 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
400 if( parent->IsLayer() )
402 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
409 void Actor::Add( Actor& child )
411 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
412 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
416 mChildren = new ActorContainer;
419 Actor* const oldParent( child.mParent );
421 // child might already be ours
422 if( this != oldParent )
424 // if we already have parent, unparent us first
427 oldParent->Remove( child ); // This causes OnChildRemove callback
429 // Old parent may need to readjust to missing child
430 if( oldParent->RelayoutDependentOnChildren() )
432 oldParent->RelayoutRequest();
436 // Guard against Add() during previous OnChildRemove callback
439 // Do this first, since user callbacks from within SetParent() may need to remove child
440 mChildren->push_back( Dali::Actor( &child ) );
442 // SetParent asserts that child can be added
443 child.SetParent( this );
445 // Notification for derived classes
448 // Only put in a relayout request if there is a suitable dependency
449 if( RelayoutDependentOnChildren() )
457 void Actor::Insert( unsigned int index, Actor& child )
459 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
460 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
464 mChildren = new ActorContainer;
467 Actor* const oldParent( child.mParent );
469 // since an explicit position has been given, always insert, even if already a child
472 oldParent->Remove( child ); // This causes OnChildRemove callback
474 // Old parent may need to readjust to missing child
475 if( oldParent->RelayoutDependentOnChildren() )
477 oldParent->RelayoutRequest();
481 // Guard against Add() during previous OnChildRemove callback
484 // Do this first, since user callbacks from within SetParent() may need to remove child
485 if( index < GetChildCount() )
487 ActorIter it = mChildren->begin();
488 std::advance( it, index );
489 mChildren->insert( it, Dali::Actor( &child ) );
493 mChildren->push_back( Dali::Actor( &child ) );
495 // SetParent asserts that child can be added
496 child.SetParent( this, index );
498 // Notification for derived classes
501 // Only put in a relayout request if there is a suitable dependency
502 if( RelayoutDependentOnChildren() )
507 if( child.RelayoutDependentOnParent() )
509 child.RelayoutRequest();
514 void Actor::Remove( Actor& child )
516 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
526 // Find the child in mChildren, and unparent it
527 ActorIter end = mChildren->end();
528 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
530 Actor& actor = GetImplementation( *iter );
532 if( &actor == &child )
534 // Keep handle for OnChildRemove notification
535 removed = Dali::Actor( &actor );
537 // Do this first, since user callbacks from within SetParent() may need to add the child
538 mChildren->erase( iter );
540 DALI_ASSERT_DEBUG( actor.GetParent() == this );
541 actor.SetParent( NULL );
549 // Notification for derived classes
550 OnChildRemove( GetImplementation( removed ) );
552 // Only put in a relayout request if there is a suitable dependency
553 if( RelayoutDependentOnChildren() )
560 void Actor::Unparent()
564 // Remove this actor from the parent. The remove will put a relayout request in for
565 // the parent if required
566 mParent->Remove( *this );
567 // mParent is now NULL!
571 unsigned int Actor::GetChildCount() const
573 return ( NULL != mChildren ) ? mChildren->size() : 0;
576 Dali::Actor Actor::GetChildAt( unsigned int index ) const
578 DALI_ASSERT_ALWAYS( index < GetChildCount() );
580 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
583 ActorPtr Actor::FindChildByName( const std::string& actorName )
586 if( actorName == mName )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = GetImplementation( *iter ).FindChildByName( actorName );
606 ActorPtr Actor::FindChildById( const unsigned int id )
615 ActorIter end = mChildren->end();
616 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
618 child = GetImplementation( *iter ).FindChildById( id );
629 void Actor::SetParentOrigin( const Vector3& origin )
633 // mNode is being used in a separate thread; queue a message to set the value & base value
634 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
637 // Cache for event-thread access
640 // not allocated, check if different from default
641 if( ParentOrigin::DEFAULT != origin )
643 mParentOrigin = new Vector3( origin );
648 // check if different from current costs more than just set
649 *mParentOrigin = origin;
653 void Actor::SetParentOriginX( float x )
655 const Vector3& current = GetCurrentParentOrigin();
657 SetParentOrigin( Vector3( x, current.y, current.z ) );
660 void Actor::SetParentOriginY( float y )
662 const Vector3& current = GetCurrentParentOrigin();
664 SetParentOrigin( Vector3( current.x, y, current.z ) );
667 void Actor::SetParentOriginZ( float z )
669 const Vector3& current = GetCurrentParentOrigin();
671 SetParentOrigin( Vector3( current.x, current.y, z ) );
674 const Vector3& Actor::GetCurrentParentOrigin() const
676 // Cached for event-thread access
677 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
680 void Actor::SetAnchorPoint( const Vector3& anchor )
684 // mNode is being used in a separate thread; queue a message to set the value & base value
685 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
688 // Cache for event-thread access
691 // not allocated, check if different from default
692 if( AnchorPoint::DEFAULT != anchor )
694 mAnchorPoint = new Vector3( anchor );
699 // check if different from current costs more than just set
700 *mAnchorPoint = anchor;
704 void Actor::SetAnchorPointX( float x )
706 const Vector3& current = GetCurrentAnchorPoint();
708 SetAnchorPoint( Vector3( x, current.y, current.z ) );
711 void Actor::SetAnchorPointY( float y )
713 const Vector3& current = GetCurrentAnchorPoint();
715 SetAnchorPoint( Vector3( current.x, y, current.z ) );
718 void Actor::SetAnchorPointZ( float z )
720 const Vector3& current = GetCurrentAnchorPoint();
722 SetAnchorPoint( Vector3( current.x, current.y, z ) );
725 const Vector3& Actor::GetCurrentAnchorPoint() const
727 // Cached for event-thread access
728 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
731 void Actor::SetPosition( float x, float y )
733 SetPosition( Vector3( x, y, 0.0f ) );
736 void Actor::SetPosition( float x, float y, float z )
738 SetPosition( Vector3( x, y, z ) );
741 void Actor::SetPosition( const Vector3& position )
743 mTargetPosition = position;
747 // mNode is being used in a separate thread; queue a message to set the value & base value
748 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
752 void Actor::SetX( float x )
754 mTargetPosition.x = x;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
763 void Actor::SetY( float y )
765 mTargetPosition.y = y;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
774 void Actor::SetZ( float z )
776 mTargetPosition.z = z;
780 // mNode is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
785 void Actor::TranslateBy( const Vector3& distance )
787 mTargetPosition += distance;
791 // mNode is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
796 const Vector3& Actor::GetCurrentPosition() const
800 // mNode is being used in a separate thread; copy the value from the previous update
801 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
804 return Vector3::ZERO;
807 const Vector3& Actor::GetTargetPosition() const
809 return mTargetPosition;
812 const Vector3& Actor::GetCurrentWorldPosition() const
816 // mNode is being used in a separate thread; copy the value from the previous update
817 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
820 return Vector3::ZERO;
823 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
825 // this flag is not animatable so keep the value
826 mPositionInheritanceMode = mode;
829 // mNode is being used in a separate thread; queue a message to set the value
830 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
834 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
836 // Cached for event-thread access
837 return mPositionInheritanceMode;
840 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
842 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
843 normalizedAxis.Normalize();
845 Quaternion orientation( angle, normalizedAxis );
847 SetOrientation( orientation );
850 void Actor::SetOrientation( const Quaternion& orientation )
854 // mNode is being used in a separate thread; queue a message to set the value & base value
855 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
859 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
863 // mNode is being used in a separate thread; queue a message to set the value & base value
864 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
868 void Actor::RotateBy( const Quaternion& relativeRotation )
872 // mNode is being used in a separate thread; queue a message to set the value & base value
873 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
877 const Quaternion& Actor::GetCurrentOrientation() const
881 // mNode is being used in a separate thread; copy the value from the previous update
882 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
885 return Quaternion::IDENTITY;
888 const Quaternion& Actor::GetCurrentWorldOrientation() const
892 // mNode is being used in a separate thread; copy the value from the previous update
893 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
896 return Quaternion::IDENTITY;
899 void Actor::SetScale( float scale )
901 SetScale( Vector3( scale, scale, scale ) );
904 void Actor::SetScale( float x, float y, float z )
906 SetScale( Vector3( x, y, z ) );
909 void Actor::SetScale( const Vector3& scale )
913 // mNode is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
918 void Actor::SetScaleX( float x )
922 // mNode is being used in a separate thread; queue a message to set the value & base value
923 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
927 void Actor::SetScaleY( float y )
931 // mNode is being used in a separate thread; queue a message to set the value & base value
932 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
936 void Actor::SetScaleZ( float z )
940 // mNode is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
945 void Actor::ScaleBy(const Vector3& relativeScale)
949 // mNode is being used in a separate thread; queue a message to set the value & base value
950 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
954 const Vector3& Actor::GetCurrentScale() const
958 // mNode is being used in a separate thread; copy the value from the previous update
959 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
965 const Vector3& Actor::GetCurrentWorldScale() const
969 // mNode is being used in a separate thread; copy the value from the previous update
970 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
976 void Actor::SetInheritScale( bool inherit )
978 // non animateable so keep local copy
979 mInheritScale = inherit;
982 // mNode is being used in a separate thread; queue a message to set the value
983 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
987 bool Actor::IsScaleInherited() const
989 return mInheritScale;
992 Matrix Actor::GetCurrentWorldMatrix() const
996 // World matrix is no longer updated unless there is something observing the node.
997 // Need to calculate it from node's world position, orientation and scale:
998 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
999 Matrix worldMatrix(false);
1000 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1001 mNode->GetWorldOrientation( updateBufferIndex ),
1002 mNode->GetWorldPosition( updateBufferIndex ) );
1006 return Matrix::IDENTITY;
1009 void Actor::SetVisible( bool visible )
1013 // mNode is being used in a separate thread; queue a message to set the value & base value
1014 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1018 bool Actor::IsVisible() const
1022 // mNode is being used in a separate thread; copy the value from the previous update
1023 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1029 void Actor::SetOpacity( float opacity )
1033 // mNode is being used in a separate thread; queue a message to set the value & base value
1034 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1038 float Actor::GetCurrentOpacity() const
1042 // mNode is being used in a separate thread; copy the value from the previous update
1043 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1049 const Vector4& Actor::GetCurrentWorldColor() const
1053 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1056 return Color::WHITE;
1059 void Actor::SetColor( const Vector4& color )
1063 // mNode is being used in a separate thread; queue a message to set the value & base value
1064 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1068 void Actor::SetColorRed( float red )
1072 // mNode is being used in a separate thread; queue a message to set the value & base value
1073 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1077 void Actor::SetColorGreen( float green )
1081 // mNode is being used in a separate thread; queue a message to set the value & base value
1082 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1086 void Actor::SetColorBlue( float blue )
1090 // mNode is being used in a separate thread; queue a message to set the value & base value
1091 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1095 const Vector4& Actor::GetCurrentColor() const
1099 // mNode is being used in a separate thread; copy the value from the previous update
1100 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1103 return Color::WHITE;
1106 void Actor::SetInheritOrientation( bool inherit )
1108 // non animateable so keep local copy
1109 mInheritOrientation = inherit;
1112 // mNode is being used in a separate thread; queue a message to set the value
1113 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1117 bool Actor::IsOrientationInherited() const
1119 return mInheritOrientation;
1122 void Actor::SetSizeModeFactor( const Vector3& factor )
1124 EnsureRelayoutData();
1126 mRelayoutData->sizeModeFactor = factor;
1129 const Vector3& Actor::GetSizeModeFactor() const
1131 if ( mRelayoutData )
1133 return mRelayoutData->sizeModeFactor;
1136 return GetDefaultSizeModeFactor();
1139 void Actor::SetColorMode( ColorMode colorMode )
1141 // non animateable so keep local copy
1142 mColorMode = colorMode;
1145 // mNode is being used in a separate thread; queue a message to set the value
1146 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1150 ColorMode Actor::GetColorMode() const
1152 // we have cached copy
1156 void Actor::SetSize( float width, float height )
1158 SetSize( Vector2( width, height ) );
1161 void Actor::SetSize( float width, float height, float depth )
1163 SetSize( Vector3( width, height, depth ) );
1166 void Actor::SetSize( const Vector2& size )
1168 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1171 void Actor::SetSizeInternal( const Vector2& size )
1173 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1176 float Actor::CalculateSizeZ( const Vector2& size ) const
1178 return std::min( size.width, size.height );
1181 void Actor::SetSize( const Vector3& size )
1183 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1185 SetPreferredSize( size.GetVectorXY() );
1189 SetSizeInternal( size );
1193 void Actor::SetSizeInternal( const Vector3& size )
1195 // dont allow recursive loop
1196 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1197 // 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
1198 if( ( NULL != mNode )&&
1199 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1200 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1201 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1205 // mNode is being used in a separate thread; queue a message to set the value & base value
1206 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1208 // Notification for derived classes
1209 mInsideOnSizeSet = true;
1210 OnSizeSet( mTargetSize );
1211 mInsideOnSizeSet = false;
1213 // Raise a relayout request if the flag is not locked
1214 if( mRelayoutData && !mRelayoutData->insideRelayout )
1221 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1223 mTargetSize = targetSize;
1225 // Notify deriving classes
1226 OnSizeAnimation( animation, mTargetSize );
1229 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1231 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1233 mTargetSize.width = targetSize;
1235 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1237 mTargetSize.height = targetSize;
1239 // Notify deriving classes
1240 OnSizeAnimation( animation, mTargetSize );
1243 void Actor::SetWidth( float width )
1247 // mNode is being used in a separate thread; queue a message to set the value & base value
1248 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1252 void Actor::SetHeight( float height )
1256 // mNode is being used in a separate thread; queue a message to set the value & base value
1257 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1261 void Actor::SetDepth( float depth )
1265 // mNode is being used in a separate thread; queue a message to set the value & base value
1266 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1270 const Vector3& Actor::GetTargetSize() const
1275 const Vector3& Actor::GetCurrentSize() const
1279 // mNode is being used in a separate thread; copy the value from the previous update
1280 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1283 return Vector3::ZERO;
1286 Vector3 Actor::GetNaturalSize() const
1288 // It is up to deriving classes to return the appropriate natural size
1289 return Vector3( 0.0f, 0.0f, 0.0f );
1292 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1294 EnsureRelayoutData();
1296 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1298 if( dimension & ( 1 << i ) )
1300 mRelayoutData->resizePolicies[ i ] = policy;
1304 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1306 if( dimension & Dimension::WIDTH )
1308 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1311 if( dimension & Dimension::HEIGHT )
1313 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1317 // If calling SetResizePolicy, assume we want relayout enabled
1318 SetRelayoutEnabled( true );
1320 OnSetResizePolicy( policy, dimension );
1322 // Trigger relayout on this control
1326 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1328 if ( mRelayoutData )
1330 // If more than one dimension is requested, just return the first one found
1331 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1333 if( ( dimension & ( 1 << i ) ) )
1335 return mRelayoutData->resizePolicies[ i ];
1340 return ResizePolicy::DEFAULT;
1343 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1345 EnsureRelayoutData();
1347 mRelayoutData->sizeSetPolicy = policy;
1350 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1352 if ( mRelayoutData )
1354 return mRelayoutData->sizeSetPolicy;
1357 return DEFAULT_SIZE_SCALE_POLICY;
1360 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1362 EnsureRelayoutData();
1364 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1366 if( dimension & ( 1 << i ) )
1368 mRelayoutData->dimensionDependencies[ i ] = dependency;
1373 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1375 if ( mRelayoutData )
1377 // If more than one dimension is requested, just return the first one found
1378 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1380 if( ( dimension & ( 1 << i ) ) )
1382 return mRelayoutData->dimensionDependencies[ i ];
1387 return Dimension::ALL_DIMENSIONS; // Default
1390 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1392 // If relayout data has not been allocated yet and the client is requesting
1393 // to disable it, do nothing
1394 if( mRelayoutData || relayoutEnabled )
1396 EnsureRelayoutData();
1398 mRelayoutData->relayoutEnabled = relayoutEnabled;
1402 bool Actor::IsRelayoutEnabled() const
1404 // Assume that if relayout data has not been allocated yet then
1405 // relayout is disabled
1406 return mRelayoutData && mRelayoutData->relayoutEnabled;
1409 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1411 EnsureRelayoutData();
1413 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1415 if( dimension & ( 1 << i ) )
1417 mRelayoutData->dimensionDirty[ i ] = dirty;
1422 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1424 if ( mRelayoutData )
1426 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1428 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1438 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1440 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1443 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1445 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1448 unsigned int Actor::AddRenderer( Renderer& renderer )
1450 //TODO: MESH_REWORK : Add support for multiple renderers
1451 if ( ! mAttachment )
1453 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1459 unsigned int Actor::GetRendererCount() const
1461 //TODO: MESH_REWORK : Add support for multiple renderers
1462 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1463 return attachment ? 1u : 0u;
1466 Renderer& Actor::GetRendererAt( unsigned int index )
1468 //TODO: MESH_REWORK : Add support for multiple renderers
1469 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1471 //TODO: MESH_REWORK : Temporary code
1472 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1473 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1475 return attachment->GetRenderer();
1478 void Actor::RemoveRenderer( Renderer& renderer )
1480 //TODO: MESH_REWORK : Add support for multiple renderers
1484 void Actor::RemoveRenderer( unsigned int index )
1486 //TODO: MESH_REWORK : Add support for multiple renderers
1491 #ifdef DALI_DYNAMICS_SUPPORT
1493 //--------------- Dynamics ---------------
1495 void Actor::DisableDynamics()
1497 if( NULL != mDynamicsData )
1499 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1501 // ensure dynamics object are disconnected from scene
1502 DisconnectDynamics();
1504 // delete joint owned by this actor
1505 while( !mDynamicsData->joints.empty() )
1507 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1510 // delete other joints referencing this actor
1511 while( !mDynamicsData->referencedJoints.empty() )
1513 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1514 ActorPtr jointOwner( joint->GetActor( true ) );
1517 jointOwner->RemoveDynamicsJoint( joint );
1521 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1524 // delete the DynamicsBody object
1525 mDynamicsData->body.Reset();
1527 // Discard Dynamics data structure
1528 delete mDynamicsData;
1529 mDynamicsData = NULL;
1533 DynamicsBodyPtr Actor::GetDynamicsBody() const
1535 DynamicsBodyPtr body;
1537 if( NULL != mDynamicsData )
1539 body = mDynamicsData->body;
1545 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1547 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1549 if( NULL == mDynamicsData )
1551 mDynamicsData = new DynamicsData( this );
1554 if( !mDynamicsData->body )
1556 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1560 DynamicsWorldPtr world( DynamicsWorld::Get() );
1563 if( mParent == world->GetRootActor().Get() )
1565 mDynamicsData->body->Connect( GetEventThreadServices() );
1571 return mDynamicsData->body;
1574 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1576 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1577 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1580 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1582 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1583 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1585 DynamicsJointPtr joint;
1587 DynamicsWorldPtr world( DynamicsWorld::Get() );
1591 if( NULL != mDynamicsData )
1593 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1595 if( mDynamicsData->joints.end() != it )
1597 // use existing joint
1603 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1604 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1608 bodyA = EnableDynamics( new DynamicsBodyConfig );
1613 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1616 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1617 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1619 if( OnStage() && attachedActor->OnStage() )
1621 joint->Connect( GetEventThreadServices() );
1624 attachedActor->ReferenceJoint( joint );
1626 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1627 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1634 const int Actor::GetNumberOfJoints() const
1636 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1639 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1641 DynamicsJointPtr joint;
1643 if( NULL != mDynamicsData )
1645 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1647 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1649 for( int i = 0; i < index; ++i )
1661 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1663 DynamicsJointPtr joint;
1665 if( NULL != mDynamicsData )
1667 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1669 if( mDynamicsData->joints.end() != it )
1671 // use existing joint
1679 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1681 if( NULL != mDynamicsData )
1683 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1684 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1686 for(; it != endIt; ++it )
1688 if( it->second == joint.Get() )
1690 ActorPtr attachedActor( it->first );
1692 if( OnStage() && attachedActor && attachedActor->OnStage() )
1694 joint->Disconnect( GetEventThreadServices() );
1699 attachedActor->ReleaseJoint( joint );
1700 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1701 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1704 mDynamicsData->joints.erase(it);
1711 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1713 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1715 if( NULL != mDynamicsData )
1717 mDynamicsData->referencedJoints.push_back(joint);
1721 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1723 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1725 if( NULL != mDynamicsData )
1727 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1729 if( it != mDynamicsData->referencedJoints.end() )
1731 mDynamicsData->referencedJoints.erase( it );
1736 void Actor::SetDynamicsRoot(bool flag)
1738 if( mIsDynamicsRoot != flag )
1740 mIsDynamicsRoot = flag;
1742 if( OnStage() && mChildren )
1744 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1745 ActorIter end = mChildren->end();
1746 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1748 Actor& child = GetImplementation(*iter);
1750 if( child.GetDynamicsBody() )
1752 if( mIsDynamicsRoot )
1754 child.ConnectDynamics();
1758 child.DisconnectDynamics();
1766 bool Actor::IsDynamicsRoot() const
1768 return mIsDynamicsRoot;
1771 void Actor::AttachedActorOnStage( Dali::Actor actor )
1773 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1777 ActorPtr attachedActor( &GetImplementation(actor) );
1779 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1780 if( NULL != mDynamicsData )
1782 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1783 if( mDynamicsData->joints.end() != it )
1785 DynamicsJointPtr joint( it->second );
1786 joint->Connect( GetEventThreadServices() );
1792 void Actor::AttachedActorOffStage( Dali::Actor actor )
1794 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1798 ActorPtr attachedActor( &GetImplementation(actor) );
1800 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1801 if( NULL != mDynamicsData )
1803 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1804 if( mDynamicsData->joints.end() != it )
1806 DynamicsJointPtr joint( it->second );
1807 joint->Disconnect( GetEventThreadServices() );
1813 void Actor::ConnectDynamics()
1815 if( NULL != mDynamicsData && mDynamicsData->body )
1817 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1819 mDynamicsData->body->Connect( GetEventThreadServices() );
1821 // Connect all joints where attachedActor is also on stage
1822 if( !mDynamicsData->joints.empty() )
1824 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1825 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1827 for(; it != endIt; ++it )
1829 Actor* attachedActor( it->first );
1830 if( NULL != attachedActor && attachedActor->OnStage() )
1832 DynamicsJointPtr joint( it->second );
1834 joint->Connect( GetEventThreadServices() );
1842 void Actor::DisconnectDynamics()
1844 if( NULL != mDynamicsData && mDynamicsData->body )
1848 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1850 // Disconnect all joints
1851 if( !mDynamicsData->joints.empty() )
1853 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1854 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1856 for(; it != endIt; ++it )
1858 DynamicsJointPtr joint( it->second );
1860 joint->Disconnect( GetEventThreadServices() );
1867 #endif // DALI_DYNAMICS_SUPPORT
1869 void Actor::SetOverlay( bool enable )
1871 // Setting STENCIL will override OVERLAY
1872 if( DrawMode::STENCIL != mDrawMode )
1874 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1878 bool Actor::IsOverlay() const
1880 return ( DrawMode::OVERLAY == mDrawMode );
1883 void Actor::SetDrawMode( DrawMode::Type drawMode )
1885 // this flag is not animatable so keep the value
1886 mDrawMode = drawMode;
1889 // mNode is being used in a separate thread; queue a message to set the value
1890 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1894 DrawMode::Type Actor::GetDrawMode() const
1899 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1901 // only valid when on-stage
1902 StagePtr stage = Stage::GetCurrent();
1903 if( stage && OnStage() )
1905 const RenderTaskList& taskList = stage->GetRenderTaskList();
1907 Vector2 converted( screenX, screenY );
1909 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1910 const int taskCount = taskList.GetTaskCount();
1911 for( int i = taskCount - 1; i >= 0; --i )
1913 Dali::RenderTask task = taskList.GetTask( i );
1914 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1916 // found a task where this conversion was ok so return
1924 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1926 bool retval = false;
1927 // only valid when on-stage
1930 CameraActor* camera = renderTask.GetCameraActor();
1934 renderTask.GetViewport( viewport );
1936 // need to translate coordinates to render tasks coordinate space
1937 Vector2 converted( screenX, screenY );
1938 if( renderTask.TranslateCoordinates( converted ) )
1940 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1947 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1949 // Early-out if mNode is NULL
1955 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1957 // Calculate the ModelView matrix
1958 Matrix modelView( false/*don't init*/);
1959 // need to use the components as world matrix is only updated for actors that need it
1960 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1961 Matrix::Multiply( modelView, modelView, viewMatrix );
1963 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1964 Matrix invertedMvp( false/*don't init*/);
1965 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1966 bool success = invertedMvp.Invert();
1968 // Convert to GL coordinates
1969 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1974 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1981 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1987 if( XyPlaneIntersect( nearPos, farPos, local ) )
1989 Vector3 size = GetCurrentSize();
1990 localX = local.x + size.x * 0.5f;
1991 localY = local.y + size.y * 0.5f;
2002 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
2005 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
2007 Mathematical Formulation
2009 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
2011 ( p - c ) dot ( p - c ) = r^2
2013 Given a ray with a point of origin 'o', and a direction vector 'd':
2015 ray(t) = o + td, t >= 0
2017 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
2019 (o + td - c ) dot ( o + td - c ) = r^2
2021 To solve for t we first expand the above into a more recognisable quadratic equation form
2023 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
2032 B = 2( o - c ) dot d
2033 C = ( o - c ) dot ( o - c ) - r^2
2035 which can be solved using a standard quadratic formula.
2037 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
2039 Practical Simplification
2041 In a renderer, we often differentiate between world space and object space. In the object space
2042 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2043 into object space, the mathematical solution presented above can be simplified significantly.
2045 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2049 and we can find the t at which the (transformed) ray intersects the sphere by
2051 ( o + td ) dot ( o + td ) = r^2
2053 According to the reasoning above, we expand the above quadratic equation into the general form
2057 which now has coefficients:
2064 // Early out if mNode is NULL
2070 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2072 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2073 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2074 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2076 // Compute the radius is not needed, square radius it's enough.
2077 const Vector3& size( mNode->GetSize( bufferIndex ) );
2079 // Scale the sphere.
2080 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2082 const float width = size.width * scale.width;
2083 const float height = size.height * scale.height;
2085 float squareSphereRadius = 0.5f * ( width * width + height * height );
2087 float a = rayDir.Dot( rayDir ); // a
2088 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2089 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2091 return ( b2 * b2 - a * c ) >= 0.f;
2094 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2101 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2103 // Transforms the ray to the local reference system.
2105 // Calculate the inverse of Model matrix
2106 Matrix invModelMatrix( false/*don't init*/);
2107 // need to use the components as world matrix is only updated for actors that need it
2108 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2110 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2111 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2113 // Test with the actor's XY plane (Normal = 0 0 1 1).
2115 float a = -rayOriginLocal.z;
2116 float b = rayDirLocal.z;
2118 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2120 // Ray travels distance * rayDirLocal to intersect with plane.
2123 const Vector3& size = mNode->GetSize( bufferIndex );
2125 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2126 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2128 // Test with the actor's geometry.
2129 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2136 void Actor::SetLeaveRequired( bool required )
2138 mLeaveRequired = required;
2141 bool Actor::GetLeaveRequired() const
2143 return mLeaveRequired;
2146 void Actor::SetKeyboardFocusable( bool focusable )
2148 mKeyboardFocusable = focusable;
2151 bool Actor::IsKeyboardFocusable() const
2153 return mKeyboardFocusable;
2156 bool Actor::GetTouchRequired() const
2158 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2161 bool Actor::GetHoverRequired() const
2163 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2166 bool Actor::GetWheelEventRequired() const
2168 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2171 bool Actor::IsHittable() const
2173 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2176 ActorGestureData& Actor::GetGestureData()
2178 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2179 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2180 if( NULL == mGestureData )
2182 mGestureData = new ActorGestureData;
2184 return *mGestureData;
2187 bool Actor::IsGestureRequred( Gesture::Type type ) const
2189 return mGestureData && mGestureData->IsGestureRequred( type );
2192 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2194 bool consumed = false;
2196 if( !mTouchedSignal.Empty() )
2198 Dali::Actor handle( this );
2199 consumed = mTouchedSignal.Emit( handle, event );
2204 // Notification for derived classes
2205 consumed = OnTouchEvent( event );
2211 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2213 bool consumed = false;
2215 if( !mHoveredSignal.Empty() )
2217 Dali::Actor handle( this );
2218 consumed = mHoveredSignal.Emit( handle, event );
2223 // Notification for derived classes
2224 consumed = OnHoverEvent( event );
2230 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2232 bool consumed = false;
2234 if( !mWheelEventSignal.Empty() )
2236 Dali::Actor handle( this );
2237 consumed = mWheelEventSignal.Emit( handle, event );
2242 // Notification for derived classes
2243 consumed = OnWheelEvent( event );
2249 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2251 return mTouchedSignal;
2254 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2256 return mHoveredSignal;
2259 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2261 return mWheelEventSignal;
2264 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2266 return mOnStageSignal;
2269 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2271 return mOffStageSignal;
2274 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2276 return mOnRelayoutSignal;
2279 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2281 bool connected( true );
2282 Actor* actor = dynamic_cast< Actor* >( object );
2284 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2286 actor->TouchedSignal().Connect( tracker, functor );
2288 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2290 actor->HoveredSignal().Connect( tracker, functor );
2292 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2294 actor->WheelEventSignal().Connect( tracker, functor );
2296 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2298 actor->OnStageSignal().Connect( tracker, functor );
2300 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2302 actor->OffStageSignal().Connect( tracker, functor );
2306 // signalName does not match any signal
2313 Actor::Actor( DerivedType derivedType )
2317 mParentOrigin( NULL ),
2318 mAnchorPoint( NULL ),
2319 mRelayoutData( NULL ),
2320 #ifdef DALI_DYNAMICS_SUPPORT
2321 mDynamicsData( NULL ),
2323 mGestureData( NULL ),
2325 mTargetSize( 0.0f, 0.0f, 0.0f ),
2327 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2329 mIsRoot( ROOT_LAYER == derivedType ),
2330 mIsRenderable( RENDERABLE == derivedType ),
2331 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2332 mIsOnStage( false ),
2333 mIsDynamicsRoot( false ),
2335 mLeaveRequired( false ),
2336 mKeyboardFocusable( false ),
2337 mDerivedRequiresTouch( false ),
2338 mDerivedRequiresHover( false ),
2339 mDerivedRequiresWheelEvent( false ),
2340 mOnStageSignalled( false ),
2341 mInsideOnSizeSet( false ),
2342 mInheritOrientation( true ),
2343 mInheritScale( true ),
2344 mDrawMode( DrawMode::NORMAL ),
2345 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2346 mColorMode( Node::DEFAULT_COLOR_MODE )
2350 void Actor::Initialize()
2353 SceneGraph::Node* node = CreateNode();
2355 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2356 mNode = node; // Keep raw-pointer to Node
2360 GetEventThreadServices().RegisterObject( this );
2365 // Remove mParent pointers from children even if we're destroying core,
2366 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2369 ActorConstIter endIter = mChildren->end();
2370 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2372 Actor& actor = GetImplementation( *iter );
2373 actor.SetParent( NULL );
2378 // Guard to allow handle destruction after Core has been destroyed
2379 if( EventThreadServices::IsCoreRunning() )
2383 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2384 mNode = NULL; // Node is about to be destroyed
2387 GetEventThreadServices().UnregisterObject( this );
2390 #ifdef DALI_DYNAMICS_SUPPORT
2392 delete mDynamicsData;
2395 // Cleanup optional gesture data
2396 delete mGestureData;
2398 // Cleanup optional parent origin and anchor
2399 delete mParentOrigin;
2400 delete mAnchorPoint;
2402 // Delete optional relayout data
2405 delete mRelayoutData;
2409 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2411 // This container is used instead of walking the Actor hierachy.
2412 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2413 ActorContainer connectionList;
2416 // This stage is atomic i.e. not interrupted by user callbacks
2417 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2419 // Notify applications about the newly connected actors.
2420 const ActorIter endIter = connectionList.end();
2421 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2423 Actor& actor = GetImplementation( *iter );
2424 actor.NotifyStageConnection();
2430 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2432 DALI_ASSERT_ALWAYS( !OnStage() );
2437 ConnectToSceneGraph( index );
2439 // Notification for internal derived classes
2440 OnStageConnectionInternal();
2442 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2443 connectionList.push_back( Dali::Actor( this ) );
2445 // Recursively connect children
2448 ActorConstIter endIter = mChildren->end();
2449 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2451 Actor& actor = GetImplementation( *iter );
2452 actor.RecursiveConnectToStage( connectionList, depth+1 );
2458 * This method is called when the Actor is connected to the Stage.
2459 * The parent must have added its Node to the scene-graph.
2460 * The child must connect its Node to the parent's Node.
2461 * This is resursive; the child calls ConnectToStage() for its children.
2463 void Actor::ConnectToSceneGraph( int index )
2465 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2469 // Reparent Node in next Update
2470 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2473 // Notify attachment
2476 mAttachment->Connect();
2479 #ifdef DALI_DYNAMICS_SUPPORT
2481 if( NULL != mDynamicsData )
2487 // Request relayout on all actors that are added to the scenegraph
2490 // Notification for Object::Observers
2494 void Actor::NotifyStageConnection()
2496 // Actors can be removed (in a callback), before the on-stage stage is reported.
2497 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2498 if( OnStage() && !mOnStageSignalled )
2500 // Notification for external (CustomActor) derived classes
2501 OnStageConnectionExternal( mDepth );
2503 if( !mOnStageSignal.Empty() )
2505 Dali::Actor handle( this );
2506 mOnStageSignal.Emit( handle );
2509 // Guard against Remove during callbacks
2512 mOnStageSignalled = true; // signal required next time Actor is removed
2517 void Actor::DisconnectFromStage()
2519 // This container is used instead of walking the Actor hierachy.
2520 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2521 ActorContainer disconnectionList;
2523 // This stage is atomic i.e. not interrupted by user callbacks
2524 RecursiveDisconnectFromStage( disconnectionList );
2526 // Notify applications about the newly disconnected actors.
2527 const ActorIter endIter = disconnectionList.end();
2528 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2530 Actor& actor = GetImplementation( *iter );
2531 actor.NotifyStageDisconnection();
2535 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2537 DALI_ASSERT_ALWAYS( OnStage() );
2539 // Recursively disconnect children
2542 ActorConstIter endIter = mChildren->end();
2543 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2545 Actor& actor = GetImplementation( *iter );
2546 actor.RecursiveDisconnectFromStage( disconnectionList );
2550 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2551 disconnectionList.push_back( Dali::Actor( this ) );
2553 // Notification for internal derived classes
2554 OnStageDisconnectionInternal();
2556 DisconnectFromSceneGraph();
2562 * This method is called by an actor or its parent, before a node removal message is sent.
2563 * This is recursive; the child calls DisconnectFromStage() for its children.
2565 void Actor::DisconnectFromSceneGraph()
2567 // Notification for Object::Observers
2568 OnSceneObjectRemove();
2570 // Notify attachment
2573 mAttachment->Disconnect();
2576 #ifdef DALI_DYNAMICS_SUPPORT
2578 if( NULL != mDynamicsData )
2580 DisconnectDynamics();
2585 void Actor::NotifyStageDisconnection()
2587 // Actors can be added (in a callback), before the off-stage state is reported.
2588 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2589 // only do this step if there is a stage, i.e. Core is not being shut down
2590 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2592 // Notification for external (CustomeActor) derived classes
2593 OnStageDisconnectionExternal();
2595 if( !mOffStageSignal.Empty() )
2597 Dali::Actor handle( this );
2598 mOffStageSignal.Emit( handle );
2601 // Guard against Add during callbacks
2604 mOnStageSignalled = false; // signal required next time Actor is added
2609 bool Actor::IsNodeConnected() const
2611 bool connected( false );
2616 if( mNode->IsRoot() || mNode->GetParent() )
2625 unsigned int Actor::GetDefaultPropertyCount() const
2627 return DEFAULT_PROPERTY_COUNT;
2630 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2632 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2634 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2636 indices.PushBack( i );
2640 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2642 if( index < DEFAULT_PROPERTY_COUNT )
2644 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2650 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2652 Property::Index index = Property::INVALID_INDEX;
2654 // Look for name in default properties
2655 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2657 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2658 if( 0 == name.compare( property->name ) )
2668 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2670 if( index < DEFAULT_PROPERTY_COUNT )
2672 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2678 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2680 if( index < DEFAULT_PROPERTY_COUNT )
2682 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2688 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2690 if( index < DEFAULT_PROPERTY_COUNT )
2692 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2698 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2700 if( index < DEFAULT_PROPERTY_COUNT )
2702 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2705 // index out of range...return Property::NONE
2706 return Property::NONE;
2709 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2713 case Dali::Actor::Property::PARENT_ORIGIN:
2715 SetParentOrigin( property.Get< Vector3 >() );
2719 case Dali::Actor::Property::PARENT_ORIGIN_X:
2721 SetParentOriginX( property.Get< float >() );
2725 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2727 SetParentOriginY( property.Get< float >() );
2731 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2733 SetParentOriginZ( property.Get< float >() );
2737 case Dali::Actor::Property::ANCHOR_POINT:
2739 SetAnchorPoint( property.Get< Vector3 >() );
2743 case Dali::Actor::Property::ANCHOR_POINT_X:
2745 SetAnchorPointX( property.Get< float >() );
2749 case Dali::Actor::Property::ANCHOR_POINT_Y:
2751 SetAnchorPointY( property.Get< float >() );
2755 case Dali::Actor::Property::ANCHOR_POINT_Z:
2757 SetAnchorPointZ( property.Get< float >() );
2761 case Dali::Actor::Property::SIZE:
2763 SetSize( property.Get< Vector3 >() );
2767 case Dali::Actor::Property::SIZE_WIDTH:
2769 SetWidth( property.Get< float >() );
2773 case Dali::Actor::Property::SIZE_HEIGHT:
2775 SetHeight( property.Get< float >() );
2779 case Dali::Actor::Property::SIZE_DEPTH:
2781 SetDepth( property.Get< float >() );
2785 case Dali::Actor::Property::POSITION:
2787 SetPosition( property.Get< Vector3 >() );
2791 case Dali::Actor::Property::POSITION_X:
2793 SetX( property.Get< float >() );
2797 case Dali::Actor::Property::POSITION_Y:
2799 SetY( property.Get< float >() );
2803 case Dali::Actor::Property::POSITION_Z:
2805 SetZ( property.Get< float >() );
2809 case Dali::Actor::Property::ORIENTATION:
2811 SetOrientation( property.Get< Quaternion >() );
2815 case Dali::Actor::Property::SCALE:
2817 SetScale( property.Get< Vector3 >() );
2821 case Dali::Actor::Property::SCALE_X:
2823 SetScaleX( property.Get< float >() );
2827 case Dali::Actor::Property::SCALE_Y:
2829 SetScaleY( property.Get< float >() );
2833 case Dali::Actor::Property::SCALE_Z:
2835 SetScaleZ( property.Get< float >() );
2839 case Dali::Actor::Property::VISIBLE:
2841 SetVisible( property.Get< bool >() );
2845 case Dali::Actor::Property::COLOR:
2847 SetColor( property.Get< Vector4 >() );
2851 case Dali::Actor::Property::COLOR_RED:
2853 SetColorRed( property.Get< float >() );
2857 case Dali::Actor::Property::COLOR_GREEN:
2859 SetColorGreen( property.Get< float >() );
2863 case Dali::Actor::Property::COLOR_BLUE:
2865 SetColorBlue( property.Get< float >() );
2869 case Dali::Actor::Property::COLOR_ALPHA:
2871 SetOpacity( property.Get< float >() );
2875 case Dali::Actor::Property::NAME:
2877 SetName( property.Get< std::string >() );
2881 case Dali::Actor::Property::SENSITIVE:
2883 SetSensitive( property.Get< bool >() );
2887 case Dali::Actor::Property::LEAVE_REQUIRED:
2889 SetLeaveRequired( property.Get< bool >() );
2893 case Dali::Actor::Property::INHERIT_ORIENTATION:
2895 SetInheritOrientation( property.Get< bool >() );
2899 case Dali::Actor::Property::INHERIT_SCALE:
2901 SetInheritScale( property.Get< bool >() );
2905 case Dali::Actor::Property::COLOR_MODE:
2907 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2911 case Dali::Actor::Property::POSITION_INHERITANCE:
2913 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2917 case Dali::Actor::Property::DRAW_MODE:
2919 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2923 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2925 SetSizeModeFactor( property.Get< Vector3 >() );
2929 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2931 ResizePolicy::Type type;
2932 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2934 SetResizePolicy( type, Dimension::WIDTH );
2939 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2941 ResizePolicy::Type type;
2942 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2944 SetResizePolicy( type, Dimension::HEIGHT );
2949 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2951 SizeScalePolicy::Type type;
2952 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2954 SetSizeScalePolicy( type );
2959 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2961 if( property.Get< bool >() )
2963 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2968 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2970 if( property.Get< bool >() )
2972 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2977 case Dali::Actor::Property::PADDING:
2979 Vector4 padding = property.Get< Vector4 >();
2980 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2981 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2985 case Dali::Actor::Property::MINIMUM_SIZE:
2987 Vector2 size = property.Get< Vector2 >();
2988 SetMinimumSize( size.x, Dimension::WIDTH );
2989 SetMinimumSize( size.y, Dimension::HEIGHT );
2993 case Dali::Actor::Property::MAXIMUM_SIZE:
2995 Vector2 size = property.Get< Vector2 >();
2996 SetMaximumSize( size.x, Dimension::WIDTH );
2997 SetMaximumSize( size.y, Dimension::HEIGHT );
3003 // this can happen in the case of a non-animatable default property so just do nothing
3009 // TODO: This method needs to be removed
3010 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3012 switch( entry.type )
3014 case Property::BOOLEAN:
3016 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3017 DALI_ASSERT_DEBUG( NULL != property );
3019 // property is being used in a separate thread; queue a message to set the property
3020 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3025 case Property::INTEGER:
3027 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3028 DALI_ASSERT_DEBUG( NULL != property );
3030 // property is being used in a separate thread; queue a message to set the property
3031 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3036 case Property::UNSIGNED_INTEGER:
3038 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
3039 DALI_ASSERT_DEBUG( NULL != property );
3041 // property is being used in a separate thread; queue a message to set the property
3042 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3047 case Property::FLOAT:
3049 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3058 case Property::VECTOR2:
3060 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3061 DALI_ASSERT_DEBUG( NULL != property );
3063 // property is being used in a separate thread; queue a message to set the property
3064 if(entry.componentIndex == 0)
3066 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3068 else if(entry.componentIndex == 1)
3070 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3074 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3080 case Property::VECTOR3:
3082 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3083 DALI_ASSERT_DEBUG( NULL != property );
3085 // property is being used in a separate thread; queue a message to set the property
3086 if(entry.componentIndex == 0)
3088 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3090 else if(entry.componentIndex == 1)
3092 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3094 else if(entry.componentIndex == 2)
3096 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3100 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3106 case Property::VECTOR4:
3108 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3109 DALI_ASSERT_DEBUG( NULL != property );
3111 // property is being used in a separate thread; queue a message to set the property
3112 if(entry.componentIndex == 0)
3114 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3116 else if(entry.componentIndex == 1)
3118 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3120 else if(entry.componentIndex == 2)
3122 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3124 else if(entry.componentIndex == 3)
3126 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3130 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3136 case Property::ROTATION:
3138 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3139 DALI_ASSERT_DEBUG( NULL != property );
3141 // property is being used in a separate thread; queue a message to set the property
3142 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3147 case Property::MATRIX:
3149 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3150 DALI_ASSERT_DEBUG( NULL != property );
3152 // property is being used in a separate thread; queue a message to set the property
3153 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3158 case Property::MATRIX3:
3160 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3161 DALI_ASSERT_DEBUG( NULL != property );
3163 // property is being used in a separate thread; queue a message to set the property
3164 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3171 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3177 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3179 Property::Value value;
3183 case Dali::Actor::Property::PARENT_ORIGIN:
3185 value = GetCurrentParentOrigin();
3189 case Dali::Actor::Property::PARENT_ORIGIN_X:
3191 value = GetCurrentParentOrigin().x;
3195 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3197 value = GetCurrentParentOrigin().y;
3201 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3203 value = GetCurrentParentOrigin().z;
3207 case Dali::Actor::Property::ANCHOR_POINT:
3209 value = GetCurrentAnchorPoint();
3213 case Dali::Actor::Property::ANCHOR_POINT_X:
3215 value = GetCurrentAnchorPoint().x;
3219 case Dali::Actor::Property::ANCHOR_POINT_Y:
3221 value = GetCurrentAnchorPoint().y;
3225 case Dali::Actor::Property::ANCHOR_POINT_Z:
3227 value = GetCurrentAnchorPoint().z;
3231 case Dali::Actor::Property::SIZE:
3233 value = GetCurrentSize();
3237 case Dali::Actor::Property::SIZE_WIDTH:
3239 value = GetCurrentSize().width;
3243 case Dali::Actor::Property::SIZE_HEIGHT:
3245 value = GetCurrentSize().height;
3249 case Dali::Actor::Property::SIZE_DEPTH:
3251 value = GetCurrentSize().depth;
3255 case Dali::Actor::Property::POSITION:
3257 value = GetCurrentPosition();
3261 case Dali::Actor::Property::POSITION_X:
3263 value = GetCurrentPosition().x;
3267 case Dali::Actor::Property::POSITION_Y:
3269 value = GetCurrentPosition().y;
3273 case Dali::Actor::Property::POSITION_Z:
3275 value = GetCurrentPosition().z;
3279 case Dali::Actor::Property::WORLD_POSITION:
3281 value = GetCurrentWorldPosition();
3285 case Dali::Actor::Property::WORLD_POSITION_X:
3287 value = GetCurrentWorldPosition().x;
3291 case Dali::Actor::Property::WORLD_POSITION_Y:
3293 value = GetCurrentWorldPosition().y;
3297 case Dali::Actor::Property::WORLD_POSITION_Z:
3299 value = GetCurrentWorldPosition().z;
3303 case Dali::Actor::Property::ORIENTATION:
3305 value = GetCurrentOrientation();
3309 case Dali::Actor::Property::WORLD_ORIENTATION:
3311 value = GetCurrentWorldOrientation();
3315 case Dali::Actor::Property::SCALE:
3317 value = GetCurrentScale();
3321 case Dali::Actor::Property::SCALE_X:
3323 value = GetCurrentScale().x;
3327 case Dali::Actor::Property::SCALE_Y:
3329 value = GetCurrentScale().y;
3333 case Dali::Actor::Property::SCALE_Z:
3335 value = GetCurrentScale().z;
3339 case Dali::Actor::Property::WORLD_SCALE:
3341 value = GetCurrentWorldScale();
3345 case Dali::Actor::Property::VISIBLE:
3347 value = IsVisible();
3351 case Dali::Actor::Property::COLOR:
3353 value = GetCurrentColor();
3357 case Dali::Actor::Property::COLOR_RED:
3359 value = GetCurrentColor().r;
3363 case Dali::Actor::Property::COLOR_GREEN:
3365 value = GetCurrentColor().g;
3369 case Dali::Actor::Property::COLOR_BLUE:
3371 value = GetCurrentColor().b;
3375 case Dali::Actor::Property::COLOR_ALPHA:
3377 value = GetCurrentColor().a;
3381 case Dali::Actor::Property::WORLD_COLOR:
3383 value = GetCurrentWorldColor();
3387 case Dali::Actor::Property::WORLD_MATRIX:
3389 value = GetCurrentWorldMatrix();
3393 case Dali::Actor::Property::NAME:
3399 case Dali::Actor::Property::SENSITIVE:
3401 value = IsSensitive();
3405 case Dali::Actor::Property::LEAVE_REQUIRED:
3407 value = GetLeaveRequired();
3411 case Dali::Actor::Property::INHERIT_ORIENTATION:
3413 value = IsOrientationInherited();
3417 case Dali::Actor::Property::INHERIT_SCALE:
3419 value = IsScaleInherited();
3423 case Dali::Actor::Property::COLOR_MODE:
3425 value = Scripting::GetColorMode( GetColorMode() );
3429 case Dali::Actor::Property::POSITION_INHERITANCE:
3431 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3435 case Dali::Actor::Property::DRAW_MODE:
3437 value = Scripting::GetDrawMode( GetDrawMode() );
3441 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3443 value = GetSizeModeFactor();
3447 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3449 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3453 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3455 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3459 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3461 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3465 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3467 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3471 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3473 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3477 case Dali::Actor::Property::PADDING:
3479 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3480 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3481 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3485 case Dali::Actor::Property::MINIMUM_SIZE:
3487 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3491 case Dali::Actor::Property::MAXIMUM_SIZE:
3493 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3499 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3507 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3512 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3514 // This method should only return an object connected to the scene-graph
3515 return OnStage() ? mNode : NULL;
3518 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3520 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3522 const PropertyBase* property( NULL );
3524 // This method should only return a property of an object connected to the scene-graph
3530 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3532 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3533 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3535 property = animatable->GetSceneGraphProperty();
3537 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3539 CustomPropertyMetadata* custom = FindCustomProperty( index );
3540 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3542 property = custom->GetSceneGraphProperty();
3544 else if( NULL != mNode )
3548 case Dali::Actor::Property::SIZE:
3549 property = &mNode->mSize;
3552 case Dali::Actor::Property::SIZE_WIDTH:
3553 property = &mNode->mSize;
3556 case Dali::Actor::Property::SIZE_HEIGHT:
3557 property = &mNode->mSize;
3560 case Dali::Actor::Property::SIZE_DEPTH:
3561 property = &mNode->mSize;
3564 case Dali::Actor::Property::POSITION:
3565 property = &mNode->mPosition;
3568 case Dali::Actor::Property::POSITION_X:
3569 property = &mNode->mPosition;
3572 case Dali::Actor::Property::POSITION_Y:
3573 property = &mNode->mPosition;
3576 case Dali::Actor::Property::POSITION_Z:
3577 property = &mNode->mPosition;
3580 case Dali::Actor::Property::ORIENTATION:
3581 property = &mNode->mOrientation;
3584 case Dali::Actor::Property::SCALE:
3585 property = &mNode->mScale;
3588 case Dali::Actor::Property::SCALE_X:
3589 property = &mNode->mScale;
3592 case Dali::Actor::Property::SCALE_Y:
3593 property = &mNode->mScale;
3596 case Dali::Actor::Property::SCALE_Z:
3597 property = &mNode->mScale;
3600 case Dali::Actor::Property::VISIBLE:
3601 property = &mNode->mVisible;
3604 case Dali::Actor::Property::COLOR:
3605 property = &mNode->mColor;
3608 case Dali::Actor::Property::COLOR_RED:
3609 property = &mNode->mColor;
3612 case Dali::Actor::Property::COLOR_GREEN:
3613 property = &mNode->mColor;
3616 case Dali::Actor::Property::COLOR_BLUE:
3617 property = &mNode->mColor;
3620 case Dali::Actor::Property::COLOR_ALPHA:
3621 property = &mNode->mColor;
3632 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3634 const PropertyInputImpl* property( NULL );
3636 // This method should only return a property of an object connected to the scene-graph
3642 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3644 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3645 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3647 property = animatable->GetSceneGraphProperty();
3649 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3651 CustomPropertyMetadata* custom = FindCustomProperty( index );
3652 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3653 property = custom->GetSceneGraphProperty();
3655 else if( NULL != mNode )
3659 case Dali::Actor::Property::PARENT_ORIGIN:
3660 property = &mNode->mParentOrigin;
3663 case Dali::Actor::Property::PARENT_ORIGIN_X:
3664 property = &mNode->mParentOrigin;
3667 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3668 property = &mNode->mParentOrigin;
3671 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3672 property = &mNode->mParentOrigin;
3675 case Dali::Actor::Property::ANCHOR_POINT:
3676 property = &mNode->mAnchorPoint;
3679 case Dali::Actor::Property::ANCHOR_POINT_X:
3680 property = &mNode->mAnchorPoint;
3683 case Dali::Actor::Property::ANCHOR_POINT_Y:
3684 property = &mNode->mAnchorPoint;
3687 case Dali::Actor::Property::ANCHOR_POINT_Z:
3688 property = &mNode->mAnchorPoint;
3691 case Dali::Actor::Property::SIZE:
3692 property = &mNode->mSize;
3695 case Dali::Actor::Property::SIZE_WIDTH:
3696 property = &mNode->mSize;
3699 case Dali::Actor::Property::SIZE_HEIGHT:
3700 property = &mNode->mSize;
3703 case Dali::Actor::Property::SIZE_DEPTH:
3704 property = &mNode->mSize;
3707 case Dali::Actor::Property::POSITION:
3708 property = &mNode->mPosition;
3711 case Dali::Actor::Property::POSITION_X:
3712 property = &mNode->mPosition;
3715 case Dali::Actor::Property::POSITION_Y:
3716 property = &mNode->mPosition;
3719 case Dali::Actor::Property::POSITION_Z:
3720 property = &mNode->mPosition;
3723 case Dali::Actor::Property::WORLD_POSITION:
3724 property = &mNode->mWorldPosition;
3727 case Dali::Actor::Property::WORLD_POSITION_X:
3728 property = &mNode->mWorldPosition;
3731 case Dali::Actor::Property::WORLD_POSITION_Y:
3732 property = &mNode->mWorldPosition;
3735 case Dali::Actor::Property::WORLD_POSITION_Z:
3736 property = &mNode->mWorldPosition;
3739 case Dali::Actor::Property::ORIENTATION:
3740 property = &mNode->mOrientation;
3743 case Dali::Actor::Property::WORLD_ORIENTATION:
3744 property = &mNode->mWorldOrientation;
3747 case Dali::Actor::Property::SCALE:
3748 property = &mNode->mScale;
3751 case Dali::Actor::Property::SCALE_X:
3752 property = &mNode->mScale;
3755 case Dali::Actor::Property::SCALE_Y:
3756 property = &mNode->mScale;
3759 case Dali::Actor::Property::SCALE_Z:
3760 property = &mNode->mScale;
3763 case Dali::Actor::Property::WORLD_SCALE:
3764 property = &mNode->mWorldScale;
3767 case Dali::Actor::Property::VISIBLE:
3768 property = &mNode->mVisible;
3771 case Dali::Actor::Property::COLOR:
3772 property = &mNode->mColor;
3775 case Dali::Actor::Property::COLOR_RED:
3776 property = &mNode->mColor;
3779 case Dali::Actor::Property::COLOR_GREEN:
3780 property = &mNode->mColor;
3783 case Dali::Actor::Property::COLOR_BLUE:
3784 property = &mNode->mColor;
3787 case Dali::Actor::Property::COLOR_ALPHA:
3788 property = &mNode->mColor;
3791 case Dali::Actor::Property::WORLD_COLOR:
3792 property = &mNode->mWorldColor;
3795 case Dali::Actor::Property::WORLD_MATRIX:
3796 property = &mNode->mWorldMatrix;
3807 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3809 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3811 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3813 // check whether the animatable property is registered already, if not then register one.
3814 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3815 if( animatableProperty )
3817 componentIndex = animatableProperty->componentIndex;
3824 case Dali::Actor::Property::PARENT_ORIGIN_X:
3825 case Dali::Actor::Property::ANCHOR_POINT_X:
3826 case Dali::Actor::Property::SIZE_WIDTH:
3827 case Dali::Actor::Property::POSITION_X:
3828 case Dali::Actor::Property::WORLD_POSITION_X:
3829 case Dali::Actor::Property::SCALE_X:
3830 case Dali::Actor::Property::COLOR_RED:
3836 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3837 case Dali::Actor::Property::ANCHOR_POINT_Y:
3838 case Dali::Actor::Property::SIZE_HEIGHT:
3839 case Dali::Actor::Property::POSITION_Y:
3840 case Dali::Actor::Property::WORLD_POSITION_Y:
3841 case Dali::Actor::Property::SCALE_Y:
3842 case Dali::Actor::Property::COLOR_GREEN:
3848 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3849 case Dali::Actor::Property::ANCHOR_POINT_Z:
3850 case Dali::Actor::Property::SIZE_DEPTH:
3851 case Dali::Actor::Property::POSITION_Z:
3852 case Dali::Actor::Property::WORLD_POSITION_Z:
3853 case Dali::Actor::Property::SCALE_Z:
3854 case Dali::Actor::Property::COLOR_BLUE:
3860 case Dali::Actor::Property::COLOR_ALPHA:
3874 return componentIndex;
3877 void Actor::SetParent( Actor* parent, int index )
3881 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3885 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3888 // Instruct each actor to create a corresponding node in the scene graph
3889 ConnectToStage( parent->GetDepth(), index );
3892 else // parent being set to NULL
3894 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3898 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3901 DALI_ASSERT_ALWAYS( mNode != NULL );
3905 // Disconnect the Node & its children from the scene-graph.
3906 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3909 // Instruct each actor to discard pointers to the scene-graph
3910 DisconnectFromStage();
3915 SceneGraph::Node* Actor::CreateNode() const
3920 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3923 Actor* actor = dynamic_cast< Actor* >( object );
3927 if( 0 == actionName.compare( ACTION_SHOW ) )
3929 actor->SetVisible( true );
3932 else if( 0 == actionName.compare( ACTION_HIDE ) )
3934 actor->SetVisible( false );
3942 void Actor::EnsureRelayoutData()
3944 // Assign relayout data.
3945 if( !mRelayoutData )
3947 mRelayoutData = new RelayoutData();
3951 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3953 // Check if actor is dependent on parent
3954 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3956 if( ( dimension & ( 1 << i ) ) )
3958 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3959 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3969 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3971 // Check if actor is dependent on children
3972 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3974 if( ( dimension & ( 1 << i ) ) )
3976 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3977 switch( resizePolicy )
3979 case ResizePolicy::FIT_TO_CHILDREN:
3980 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3996 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3998 return Actor::RelayoutDependentOnChildren( dimension );
4001 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4003 // Check each possible dimension and see if it is dependent on the input one
4004 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4006 if( dimension & ( 1 << i ) )
4008 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4015 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4017 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4019 if( dimension & ( 1 << i ) )
4021 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4026 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4028 // If more than one dimension is requested, just return the first one found
4029 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4031 if( ( dimension & ( 1 << i ) ) )
4033 return mRelayoutData->negotiatedDimensions[ i ];
4037 return 0.0f; // Default
4040 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4042 EnsureRelayoutData();
4044 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4046 if( dimension & ( 1 << i ) )
4048 mRelayoutData->dimensionPadding[ i ] = padding;
4053 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4055 if ( mRelayoutData )
4057 // If more than one dimension is requested, just return the first one found
4058 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4060 if( ( dimension & ( 1 << i ) ) )
4062 return mRelayoutData->dimensionPadding[ i ];
4067 return GetDefaultDimensionPadding();
4070 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4072 EnsureRelayoutData();
4074 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4076 if( dimension & ( 1 << i ) )
4078 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4083 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4085 if ( mRelayoutData )
4087 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4089 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4099 float Actor::GetHeightForWidthBase( float width )
4101 float height = 0.0f;
4103 const Vector3 naturalSize = GetNaturalSize();
4104 if( naturalSize.width > 0.0f )
4106 height = naturalSize.height * width / naturalSize.width;
4108 else // we treat 0 as 1:1 aspect ratio
4116 float Actor::GetWidthForHeightBase( float height )
4120 const Vector3 naturalSize = GetNaturalSize();
4121 if( naturalSize.height > 0.0f )
4123 width = naturalSize.width * height / naturalSize.height;
4125 else // we treat 0 as 1:1 aspect ratio
4133 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4135 // Fill to parent, taking size mode factor into account
4136 switch( child.GetResizePolicy( dimension ) )
4138 case ResizePolicy::FILL_TO_PARENT:
4140 return GetLatestSize( dimension );
4143 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4145 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4148 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4150 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4155 return GetLatestSize( dimension );
4160 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4162 // Can be overridden in derived class
4163 return CalculateChildSizeBase( child, dimension );
4166 float Actor::GetHeightForWidth( float width )
4168 // Can be overridden in derived class
4169 return GetHeightForWidthBase( width );
4172 float Actor::GetWidthForHeight( float height )
4174 // Can be overridden in derived class
4175 return GetWidthForHeightBase( height );
4178 float Actor::GetLatestSize( Dimension::Type dimension ) const
4180 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4183 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4185 Vector2 padding = GetPadding( dimension );
4187 return GetLatestSize( dimension ) + padding.x + padding.y;
4190 float Actor::NegotiateFromParent( Dimension::Type dimension )
4192 Actor* parent = GetParent();
4195 Vector2 padding( GetPadding( dimension ) );
4196 Vector2 parentPadding( parent->GetPadding( dimension ) );
4197 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4203 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4205 float maxDimensionPoint = 0.0f;
4207 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4209 Dali::Actor child = GetChildAt( i );
4210 Actor& childImpl = GetImplementation( child );
4212 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4214 // Calculate the min and max points that the children range across
4215 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4216 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4217 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4221 return maxDimensionPoint;
4224 float Actor::GetSize( Dimension::Type dimension ) const
4226 return GetDimensionValue( GetTargetSize(), dimension );
4229 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4231 return GetDimensionValue( GetNaturalSize(), dimension );
4234 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4236 switch( GetResizePolicy( dimension ) )
4238 case ResizePolicy::USE_NATURAL_SIZE:
4240 return GetNaturalSize( dimension );
4243 case ResizePolicy::FIXED:
4245 return GetDimensionValue( GetPreferredSize(), dimension );
4248 case ResizePolicy::USE_ASSIGNED_SIZE:
4250 return GetDimensionValue( maximumSize, dimension );
4253 case ResizePolicy::FILL_TO_PARENT:
4254 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4255 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4257 return NegotiateFromParent( dimension );
4260 case ResizePolicy::FIT_TO_CHILDREN:
4262 return NegotiateFromChildren( dimension );
4265 case ResizePolicy::DIMENSION_DEPENDENCY:
4267 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4270 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4272 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4275 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4277 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4289 return 0.0f; // Default
4292 float Actor::ClampDimension( float size, Dimension::Type dimension )
4294 const float minSize = GetMinimumSize( dimension );
4295 const float maxSize = GetMaximumSize( dimension );
4297 return std::max( minSize, std::min( size, maxSize ) );
4300 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4302 // Check if it needs to be negotiated
4303 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4305 // Check that we havn't gotten into an infinite loop
4306 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4307 bool recursionFound = false;
4308 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4310 if( *it == searchActor )
4312 recursionFound = true;
4317 if( !recursionFound )
4319 // Record the path that we have taken
4320 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4322 // Dimension dependency check
4323 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4325 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4327 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4329 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4333 // Parent dependency check
4334 Actor* parent = GetParent();
4335 if( parent && RelayoutDependentOnParent( dimension ) )
4337 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4340 // Children dependency check
4341 if( RelayoutDependentOnChildren( dimension ) )
4343 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4345 Dali::Actor child = GetChildAt( i );
4346 Actor& childImpl = GetImplementation( child );
4348 // Only relayout child first if it is not dependent on this actor
4349 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4351 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4356 // For deriving classes
4357 OnCalculateRelayoutSize( dimension );
4359 // All dependencies checked, calculate the size and set negotiated flag
4360 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4362 SetNegotiatedDimension( newSize, dimension );
4363 SetLayoutNegotiated( true, dimension );
4365 // For deriving classes
4366 OnLayoutNegotiated( newSize, dimension );
4368 // This actor has been successfully processed, pop it off the recursion stack
4369 recursionStack.pop_back();
4373 // TODO: Break infinite loop
4374 SetLayoutNegotiated( true, dimension );
4379 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4381 // Negotiate all dimensions that require it
4382 ActorDimensionStack recursionStack;
4384 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4386 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4389 NegotiateDimension( dimension, allocatedSize, recursionStack );
4393 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4395 switch( mRelayoutData->sizeSetPolicy )
4397 case SizeScalePolicy::USE_SIZE_SET:
4402 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4404 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4405 const Vector3 naturalSize = GetNaturalSize();
4406 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4408 const float sizeRatio = size.width / size.height;
4409 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4411 if( naturalSizeRatio < sizeRatio )
4413 return Vector2( naturalSizeRatio * size.height, size.height );
4415 else if( naturalSizeRatio > sizeRatio )
4417 return Vector2( size.width, size.width / naturalSizeRatio );
4428 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4430 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4431 const Vector3 naturalSize = GetNaturalSize();
4432 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4434 const float sizeRatio = size.width / size.height;
4435 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4437 if( naturalSizeRatio < sizeRatio )
4439 return Vector2( size.width, size.width / naturalSizeRatio );
4441 else if( naturalSizeRatio > sizeRatio )
4443 return Vector2( naturalSizeRatio * size.height, size.height );
4461 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4463 // Do the set actor size
4464 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4466 // Adjust for size set policy
4467 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4469 // Lock the flag to stop recursive relayouts on set size
4470 mRelayoutData->insideRelayout = true;
4471 SetSize( negotiatedSize );
4472 mRelayoutData->insideRelayout = false;
4474 // Clear flags for all dimensions
4475 SetLayoutDirty( false );
4477 // Give deriving classes a chance to respond
4478 OnRelayout( negotiatedSize, container );
4480 if( !mOnRelayoutSignal.Empty() )
4482 Dali::Actor handle( this );
4483 mOnRelayoutSignal.Emit( handle );
4487 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4489 // Do the negotiation
4490 NegotiateDimensions( allocatedSize );
4492 // Set the actor size
4493 SetNegotiatedSize( container );
4495 // Negotiate down to children
4496 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4498 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4500 Dali::Actor child = GetChildAt( i );
4502 // Only relayout if required
4503 if( GetImplementation( child ).RelayoutRequired() )
4505 container.Add( child, newBounds );
4510 void Actor::RelayoutRequest( Dimension::Type dimension )
4512 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4513 if( relayoutController )
4515 Dali::Actor self( this );
4516 relayoutController->RequestRelayout( self, dimension );
4520 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4524 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4528 void Actor::SetPreferredSize( const Vector2& size )
4530 EnsureRelayoutData();
4532 if( size.width > 0.0f )
4534 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4537 if( size.height > 0.0f )
4539 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4542 mRelayoutData->preferredSize = size;
4547 Vector2 Actor::GetPreferredSize() const
4549 if ( mRelayoutData )
4551 return mRelayoutData->preferredSize;
4554 return GetDefaultPreferredSize();
4557 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4559 EnsureRelayoutData();
4561 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4563 if( dimension & ( 1 << i ) )
4565 mRelayoutData->minimumSize[ i ] = size;
4572 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4574 if ( mRelayoutData )
4576 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4578 if( dimension & ( 1 << i ) )
4580 return mRelayoutData->minimumSize[ i ];
4585 return 0.0f; // Default
4588 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4590 EnsureRelayoutData();
4592 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4594 if( dimension & ( 1 << i ) )
4596 mRelayoutData->maximumSize[ i ] = size;
4603 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4605 if ( mRelayoutData )
4607 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4609 if( dimension & ( 1 << i ) )
4611 return mRelayoutData->maximumSize[ i ];
4616 return FLT_MAX; // Default
4619 } // namespace Internal