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 )
2318 mParentOrigin( NULL ),
2319 mAnchorPoint( NULL ),
2320 mRelayoutData( NULL ),
2321 #ifdef DALI_DYNAMICS_SUPPORT
2322 mDynamicsData( NULL ),
2324 mGestureData( NULL ),
2326 mTargetSize( 0.0f, 0.0f, 0.0f ),
2328 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2330 mIsRoot( ROOT_LAYER == derivedType ),
2331 mIsRenderable( RENDERABLE == derivedType ),
2332 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2333 mIsOnStage( false ),
2334 mIsDynamicsRoot( false ),
2336 mLeaveRequired( false ),
2337 mKeyboardFocusable( false ),
2338 mDerivedRequiresTouch( false ),
2339 mDerivedRequiresHover( false ),
2340 mDerivedRequiresWheelEvent( false ),
2341 mOnStageSignalled( false ),
2342 mInsideOnSizeSet( false ),
2343 mInheritOrientation( true ),
2344 mInheritScale( true ),
2345 mDrawMode( DrawMode::NORMAL ),
2346 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2347 mColorMode( Node::DEFAULT_COLOR_MODE )
2351 void Actor::Initialize()
2354 SceneGraph::Node* node = CreateNode();
2356 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2357 mNode = node; // Keep raw-pointer to Node
2361 GetEventThreadServices().RegisterObject( this );
2366 // Remove mParent pointers from children even if we're destroying core,
2367 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2370 ActorConstIter endIter = mChildren->end();
2371 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2373 Actor& actor = GetImplementation( *iter );
2374 actor.SetParent( NULL );
2379 // Guard to allow handle destruction after Core has been destroyed
2380 if( EventThreadServices::IsCoreRunning() )
2384 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2385 mNode = NULL; // Node is about to be destroyed
2388 GetEventThreadServices().UnregisterObject( this );
2391 #ifdef DALI_DYNAMICS_SUPPORT
2393 delete mDynamicsData;
2396 // Cleanup optional gesture data
2397 delete mGestureData;
2399 // Cleanup optional parent origin and anchor
2400 delete mParentOrigin;
2401 delete mAnchorPoint;
2403 // Delete optional relayout data
2406 delete mRelayoutData;
2410 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2412 // This container is used instead of walking the Actor hierachy.
2413 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2414 ActorContainer connectionList;
2417 // This stage is atomic i.e. not interrupted by user callbacks
2418 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2420 // Notify applications about the newly connected actors.
2421 const ActorIter endIter = connectionList.end();
2422 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2424 Actor& actor = GetImplementation( *iter );
2425 actor.NotifyStageConnection();
2431 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2433 DALI_ASSERT_ALWAYS( !OnStage() );
2438 ConnectToSceneGraph( index );
2440 // Notification for internal derived classes
2441 OnStageConnectionInternal();
2443 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2444 connectionList.push_back( Dali::Actor( this ) );
2446 // Recursively connect children
2449 ActorConstIter endIter = mChildren->end();
2450 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2452 Actor& actor = GetImplementation( *iter );
2453 actor.RecursiveConnectToStage( connectionList, depth+1 );
2459 * This method is called when the Actor is connected to the Stage.
2460 * The parent must have added its Node to the scene-graph.
2461 * The child must connect its Node to the parent's Node.
2462 * This is resursive; the child calls ConnectToStage() for its children.
2464 void Actor::ConnectToSceneGraph( int index )
2466 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2470 // Reparent Node in next Update
2471 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2474 // Notify attachment
2477 mAttachment->Connect();
2480 #ifdef DALI_DYNAMICS_SUPPORT
2482 if( NULL != mDynamicsData )
2488 // Request relayout on all actors that are added to the scenegraph
2491 // Notification for Object::Observers
2495 void Actor::NotifyStageConnection()
2497 // Actors can be removed (in a callback), before the on-stage stage is reported.
2498 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2499 if( OnStage() && !mOnStageSignalled )
2501 // Notification for external (CustomActor) derived classes
2502 OnStageConnectionExternal( mDepth );
2504 if( !mOnStageSignal.Empty() )
2506 Dali::Actor handle( this );
2507 mOnStageSignal.Emit( handle );
2510 // Guard against Remove during callbacks
2513 mOnStageSignalled = true; // signal required next time Actor is removed
2518 void Actor::DisconnectFromStage()
2520 // This container is used instead of walking the Actor hierachy.
2521 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2522 ActorContainer disconnectionList;
2524 // This stage is atomic i.e. not interrupted by user callbacks
2525 RecursiveDisconnectFromStage( disconnectionList );
2527 // Notify applications about the newly disconnected actors.
2528 const ActorIter endIter = disconnectionList.end();
2529 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2531 Actor& actor = GetImplementation( *iter );
2532 actor.NotifyStageDisconnection();
2536 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2538 DALI_ASSERT_ALWAYS( OnStage() );
2540 // Recursively disconnect children
2543 ActorConstIter endIter = mChildren->end();
2544 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2546 Actor& actor = GetImplementation( *iter );
2547 actor.RecursiveDisconnectFromStage( disconnectionList );
2551 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2552 disconnectionList.push_back( Dali::Actor( this ) );
2554 // Notification for internal derived classes
2555 OnStageDisconnectionInternal();
2557 DisconnectFromSceneGraph();
2563 * This method is called by an actor or its parent, before a node removal message is sent.
2564 * This is recursive; the child calls DisconnectFromStage() for its children.
2566 void Actor::DisconnectFromSceneGraph()
2568 // Notification for Object::Observers
2569 OnSceneObjectRemove();
2571 // Notify attachment
2574 mAttachment->Disconnect();
2577 #ifdef DALI_DYNAMICS_SUPPORT
2579 if( NULL != mDynamicsData )
2581 DisconnectDynamics();
2586 void Actor::NotifyStageDisconnection()
2588 // Actors can be added (in a callback), before the off-stage state is reported.
2589 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2590 // only do this step if there is a stage, i.e. Core is not being shut down
2591 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2593 // Notification for external (CustomeActor) derived classes
2594 OnStageDisconnectionExternal();
2596 if( !mOffStageSignal.Empty() )
2598 Dali::Actor handle( this );
2599 mOffStageSignal.Emit( handle );
2602 // Guard against Add during callbacks
2605 mOnStageSignalled = false; // signal required next time Actor is added
2610 bool Actor::IsNodeConnected() const
2612 bool connected( false );
2617 if( mNode->IsRoot() || mNode->GetParent() )
2626 unsigned int Actor::GetDefaultPropertyCount() const
2628 return DEFAULT_PROPERTY_COUNT;
2631 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2633 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2635 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2637 indices.PushBack( i );
2641 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2643 if( index < DEFAULT_PROPERTY_COUNT )
2645 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2651 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2653 Property::Index index = Property::INVALID_INDEX;
2655 // Look for name in default properties
2656 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2658 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2659 if( 0 == name.compare( property->name ) )
2669 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2671 if( index < DEFAULT_PROPERTY_COUNT )
2673 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2679 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2681 if( index < DEFAULT_PROPERTY_COUNT )
2683 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2689 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2691 if( index < DEFAULT_PROPERTY_COUNT )
2693 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2699 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2701 if( index < DEFAULT_PROPERTY_COUNT )
2703 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2706 // index out of range...return Property::NONE
2707 return Property::NONE;
2710 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2714 case Dali::Actor::Property::PARENT_ORIGIN:
2716 SetParentOrigin( property.Get< Vector3 >() );
2720 case Dali::Actor::Property::PARENT_ORIGIN_X:
2722 SetParentOriginX( property.Get< float >() );
2726 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2728 SetParentOriginY( property.Get< float >() );
2732 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2734 SetParentOriginZ( property.Get< float >() );
2738 case Dali::Actor::Property::ANCHOR_POINT:
2740 SetAnchorPoint( property.Get< Vector3 >() );
2744 case Dali::Actor::Property::ANCHOR_POINT_X:
2746 SetAnchorPointX( property.Get< float >() );
2750 case Dali::Actor::Property::ANCHOR_POINT_Y:
2752 SetAnchorPointY( property.Get< float >() );
2756 case Dali::Actor::Property::ANCHOR_POINT_Z:
2758 SetAnchorPointZ( property.Get< float >() );
2762 case Dali::Actor::Property::SIZE:
2764 SetSize( property.Get< Vector3 >() );
2768 case Dali::Actor::Property::SIZE_WIDTH:
2770 SetWidth( property.Get< float >() );
2774 case Dali::Actor::Property::SIZE_HEIGHT:
2776 SetHeight( property.Get< float >() );
2780 case Dali::Actor::Property::SIZE_DEPTH:
2782 SetDepth( property.Get< float >() );
2786 case Dali::Actor::Property::POSITION:
2788 SetPosition( property.Get< Vector3 >() );
2792 case Dali::Actor::Property::POSITION_X:
2794 SetX( property.Get< float >() );
2798 case Dali::Actor::Property::POSITION_Y:
2800 SetY( property.Get< float >() );
2804 case Dali::Actor::Property::POSITION_Z:
2806 SetZ( property.Get< float >() );
2810 case Dali::Actor::Property::ORIENTATION:
2812 SetOrientation( property.Get< Quaternion >() );
2816 case Dali::Actor::Property::SCALE:
2818 SetScale( property.Get< Vector3 >() );
2822 case Dali::Actor::Property::SCALE_X:
2824 SetScaleX( property.Get< float >() );
2828 case Dali::Actor::Property::SCALE_Y:
2830 SetScaleY( property.Get< float >() );
2834 case Dali::Actor::Property::SCALE_Z:
2836 SetScaleZ( property.Get< float >() );
2840 case Dali::Actor::Property::VISIBLE:
2842 SetVisible( property.Get< bool >() );
2846 case Dali::Actor::Property::COLOR:
2848 SetColor( property.Get< Vector4 >() );
2852 case Dali::Actor::Property::COLOR_RED:
2854 SetColorRed( property.Get< float >() );
2858 case Dali::Actor::Property::COLOR_GREEN:
2860 SetColorGreen( property.Get< float >() );
2864 case Dali::Actor::Property::COLOR_BLUE:
2866 SetColorBlue( property.Get< float >() );
2870 case Dali::Actor::Property::COLOR_ALPHA:
2872 SetOpacity( property.Get< float >() );
2876 case Dali::Actor::Property::NAME:
2878 SetName( property.Get< std::string >() );
2882 case Dali::Actor::Property::SENSITIVE:
2884 SetSensitive( property.Get< bool >() );
2888 case Dali::Actor::Property::LEAVE_REQUIRED:
2890 SetLeaveRequired( property.Get< bool >() );
2894 case Dali::Actor::Property::INHERIT_ORIENTATION:
2896 SetInheritOrientation( property.Get< bool >() );
2900 case Dali::Actor::Property::INHERIT_SCALE:
2902 SetInheritScale( property.Get< bool >() );
2906 case Dali::Actor::Property::COLOR_MODE:
2908 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2912 case Dali::Actor::Property::POSITION_INHERITANCE:
2914 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2918 case Dali::Actor::Property::DRAW_MODE:
2920 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2924 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2926 SetSizeModeFactor( property.Get< Vector3 >() );
2930 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2932 ResizePolicy::Type type;
2933 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2935 SetResizePolicy( type, Dimension::WIDTH );
2940 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2942 ResizePolicy::Type type;
2943 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2945 SetResizePolicy( type, Dimension::HEIGHT );
2950 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2952 SizeScalePolicy::Type type;
2953 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2955 SetSizeScalePolicy( type );
2960 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2962 if( property.Get< bool >() )
2964 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2969 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2971 if( property.Get< bool >() )
2973 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2978 case Dali::Actor::Property::PADDING:
2980 Vector4 padding = property.Get< Vector4 >();
2981 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2982 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2986 case Dali::Actor::Property::MINIMUM_SIZE:
2988 Vector2 size = property.Get< Vector2 >();
2989 SetMinimumSize( size.x, Dimension::WIDTH );
2990 SetMinimumSize( size.y, Dimension::HEIGHT );
2994 case Dali::Actor::Property::MAXIMUM_SIZE:
2996 Vector2 size = property.Get< Vector2 >();
2997 SetMaximumSize( size.x, Dimension::WIDTH );
2998 SetMaximumSize( size.y, Dimension::HEIGHT );
3004 // this can happen in the case of a non-animatable default property so just do nothing
3010 // TODO: This method needs to be removed
3011 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3013 switch( entry.type )
3015 case Property::BOOLEAN:
3017 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3018 DALI_ASSERT_DEBUG( NULL != property );
3020 // property is being used in a separate thread; queue a message to set the property
3021 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3026 case Property::INTEGER:
3028 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3029 DALI_ASSERT_DEBUG( NULL != property );
3031 // property is being used in a separate thread; queue a message to set the property
3032 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3037 case Property::UNSIGNED_INTEGER:
3039 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
3040 DALI_ASSERT_DEBUG( NULL != property );
3042 // property is being used in a separate thread; queue a message to set the property
3043 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3048 case Property::FLOAT:
3050 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3051 DALI_ASSERT_DEBUG( NULL != property );
3053 // property is being used in a separate thread; queue a message to set the property
3054 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3059 case Property::VECTOR2:
3061 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3062 DALI_ASSERT_DEBUG( NULL != property );
3064 // property is being used in a separate thread; queue a message to set the property
3065 if(entry.componentIndex == 0)
3067 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3069 else if(entry.componentIndex == 1)
3071 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3075 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3081 case Property::VECTOR3:
3083 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3084 DALI_ASSERT_DEBUG( NULL != property );
3086 // property is being used in a separate thread; queue a message to set the property
3087 if(entry.componentIndex == 0)
3089 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3091 else if(entry.componentIndex == 1)
3093 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3095 else if(entry.componentIndex == 2)
3097 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3101 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3107 case Property::VECTOR4:
3109 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3110 DALI_ASSERT_DEBUG( NULL != property );
3112 // property is being used in a separate thread; queue a message to set the property
3113 if(entry.componentIndex == 0)
3115 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3117 else if(entry.componentIndex == 1)
3119 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3121 else if(entry.componentIndex == 2)
3123 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3125 else if(entry.componentIndex == 3)
3127 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3131 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3137 case Property::ROTATION:
3139 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3140 DALI_ASSERT_DEBUG( NULL != property );
3142 // property is being used in a separate thread; queue a message to set the property
3143 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3148 case Property::MATRIX:
3150 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3151 DALI_ASSERT_DEBUG( NULL != property );
3153 // property is being used in a separate thread; queue a message to set the property
3154 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3159 case Property::MATRIX3:
3161 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3162 DALI_ASSERT_DEBUG( NULL != property );
3164 // property is being used in a separate thread; queue a message to set the property
3165 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3172 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3178 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3180 Property::Value value;
3184 case Dali::Actor::Property::PARENT_ORIGIN:
3186 value = GetCurrentParentOrigin();
3190 case Dali::Actor::Property::PARENT_ORIGIN_X:
3192 value = GetCurrentParentOrigin().x;
3196 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3198 value = GetCurrentParentOrigin().y;
3202 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3204 value = GetCurrentParentOrigin().z;
3208 case Dali::Actor::Property::ANCHOR_POINT:
3210 value = GetCurrentAnchorPoint();
3214 case Dali::Actor::Property::ANCHOR_POINT_X:
3216 value = GetCurrentAnchorPoint().x;
3220 case Dali::Actor::Property::ANCHOR_POINT_Y:
3222 value = GetCurrentAnchorPoint().y;
3226 case Dali::Actor::Property::ANCHOR_POINT_Z:
3228 value = GetCurrentAnchorPoint().z;
3232 case Dali::Actor::Property::SIZE:
3234 value = GetCurrentSize();
3238 case Dali::Actor::Property::SIZE_WIDTH:
3240 value = GetCurrentSize().width;
3244 case Dali::Actor::Property::SIZE_HEIGHT:
3246 value = GetCurrentSize().height;
3250 case Dali::Actor::Property::SIZE_DEPTH:
3252 value = GetCurrentSize().depth;
3256 case Dali::Actor::Property::POSITION:
3258 value = GetCurrentPosition();
3262 case Dali::Actor::Property::POSITION_X:
3264 value = GetCurrentPosition().x;
3268 case Dali::Actor::Property::POSITION_Y:
3270 value = GetCurrentPosition().y;
3274 case Dali::Actor::Property::POSITION_Z:
3276 value = GetCurrentPosition().z;
3280 case Dali::Actor::Property::WORLD_POSITION:
3282 value = GetCurrentWorldPosition();
3286 case Dali::Actor::Property::WORLD_POSITION_X:
3288 value = GetCurrentWorldPosition().x;
3292 case Dali::Actor::Property::WORLD_POSITION_Y:
3294 value = GetCurrentWorldPosition().y;
3298 case Dali::Actor::Property::WORLD_POSITION_Z:
3300 value = GetCurrentWorldPosition().z;
3304 case Dali::Actor::Property::ORIENTATION:
3306 value = GetCurrentOrientation();
3310 case Dali::Actor::Property::WORLD_ORIENTATION:
3312 value = GetCurrentWorldOrientation();
3316 case Dali::Actor::Property::SCALE:
3318 value = GetCurrentScale();
3322 case Dali::Actor::Property::SCALE_X:
3324 value = GetCurrentScale().x;
3328 case Dali::Actor::Property::SCALE_Y:
3330 value = GetCurrentScale().y;
3334 case Dali::Actor::Property::SCALE_Z:
3336 value = GetCurrentScale().z;
3340 case Dali::Actor::Property::WORLD_SCALE:
3342 value = GetCurrentWorldScale();
3346 case Dali::Actor::Property::VISIBLE:
3348 value = IsVisible();
3352 case Dali::Actor::Property::COLOR:
3354 value = GetCurrentColor();
3358 case Dali::Actor::Property::COLOR_RED:
3360 value = GetCurrentColor().r;
3364 case Dali::Actor::Property::COLOR_GREEN:
3366 value = GetCurrentColor().g;
3370 case Dali::Actor::Property::COLOR_BLUE:
3372 value = GetCurrentColor().b;
3376 case Dali::Actor::Property::COLOR_ALPHA:
3378 value = GetCurrentColor().a;
3382 case Dali::Actor::Property::WORLD_COLOR:
3384 value = GetCurrentWorldColor();
3388 case Dali::Actor::Property::WORLD_MATRIX:
3390 value = GetCurrentWorldMatrix();
3394 case Dali::Actor::Property::NAME:
3400 case Dali::Actor::Property::SENSITIVE:
3402 value = IsSensitive();
3406 case Dali::Actor::Property::LEAVE_REQUIRED:
3408 value = GetLeaveRequired();
3412 case Dali::Actor::Property::INHERIT_ORIENTATION:
3414 value = IsOrientationInherited();
3418 case Dali::Actor::Property::INHERIT_SCALE:
3420 value = IsScaleInherited();
3424 case Dali::Actor::Property::COLOR_MODE:
3426 value = Scripting::GetColorMode( GetColorMode() );
3430 case Dali::Actor::Property::POSITION_INHERITANCE:
3432 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3436 case Dali::Actor::Property::DRAW_MODE:
3438 value = Scripting::GetDrawMode( GetDrawMode() );
3442 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3444 value = GetSizeModeFactor();
3448 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3450 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3454 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3456 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3460 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3462 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3466 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3468 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3472 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3474 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3478 case Dali::Actor::Property::PADDING:
3480 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3481 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3482 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3486 case Dali::Actor::Property::MINIMUM_SIZE:
3488 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3492 case Dali::Actor::Property::MAXIMUM_SIZE:
3494 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3500 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3508 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3513 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3515 // This method should only return an object connected to the scene-graph
3516 return OnStage() ? mNode : NULL;
3519 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3521 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3523 const PropertyBase* property( NULL );
3525 // This method should only return a property of an object connected to the scene-graph
3531 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3533 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3534 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3536 property = animatable->GetSceneGraphProperty();
3538 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3540 CustomPropertyMetadata* custom = FindCustomProperty( index );
3541 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3543 property = custom->GetSceneGraphProperty();
3545 else if( NULL != mNode )
3549 case Dali::Actor::Property::SIZE:
3550 property = &mNode->mSize;
3553 case Dali::Actor::Property::SIZE_WIDTH:
3554 property = &mNode->mSize;
3557 case Dali::Actor::Property::SIZE_HEIGHT:
3558 property = &mNode->mSize;
3561 case Dali::Actor::Property::SIZE_DEPTH:
3562 property = &mNode->mSize;
3565 case Dali::Actor::Property::POSITION:
3566 property = &mNode->mPosition;
3569 case Dali::Actor::Property::POSITION_X:
3570 property = &mNode->mPosition;
3573 case Dali::Actor::Property::POSITION_Y:
3574 property = &mNode->mPosition;
3577 case Dali::Actor::Property::POSITION_Z:
3578 property = &mNode->mPosition;
3581 case Dali::Actor::Property::ORIENTATION:
3582 property = &mNode->mOrientation;
3585 case Dali::Actor::Property::SCALE:
3586 property = &mNode->mScale;
3589 case Dali::Actor::Property::SCALE_X:
3590 property = &mNode->mScale;
3593 case Dali::Actor::Property::SCALE_Y:
3594 property = &mNode->mScale;
3597 case Dali::Actor::Property::SCALE_Z:
3598 property = &mNode->mScale;
3601 case Dali::Actor::Property::VISIBLE:
3602 property = &mNode->mVisible;
3605 case Dali::Actor::Property::COLOR:
3606 property = &mNode->mColor;
3609 case Dali::Actor::Property::COLOR_RED:
3610 property = &mNode->mColor;
3613 case Dali::Actor::Property::COLOR_GREEN:
3614 property = &mNode->mColor;
3617 case Dali::Actor::Property::COLOR_BLUE:
3618 property = &mNode->mColor;
3621 case Dali::Actor::Property::COLOR_ALPHA:
3622 property = &mNode->mColor;
3633 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3635 const PropertyInputImpl* property( NULL );
3637 // This method should only return a property of an object connected to the scene-graph
3643 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3645 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3646 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3648 property = animatable->GetSceneGraphProperty();
3650 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3652 CustomPropertyMetadata* custom = FindCustomProperty( index );
3653 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3654 property = custom->GetSceneGraphProperty();
3656 else if( NULL != mNode )
3660 case Dali::Actor::Property::PARENT_ORIGIN:
3661 property = &mNode->mParentOrigin;
3664 case Dali::Actor::Property::PARENT_ORIGIN_X:
3665 property = &mNode->mParentOrigin;
3668 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3669 property = &mNode->mParentOrigin;
3672 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3673 property = &mNode->mParentOrigin;
3676 case Dali::Actor::Property::ANCHOR_POINT:
3677 property = &mNode->mAnchorPoint;
3680 case Dali::Actor::Property::ANCHOR_POINT_X:
3681 property = &mNode->mAnchorPoint;
3684 case Dali::Actor::Property::ANCHOR_POINT_Y:
3685 property = &mNode->mAnchorPoint;
3688 case Dali::Actor::Property::ANCHOR_POINT_Z:
3689 property = &mNode->mAnchorPoint;
3692 case Dali::Actor::Property::SIZE:
3693 property = &mNode->mSize;
3696 case Dali::Actor::Property::SIZE_WIDTH:
3697 property = &mNode->mSize;
3700 case Dali::Actor::Property::SIZE_HEIGHT:
3701 property = &mNode->mSize;
3704 case Dali::Actor::Property::SIZE_DEPTH:
3705 property = &mNode->mSize;
3708 case Dali::Actor::Property::POSITION:
3709 property = &mNode->mPosition;
3712 case Dali::Actor::Property::POSITION_X:
3713 property = &mNode->mPosition;
3716 case Dali::Actor::Property::POSITION_Y:
3717 property = &mNode->mPosition;
3720 case Dali::Actor::Property::POSITION_Z:
3721 property = &mNode->mPosition;
3724 case Dali::Actor::Property::WORLD_POSITION:
3725 property = &mNode->mWorldPosition;
3728 case Dali::Actor::Property::WORLD_POSITION_X:
3729 property = &mNode->mWorldPosition;
3732 case Dali::Actor::Property::WORLD_POSITION_Y:
3733 property = &mNode->mWorldPosition;
3736 case Dali::Actor::Property::WORLD_POSITION_Z:
3737 property = &mNode->mWorldPosition;
3740 case Dali::Actor::Property::ORIENTATION:
3741 property = &mNode->mOrientation;
3744 case Dali::Actor::Property::WORLD_ORIENTATION:
3745 property = &mNode->mWorldOrientation;
3748 case Dali::Actor::Property::SCALE:
3749 property = &mNode->mScale;
3752 case Dali::Actor::Property::SCALE_X:
3753 property = &mNode->mScale;
3756 case Dali::Actor::Property::SCALE_Y:
3757 property = &mNode->mScale;
3760 case Dali::Actor::Property::SCALE_Z:
3761 property = &mNode->mScale;
3764 case Dali::Actor::Property::WORLD_SCALE:
3765 property = &mNode->mWorldScale;
3768 case Dali::Actor::Property::VISIBLE:
3769 property = &mNode->mVisible;
3772 case Dali::Actor::Property::COLOR:
3773 property = &mNode->mColor;
3776 case Dali::Actor::Property::COLOR_RED:
3777 property = &mNode->mColor;
3780 case Dali::Actor::Property::COLOR_GREEN:
3781 property = &mNode->mColor;
3784 case Dali::Actor::Property::COLOR_BLUE:
3785 property = &mNode->mColor;
3788 case Dali::Actor::Property::COLOR_ALPHA:
3789 property = &mNode->mColor;
3792 case Dali::Actor::Property::WORLD_COLOR:
3793 property = &mNode->mWorldColor;
3796 case Dali::Actor::Property::WORLD_MATRIX:
3797 property = &mNode->mWorldMatrix;
3808 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3810 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3812 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3814 // check whether the animatable property is registered already, if not then register one.
3815 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3816 if( animatableProperty )
3818 componentIndex = animatableProperty->componentIndex;
3825 case Dali::Actor::Property::PARENT_ORIGIN_X:
3826 case Dali::Actor::Property::ANCHOR_POINT_X:
3827 case Dali::Actor::Property::SIZE_WIDTH:
3828 case Dali::Actor::Property::POSITION_X:
3829 case Dali::Actor::Property::WORLD_POSITION_X:
3830 case Dali::Actor::Property::SCALE_X:
3831 case Dali::Actor::Property::COLOR_RED:
3837 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3838 case Dali::Actor::Property::ANCHOR_POINT_Y:
3839 case Dali::Actor::Property::SIZE_HEIGHT:
3840 case Dali::Actor::Property::POSITION_Y:
3841 case Dali::Actor::Property::WORLD_POSITION_Y:
3842 case Dali::Actor::Property::SCALE_Y:
3843 case Dali::Actor::Property::COLOR_GREEN:
3849 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3850 case Dali::Actor::Property::ANCHOR_POINT_Z:
3851 case Dali::Actor::Property::SIZE_DEPTH:
3852 case Dali::Actor::Property::POSITION_Z:
3853 case Dali::Actor::Property::WORLD_POSITION_Z:
3854 case Dali::Actor::Property::SCALE_Z:
3855 case Dali::Actor::Property::COLOR_BLUE:
3861 case Dali::Actor::Property::COLOR_ALPHA:
3875 return componentIndex;
3878 void Actor::SetParent( Actor* parent, int index )
3882 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3886 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3889 // Instruct each actor to create a corresponding node in the scene graph
3890 ConnectToStage( parent->GetDepth(), index );
3893 else // parent being set to NULL
3895 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3899 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3902 DALI_ASSERT_ALWAYS( mNode != NULL );
3906 // Disconnect the Node & its children from the scene-graph.
3907 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3910 // Instruct each actor to discard pointers to the scene-graph
3911 DisconnectFromStage();
3916 SceneGraph::Node* Actor::CreateNode() const
3921 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3924 Actor* actor = dynamic_cast< Actor* >( object );
3928 if( 0 == actionName.compare( ACTION_SHOW ) )
3930 actor->SetVisible( true );
3933 else if( 0 == actionName.compare( ACTION_HIDE ) )
3935 actor->SetVisible( false );
3943 void Actor::EnsureRelayoutData()
3945 // Assign relayout data.
3946 if( !mRelayoutData )
3948 mRelayoutData = new RelayoutData();
3952 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3954 // Check if actor is dependent on parent
3955 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3957 if( ( dimension & ( 1 << i ) ) )
3959 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3960 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3970 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3972 // Check if actor is dependent on children
3973 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3975 if( ( dimension & ( 1 << i ) ) )
3977 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3978 switch( resizePolicy )
3980 case ResizePolicy::FIT_TO_CHILDREN:
3981 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3997 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3999 return Actor::RelayoutDependentOnChildren( dimension );
4002 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4004 // Check each possible dimension and see if it is dependent on the input one
4005 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4007 if( dimension & ( 1 << i ) )
4009 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4016 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4018 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4020 if( dimension & ( 1 << i ) )
4022 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4027 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4029 // If more than one dimension is requested, just return the first one found
4030 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4032 if( ( dimension & ( 1 << i ) ) )
4034 return mRelayoutData->negotiatedDimensions[ i ];
4038 return 0.0f; // Default
4041 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4043 EnsureRelayoutData();
4045 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4047 if( dimension & ( 1 << i ) )
4049 mRelayoutData->dimensionPadding[ i ] = padding;
4054 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4056 if ( mRelayoutData )
4058 // If more than one dimension is requested, just return the first one found
4059 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4061 if( ( dimension & ( 1 << i ) ) )
4063 return mRelayoutData->dimensionPadding[ i ];
4068 return GetDefaultDimensionPadding();
4071 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4073 EnsureRelayoutData();
4075 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4077 if( dimension & ( 1 << i ) )
4079 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4084 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4086 if ( mRelayoutData )
4088 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4090 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4100 float Actor::GetHeightForWidthBase( float width )
4102 float height = 0.0f;
4104 const Vector3 naturalSize = GetNaturalSize();
4105 if( naturalSize.width > 0.0f )
4107 height = naturalSize.height * width / naturalSize.width;
4109 else // we treat 0 as 1:1 aspect ratio
4117 float Actor::GetWidthForHeightBase( float height )
4121 const Vector3 naturalSize = GetNaturalSize();
4122 if( naturalSize.height > 0.0f )
4124 width = naturalSize.width * height / naturalSize.height;
4126 else // we treat 0 as 1:1 aspect ratio
4134 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4136 // Fill to parent, taking size mode factor into account
4137 switch( child.GetResizePolicy( dimension ) )
4139 case ResizePolicy::FILL_TO_PARENT:
4141 return GetLatestSize( dimension );
4144 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4146 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4149 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4151 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4156 return GetLatestSize( dimension );
4161 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4163 // Can be overridden in derived class
4164 return CalculateChildSizeBase( child, dimension );
4167 float Actor::GetHeightForWidth( float width )
4169 // Can be overridden in derived class
4170 return GetHeightForWidthBase( width );
4173 float Actor::GetWidthForHeight( float height )
4175 // Can be overridden in derived class
4176 return GetWidthForHeightBase( height );
4179 float Actor::GetLatestSize( Dimension::Type dimension ) const
4181 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4184 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4186 Vector2 padding = GetPadding( dimension );
4188 return GetLatestSize( dimension ) + padding.x + padding.y;
4191 float Actor::NegotiateFromParent( Dimension::Type dimension )
4193 Actor* parent = GetParent();
4196 Vector2 padding( GetPadding( dimension ) );
4197 Vector2 parentPadding( parent->GetPadding( dimension ) );
4198 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4204 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4206 float maxDimensionPoint = 0.0f;
4208 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4210 Dali::Actor child = GetChildAt( i );
4211 Actor& childImpl = GetImplementation( child );
4213 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4215 // Calculate the min and max points that the children range across
4216 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4217 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4218 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4222 return maxDimensionPoint;
4225 float Actor::GetSize( Dimension::Type dimension ) const
4227 return GetDimensionValue( GetTargetSize(), dimension );
4230 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4232 return GetDimensionValue( GetNaturalSize(), dimension );
4235 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4237 switch( GetResizePolicy( dimension ) )
4239 case ResizePolicy::USE_NATURAL_SIZE:
4241 return GetNaturalSize( dimension );
4244 case ResizePolicy::FIXED:
4246 return GetDimensionValue( GetPreferredSize(), dimension );
4249 case ResizePolicy::USE_ASSIGNED_SIZE:
4251 return GetDimensionValue( maximumSize, dimension );
4254 case ResizePolicy::FILL_TO_PARENT:
4255 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4256 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4258 return NegotiateFromParent( dimension );
4261 case ResizePolicy::FIT_TO_CHILDREN:
4263 return NegotiateFromChildren( dimension );
4266 case ResizePolicy::DIMENSION_DEPENDENCY:
4268 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4271 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4273 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4276 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4278 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4290 return 0.0f; // Default
4293 float Actor::ClampDimension( float size, Dimension::Type dimension )
4295 const float minSize = GetMinimumSize( dimension );
4296 const float maxSize = GetMaximumSize( dimension );
4298 return std::max( minSize, std::min( size, maxSize ) );
4301 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4303 // Check if it needs to be negotiated
4304 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4306 // Check that we havn't gotten into an infinite loop
4307 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4308 bool recursionFound = false;
4309 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4311 if( *it == searchActor )
4313 recursionFound = true;
4318 if( !recursionFound )
4320 // Record the path that we have taken
4321 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4323 // Dimension dependency check
4324 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4326 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4328 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4330 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4334 // Parent dependency check
4335 Actor* parent = GetParent();
4336 if( parent && RelayoutDependentOnParent( dimension ) )
4338 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4341 // Children dependency check
4342 if( RelayoutDependentOnChildren( dimension ) )
4344 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4346 Dali::Actor child = GetChildAt( i );
4347 Actor& childImpl = GetImplementation( child );
4349 // Only relayout child first if it is not dependent on this actor
4350 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4352 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4357 // For deriving classes
4358 OnCalculateRelayoutSize( dimension );
4360 // All dependencies checked, calculate the size and set negotiated flag
4361 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4363 SetNegotiatedDimension( newSize, dimension );
4364 SetLayoutNegotiated( true, dimension );
4366 // For deriving classes
4367 OnLayoutNegotiated( newSize, dimension );
4369 // This actor has been successfully processed, pop it off the recursion stack
4370 recursionStack.pop_back();
4374 // TODO: Break infinite loop
4375 SetLayoutNegotiated( true, dimension );
4380 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4382 // Negotiate all dimensions that require it
4383 ActorDimensionStack recursionStack;
4385 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4387 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4390 NegotiateDimension( dimension, allocatedSize, recursionStack );
4394 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4396 switch( mRelayoutData->sizeSetPolicy )
4398 case SizeScalePolicy::USE_SIZE_SET:
4403 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4405 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4406 const Vector3 naturalSize = GetNaturalSize();
4407 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4409 const float sizeRatio = size.width / size.height;
4410 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4412 if( naturalSizeRatio < sizeRatio )
4414 return Vector2( naturalSizeRatio * size.height, size.height );
4416 else if( naturalSizeRatio > sizeRatio )
4418 return Vector2( size.width, size.width / naturalSizeRatio );
4429 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4431 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4432 const Vector3 naturalSize = GetNaturalSize();
4433 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4435 const float sizeRatio = size.width / size.height;
4436 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4438 if( naturalSizeRatio < sizeRatio )
4440 return Vector2( size.width, size.width / naturalSizeRatio );
4442 else if( naturalSizeRatio > sizeRatio )
4444 return Vector2( naturalSizeRatio * size.height, size.height );
4462 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4464 // Do the set actor size
4465 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4467 // Adjust for size set policy
4468 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4470 // Lock the flag to stop recursive relayouts on set size
4471 mRelayoutData->insideRelayout = true;
4472 SetSize( negotiatedSize );
4473 mRelayoutData->insideRelayout = false;
4475 // Clear flags for all dimensions
4476 SetLayoutDirty( false );
4478 // Give deriving classes a chance to respond
4479 OnRelayout( negotiatedSize, container );
4481 if( !mOnRelayoutSignal.Empty() )
4483 Dali::Actor handle( this );
4484 mOnRelayoutSignal.Emit( handle );
4488 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4490 // Do the negotiation
4491 NegotiateDimensions( allocatedSize );
4493 // Set the actor size
4494 SetNegotiatedSize( container );
4496 // Negotiate down to children
4497 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4499 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4501 Dali::Actor child = GetChildAt( i );
4503 // Only relayout if required
4504 if( GetImplementation( child ).RelayoutRequired() )
4506 container.Add( child, newBounds );
4511 void Actor::RelayoutRequest( Dimension::Type dimension )
4513 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4514 if( relayoutController )
4516 Dali::Actor self( this );
4517 relayoutController->RequestRelayout( self, dimension );
4521 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4525 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4529 void Actor::SetPreferredSize( const Vector2& size )
4531 EnsureRelayoutData();
4533 if( size.width > 0.0f )
4535 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4538 if( size.height > 0.0f )
4540 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4543 mRelayoutData->preferredSize = size;
4548 Vector2 Actor::GetPreferredSize() const
4550 if ( mRelayoutData )
4552 return mRelayoutData->preferredSize;
4555 return GetDefaultPreferredSize();
4558 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4560 EnsureRelayoutData();
4562 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4564 if( dimension & ( 1 << i ) )
4566 mRelayoutData->minimumSize[ i ] = size;
4573 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4575 if ( mRelayoutData )
4577 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4579 if( dimension & ( 1 << i ) )
4581 return mRelayoutData->minimumSize[ i ];
4586 return 0.0f; // Default
4589 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4591 EnsureRelayoutData();
4593 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4595 if( dimension & ( 1 << i ) )
4597 mRelayoutData->maximumSize[ i ] = size;
4604 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4606 if ( mRelayoutData )
4608 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4610 if( dimension & ( 1 << i ) )
4612 return mRelayoutData->maximumSize[ i ];
4617 return FLT_MAX; // Default
4620 } // namespace Internal