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( ActorPtr( &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, ActorPtr( &child ) );
493 mChildren->push_back( ActorPtr( &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 if( (this == &child) || (!mChildren) )
518 // no children or removing itself
524 // Find the child in mChildren, and unparent it
525 ActorIter end = mChildren->end();
526 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
528 ActorPtr actor = (*iter);
530 if( actor.Get() == &child )
532 // Keep handle for OnChildRemove notification
535 // Do this first, since user callbacks from within SetParent() may need to add the child
536 mChildren->erase( iter );
538 DALI_ASSERT_DEBUG( actor->GetParent() == this );
539 actor->SetParent( NULL );
547 // Notification for derived classes
548 OnChildRemove( *(removed.Get()) );
550 // Only put in a relayout request if there is a suitable dependency
551 if( RelayoutDependentOnChildren() )
558 void Actor::Unparent()
562 // Remove this actor from the parent. The remove will put a relayout request in for
563 // the parent if required
564 mParent->Remove( *this );
565 // mParent is now NULL!
569 unsigned int Actor::GetChildCount() const
571 return ( NULL != mChildren ) ? mChildren->size() : 0;
574 ActorPtr Actor::GetChildAt( unsigned int index ) const
576 DALI_ASSERT_ALWAYS( index < GetChildCount() );
578 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
581 ActorPtr Actor::FindChildByName( const std::string& actorName )
584 if( actorName == mName )
590 ActorIter end = mChildren->end();
591 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
593 child = (*iter)->FindChildByName( actorName );
604 ActorPtr Actor::FindChildById( const unsigned int id )
613 ActorIter end = mChildren->end();
614 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
616 child = (*iter)->FindChildById( id );
627 void Actor::SetParentOrigin( const Vector3& origin )
631 // mNode is being used in a separate thread; queue a message to set the value & base value
632 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
635 // Cache for event-thread access
638 // not allocated, check if different from default
639 if( ParentOrigin::DEFAULT != origin )
641 mParentOrigin = new Vector3( origin );
646 // check if different from current costs more than just set
647 *mParentOrigin = origin;
651 void Actor::SetParentOriginX( float x )
653 const Vector3& current = GetCurrentParentOrigin();
655 SetParentOrigin( Vector3( x, current.y, current.z ) );
658 void Actor::SetParentOriginY( float y )
660 const Vector3& current = GetCurrentParentOrigin();
662 SetParentOrigin( Vector3( current.x, y, current.z ) );
665 void Actor::SetParentOriginZ( float z )
667 const Vector3& current = GetCurrentParentOrigin();
669 SetParentOrigin( Vector3( current.x, current.y, z ) );
672 const Vector3& Actor::GetCurrentParentOrigin() const
674 // Cached for event-thread access
675 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
678 void Actor::SetAnchorPoint( const Vector3& anchor )
682 // mNode is being used in a separate thread; queue a message to set the value & base value
683 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
686 // Cache for event-thread access
689 // not allocated, check if different from default
690 if( AnchorPoint::DEFAULT != anchor )
692 mAnchorPoint = new Vector3( anchor );
697 // check if different from current costs more than just set
698 *mAnchorPoint = anchor;
702 void Actor::SetAnchorPointX( float x )
704 const Vector3& current = GetCurrentAnchorPoint();
706 SetAnchorPoint( Vector3( x, current.y, current.z ) );
709 void Actor::SetAnchorPointY( float y )
711 const Vector3& current = GetCurrentAnchorPoint();
713 SetAnchorPoint( Vector3( current.x, y, current.z ) );
716 void Actor::SetAnchorPointZ( float z )
718 const Vector3& current = GetCurrentAnchorPoint();
720 SetAnchorPoint( Vector3( current.x, current.y, z ) );
723 const Vector3& Actor::GetCurrentAnchorPoint() const
725 // Cached for event-thread access
726 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
729 void Actor::SetPosition( float x, float y )
731 SetPosition( Vector3( x, y, 0.0f ) );
734 void Actor::SetPosition( float x, float y, float z )
736 SetPosition( Vector3( x, y, z ) );
739 void Actor::SetPosition( const Vector3& position )
741 mTargetPosition = position;
745 // mNode is being used in a separate thread; queue a message to set the value & base value
746 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
750 void Actor::SetX( float x )
752 mTargetPosition.x = x;
756 // mNode is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
761 void Actor::SetY( float y )
763 mTargetPosition.y = y;
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
772 void Actor::SetZ( float z )
774 mTargetPosition.z = z;
778 // mNode is being used in a separate thread; queue a message to set the value & base value
779 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
783 void Actor::TranslateBy( const Vector3& distance )
785 mTargetPosition += distance;
789 // mNode is being used in a separate thread; queue a message to set the value & base value
790 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
794 const Vector3& Actor::GetCurrentPosition() const
798 // mNode is being used in a separate thread; copy the value from the previous update
799 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
802 return Vector3::ZERO;
805 const Vector3& Actor::GetTargetPosition() const
807 return mTargetPosition;
810 const Vector3& Actor::GetCurrentWorldPosition() const
814 // mNode is being used in a separate thread; copy the value from the previous update
815 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
818 return Vector3::ZERO;
821 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
823 // this flag is not animatable so keep the value
824 mPositionInheritanceMode = mode;
827 // mNode is being used in a separate thread; queue a message to set the value
828 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
832 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
834 // Cached for event-thread access
835 return mPositionInheritanceMode;
838 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
840 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
841 normalizedAxis.Normalize();
843 Quaternion orientation( angle, normalizedAxis );
845 SetOrientation( orientation );
848 void Actor::SetOrientation( const Quaternion& orientation )
852 // mNode is being used in a separate thread; queue a message to set the value & base value
853 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
857 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
861 // mNode is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
866 void Actor::RotateBy( const Quaternion& relativeRotation )
870 // mNode is being used in a separate thread; queue a message to set the value & base value
871 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
875 const Quaternion& Actor::GetCurrentOrientation() const
879 // mNode is being used in a separate thread; copy the value from the previous update
880 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
883 return Quaternion::IDENTITY;
886 const Quaternion& Actor::GetCurrentWorldOrientation() const
890 // mNode is being used in a separate thread; copy the value from the previous update
891 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
894 return Quaternion::IDENTITY;
897 void Actor::SetScale( float scale )
899 SetScale( Vector3( scale, scale, scale ) );
902 void Actor::SetScale( float x, float y, float z )
904 SetScale( Vector3( x, y, z ) );
907 void Actor::SetScale( const Vector3& scale )
911 // mNode is being used in a separate thread; queue a message to set the value & base value
912 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
916 void Actor::SetScaleX( float x )
920 // mNode is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
925 void Actor::SetScaleY( float y )
929 // mNode is being used in a separate thread; queue a message to set the value & base value
930 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
934 void Actor::SetScaleZ( float z )
938 // mNode is being used in a separate thread; queue a message to set the value & base value
939 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
943 void Actor::ScaleBy(const Vector3& relativeScale)
947 // mNode is being used in a separate thread; queue a message to set the value & base value
948 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
952 const Vector3& Actor::GetCurrentScale() const
956 // mNode is being used in a separate thread; copy the value from the previous update
957 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
963 const Vector3& Actor::GetCurrentWorldScale() const
967 // mNode is being used in a separate thread; copy the value from the previous update
968 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
974 void Actor::SetInheritScale( bool inherit )
976 // non animateable so keep local copy
977 mInheritScale = inherit;
980 // mNode is being used in a separate thread; queue a message to set the value
981 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
985 bool Actor::IsScaleInherited() const
987 return mInheritScale;
990 Matrix Actor::GetCurrentWorldMatrix() const
994 // World matrix is no longer updated unless there is something observing the node.
995 // Need to calculate it from node's world position, orientation and scale:
996 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
997 Matrix worldMatrix(false);
998 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
999 mNode->GetWorldOrientation( updateBufferIndex ),
1000 mNode->GetWorldPosition( updateBufferIndex ) );
1004 return Matrix::IDENTITY;
1007 void Actor::SetVisible( bool visible )
1011 // mNode is being used in a separate thread; queue a message to set the value & base value
1012 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1016 bool Actor::IsVisible() const
1020 // mNode is being used in a separate thread; copy the value from the previous update
1021 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1027 void Actor::SetOpacity( float opacity )
1031 // mNode is being used in a separate thread; queue a message to set the value & base value
1032 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1036 float Actor::GetCurrentOpacity() const
1040 // mNode is being used in a separate thread; copy the value from the previous update
1041 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1047 const Vector4& Actor::GetCurrentWorldColor() const
1051 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1054 return Color::WHITE;
1057 void Actor::SetColor( const Vector4& color )
1061 // mNode is being used in a separate thread; queue a message to set the value & base value
1062 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1066 void Actor::SetColorRed( float red )
1070 // mNode is being used in a separate thread; queue a message to set the value & base value
1071 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1075 void Actor::SetColorGreen( float green )
1079 // mNode is being used in a separate thread; queue a message to set the value & base value
1080 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1084 void Actor::SetColorBlue( float blue )
1088 // mNode is being used in a separate thread; queue a message to set the value & base value
1089 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1093 const Vector4& Actor::GetCurrentColor() const
1097 // mNode is being used in a separate thread; copy the value from the previous update
1098 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1101 return Color::WHITE;
1104 void Actor::SetInheritOrientation( bool inherit )
1106 // non animateable so keep local copy
1107 mInheritOrientation = inherit;
1110 // mNode is being used in a separate thread; queue a message to set the value
1111 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1115 bool Actor::IsOrientationInherited() const
1117 return mInheritOrientation;
1120 void Actor::SetSizeModeFactor( const Vector3& factor )
1122 EnsureRelayoutData();
1124 mRelayoutData->sizeModeFactor = factor;
1127 const Vector3& Actor::GetSizeModeFactor() const
1129 if ( mRelayoutData )
1131 return mRelayoutData->sizeModeFactor;
1134 return GetDefaultSizeModeFactor();
1137 void Actor::SetColorMode( ColorMode colorMode )
1139 // non animateable so keep local copy
1140 mColorMode = colorMode;
1143 // mNode is being used in a separate thread; queue a message to set the value
1144 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1148 ColorMode Actor::GetColorMode() const
1150 // we have cached copy
1154 void Actor::SetSize( float width, float height )
1156 SetSize( Vector2( width, height ) );
1159 void Actor::SetSize( float width, float height, float depth )
1161 SetSize( Vector3( width, height, depth ) );
1164 void Actor::SetSize( const Vector2& size )
1166 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1169 void Actor::SetSizeInternal( const Vector2& size )
1171 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1174 float Actor::CalculateSizeZ( const Vector2& size ) const
1176 return std::min( size.width, size.height );
1179 void Actor::SetSize( const Vector3& size )
1181 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1183 SetPreferredSize( size.GetVectorXY() );
1187 SetSizeInternal( size );
1191 void Actor::SetSizeInternal( const Vector3& size )
1193 // dont allow recursive loop
1194 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1195 // 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
1196 if( ( NULL != mNode )&&
1197 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1198 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1199 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1203 // mNode is being used in a separate thread; queue a message to set the value & base value
1204 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1206 // Notification for derived classes
1207 mInsideOnSizeSet = true;
1208 OnSizeSet( mTargetSize );
1209 mInsideOnSizeSet = false;
1211 // Raise a relayout request if the flag is not locked
1212 if( mRelayoutData && !mRelayoutData->insideRelayout )
1219 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1221 mTargetSize = targetSize;
1223 // Notify deriving classes
1224 OnSizeAnimation( animation, mTargetSize );
1227 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1229 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1231 mTargetSize.width = targetSize;
1233 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1235 mTargetSize.height = targetSize;
1237 // Notify deriving classes
1238 OnSizeAnimation( animation, mTargetSize );
1241 void Actor::SetWidth( float width )
1245 // mNode is being used in a separate thread; queue a message to set the value & base value
1246 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1250 void Actor::SetHeight( float height )
1254 // mNode is being used in a separate thread; queue a message to set the value & base value
1255 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1259 void Actor::SetDepth( float depth )
1263 // mNode is being used in a separate thread; queue a message to set the value & base value
1264 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1268 const Vector3& Actor::GetTargetSize() const
1273 const Vector3& Actor::GetCurrentSize() const
1277 // mNode is being used in a separate thread; copy the value from the previous update
1278 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1281 return Vector3::ZERO;
1284 Vector3 Actor::GetNaturalSize() const
1286 // It is up to deriving classes to return the appropriate natural size
1287 return Vector3( 0.0f, 0.0f, 0.0f );
1290 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1292 EnsureRelayoutData();
1294 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1296 if( dimension & ( 1 << i ) )
1298 mRelayoutData->resizePolicies[ i ] = policy;
1302 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1304 if( dimension & Dimension::WIDTH )
1306 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1309 if( dimension & Dimension::HEIGHT )
1311 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1315 // If calling SetResizePolicy, assume we want relayout enabled
1316 SetRelayoutEnabled( true );
1318 OnSetResizePolicy( policy, dimension );
1320 // Trigger relayout on this control
1324 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1326 if ( mRelayoutData )
1328 // If more than one dimension is requested, just return the first one found
1329 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1331 if( ( dimension & ( 1 << i ) ) )
1333 return mRelayoutData->resizePolicies[ i ];
1338 return ResizePolicy::DEFAULT;
1341 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1343 EnsureRelayoutData();
1345 mRelayoutData->sizeSetPolicy = policy;
1348 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1350 if ( mRelayoutData )
1352 return mRelayoutData->sizeSetPolicy;
1355 return DEFAULT_SIZE_SCALE_POLICY;
1358 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1360 EnsureRelayoutData();
1362 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1364 if( dimension & ( 1 << i ) )
1366 mRelayoutData->dimensionDependencies[ i ] = dependency;
1371 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1373 if ( mRelayoutData )
1375 // If more than one dimension is requested, just return the first one found
1376 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1378 if( ( dimension & ( 1 << i ) ) )
1380 return mRelayoutData->dimensionDependencies[ i ];
1385 return Dimension::ALL_DIMENSIONS; // Default
1388 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1390 // If relayout data has not been allocated yet and the client is requesting
1391 // to disable it, do nothing
1392 if( mRelayoutData || relayoutEnabled )
1394 EnsureRelayoutData();
1396 mRelayoutData->relayoutEnabled = relayoutEnabled;
1400 bool Actor::IsRelayoutEnabled() const
1402 // Assume that if relayout data has not been allocated yet then
1403 // relayout is disabled
1404 return mRelayoutData && mRelayoutData->relayoutEnabled;
1407 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1409 EnsureRelayoutData();
1411 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1413 if( dimension & ( 1 << i ) )
1415 mRelayoutData->dimensionDirty[ i ] = dirty;
1420 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1422 if ( mRelayoutData )
1424 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1426 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1436 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1438 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1441 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1443 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1446 unsigned int Actor::AddRenderer( Renderer& renderer )
1448 //TODO: MESH_REWORK : Add support for multiple renderers
1449 if ( ! mAttachment )
1451 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1457 unsigned int Actor::GetRendererCount() const
1459 //TODO: MESH_REWORK : Add support for multiple renderers
1460 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1461 return attachment ? 1u : 0u;
1464 Renderer& Actor::GetRendererAt( unsigned int index )
1466 //TODO: MESH_REWORK : Add support for multiple renderers
1467 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1469 //TODO: MESH_REWORK : Temporary code
1470 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1471 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1473 return attachment->GetRenderer();
1476 void Actor::RemoveRenderer( Renderer& renderer )
1478 //TODO: MESH_REWORK : Add support for multiple renderers
1482 void Actor::RemoveRenderer( unsigned int index )
1484 //TODO: MESH_REWORK : Add support for multiple renderers
1489 #ifdef DALI_DYNAMICS_SUPPORT
1491 //--------------- Dynamics ---------------
1493 void Actor::DisableDynamics()
1495 if( NULL != mDynamicsData )
1497 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1499 // ensure dynamics object are disconnected from scene
1500 DisconnectDynamics();
1502 // delete joint owned by this actor
1503 while( !mDynamicsData->joints.empty() )
1505 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1508 // delete other joints referencing this actor
1509 while( !mDynamicsData->referencedJoints.empty() )
1511 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1512 ActorPtr jointOwner( joint->GetActor( true ) );
1515 jointOwner->RemoveDynamicsJoint( joint );
1519 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1522 // delete the DynamicsBody object
1523 mDynamicsData->body.Reset();
1525 // Discard Dynamics data structure
1526 delete mDynamicsData;
1527 mDynamicsData = NULL;
1531 DynamicsBodyPtr Actor::GetDynamicsBody() const
1533 DynamicsBodyPtr body;
1535 if( NULL != mDynamicsData )
1537 body = mDynamicsData->body;
1543 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1545 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1547 if( NULL == mDynamicsData )
1549 mDynamicsData = new DynamicsData( this );
1552 if( !mDynamicsData->body )
1554 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1558 DynamicsWorldPtr world( DynamicsWorld::Get() );
1561 if( mParent == world->GetRootActor().Get() )
1563 mDynamicsData->body->Connect( GetEventThreadServices() );
1569 return mDynamicsData->body;
1572 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1574 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1575 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1578 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1580 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1581 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1583 DynamicsJointPtr joint;
1585 DynamicsWorldPtr world( DynamicsWorld::Get() );
1589 if( NULL != mDynamicsData )
1591 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1593 if( mDynamicsData->joints.end() != it )
1595 // use existing joint
1601 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1602 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1606 bodyA = EnableDynamics( new DynamicsBodyConfig );
1611 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1614 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1615 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1617 if( OnStage() && attachedActor->OnStage() )
1619 joint->Connect( GetEventThreadServices() );
1622 attachedActor->ReferenceJoint( joint );
1624 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1625 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1632 const int Actor::GetNumberOfJoints() const
1634 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1637 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1639 DynamicsJointPtr joint;
1641 if( NULL != mDynamicsData )
1643 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1645 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1647 for( int i = 0; i < index; ++i )
1659 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1661 DynamicsJointPtr joint;
1663 if( NULL != mDynamicsData )
1665 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1667 if( mDynamicsData->joints.end() != it )
1669 // use existing joint
1677 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1679 if( NULL != mDynamicsData )
1681 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1682 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1684 for(; it != endIt; ++it )
1686 if( it->second == joint.Get() )
1688 ActorPtr attachedActor( it->first );
1690 if( OnStage() && attachedActor && attachedActor->OnStage() )
1692 joint->Disconnect( GetEventThreadServices() );
1697 attachedActor->ReleaseJoint( joint );
1698 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1699 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1702 mDynamicsData->joints.erase(it);
1709 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1711 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1713 if( NULL != mDynamicsData )
1715 mDynamicsData->referencedJoints.push_back(joint);
1719 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1721 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1723 if( NULL != mDynamicsData )
1725 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1727 if( it != mDynamicsData->referencedJoints.end() )
1729 mDynamicsData->referencedJoints.erase( it );
1734 void Actor::SetDynamicsRoot(bool flag)
1736 if( mIsDynamicsRoot != flag )
1738 mIsDynamicsRoot = flag;
1740 if( OnStage() && mChildren )
1742 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1743 ActorIter end = mChildren->end();
1744 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1746 ActorPtr child = (*iter);
1748 if( child->GetDynamicsBody() )
1750 if( mIsDynamicsRoot )
1752 child->ConnectDynamics();
1756 child->DisconnectDynamics();
1764 bool Actor::IsDynamicsRoot() const
1766 return mIsDynamicsRoot;
1769 void Actor::AttachedActorOnStage( Dali::Actor actor )
1771 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1775 ActorPtr attachedActor( &GetImplementation(actor) );
1777 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1778 if( NULL != mDynamicsData )
1780 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1781 if( mDynamicsData->joints.end() != it )
1783 DynamicsJointPtr joint( it->second );
1784 joint->Connect( GetEventThreadServices() );
1790 void Actor::AttachedActorOffStage( Dali::Actor actor )
1792 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1796 ActorPtr attachedActor( &GetImplementation(actor) );
1798 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1799 if( NULL != mDynamicsData )
1801 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1802 if( mDynamicsData->joints.end() != it )
1804 DynamicsJointPtr joint( it->second );
1805 joint->Disconnect( GetEventThreadServices() );
1811 void Actor::ConnectDynamics()
1813 if( NULL != mDynamicsData && mDynamicsData->body )
1815 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1817 mDynamicsData->body->Connect( GetEventThreadServices() );
1819 // Connect all joints where attachedActor is also on stage
1820 if( !mDynamicsData->joints.empty() )
1822 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1823 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1825 for(; it != endIt; ++it )
1827 Actor* attachedActor( it->first );
1828 if( NULL != attachedActor && attachedActor->OnStage() )
1830 DynamicsJointPtr joint( it->second );
1832 joint->Connect( GetEventThreadServices() );
1840 void Actor::DisconnectDynamics()
1842 if( NULL != mDynamicsData && mDynamicsData->body )
1846 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1848 // Disconnect all joints
1849 if( !mDynamicsData->joints.empty() )
1851 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1852 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1854 for(; it != endIt; ++it )
1856 DynamicsJointPtr joint( it->second );
1858 joint->Disconnect( GetEventThreadServices() );
1865 #endif // DALI_DYNAMICS_SUPPORT
1867 void Actor::SetOverlay( bool enable )
1869 // Setting STENCIL will override OVERLAY
1870 if( DrawMode::STENCIL != mDrawMode )
1872 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1876 bool Actor::IsOverlay() const
1878 return ( DrawMode::OVERLAY == mDrawMode );
1881 void Actor::SetDrawMode( DrawMode::Type drawMode )
1883 // this flag is not animatable so keep the value
1884 mDrawMode = drawMode;
1887 // mNode is being used in a separate thread; queue a message to set the value
1888 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1892 DrawMode::Type Actor::GetDrawMode() const
1897 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1899 // only valid when on-stage
1900 StagePtr stage = Stage::GetCurrent();
1901 if( stage && OnStage() )
1903 const RenderTaskList& taskList = stage->GetRenderTaskList();
1905 Vector2 converted( screenX, screenY );
1907 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1908 const int taskCount = taskList.GetTaskCount();
1909 for( int i = taskCount - 1; i >= 0; --i )
1911 Dali::RenderTask task = taskList.GetTask( i );
1912 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1914 // found a task where this conversion was ok so return
1922 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1924 bool retval = false;
1925 // only valid when on-stage
1928 CameraActor* camera = renderTask.GetCameraActor();
1932 renderTask.GetViewport( viewport );
1934 // need to translate coordinates to render tasks coordinate space
1935 Vector2 converted( screenX, screenY );
1936 if( renderTask.TranslateCoordinates( converted ) )
1938 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1945 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1947 // Early-out if mNode is NULL
1953 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1955 // Calculate the ModelView matrix
1956 Matrix modelView( false/*don't init*/);
1957 // need to use the components as world matrix is only updated for actors that need it
1958 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1959 Matrix::Multiply( modelView, modelView, viewMatrix );
1961 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1962 Matrix invertedMvp( false/*don't init*/);
1963 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1964 bool success = invertedMvp.Invert();
1966 // Convert to GL coordinates
1967 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1972 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1979 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1985 if( XyPlaneIntersect( nearPos, farPos, local ) )
1987 Vector3 size = GetCurrentSize();
1988 localX = local.x + size.x * 0.5f;
1989 localY = local.y + size.y * 0.5f;
2000 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
2003 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
2005 Mathematical Formulation
2007 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
2009 ( p - c ) dot ( p - c ) = r^2
2011 Given a ray with a point of origin 'o', and a direction vector 'd':
2013 ray(t) = o + td, t >= 0
2015 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
2017 (o + td - c ) dot ( o + td - c ) = r^2
2019 To solve for t we first expand the above into a more recognisable quadratic equation form
2021 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
2030 B = 2( o - c ) dot d
2031 C = ( o - c ) dot ( o - c ) - r^2
2033 which can be solved using a standard quadratic formula.
2035 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
2037 Practical Simplification
2039 In a renderer, we often differentiate between world space and object space. In the object space
2040 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2041 into object space, the mathematical solution presented above can be simplified significantly.
2043 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2047 and we can find the t at which the (transformed) ray intersects the sphere by
2049 ( o + td ) dot ( o + td ) = r^2
2051 According to the reasoning above, we expand the above quadratic equation into the general form
2055 which now has coefficients:
2062 // Early out if mNode is NULL
2068 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2070 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2071 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2072 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2074 // Compute the radius is not needed, square radius it's enough.
2075 const Vector3& size( mNode->GetSize( bufferIndex ) );
2077 // Scale the sphere.
2078 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2080 const float width = size.width * scale.width;
2081 const float height = size.height * scale.height;
2083 float squareSphereRadius = 0.5f * ( width * width + height * height );
2085 float a = rayDir.Dot( rayDir ); // a
2086 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2087 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2089 return ( b2 * b2 - a * c ) >= 0.f;
2092 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2099 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2101 // Transforms the ray to the local reference system.
2103 // Calculate the inverse of Model matrix
2104 Matrix invModelMatrix( false/*don't init*/);
2105 // need to use the components as world matrix is only updated for actors that need it
2106 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2108 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2109 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2111 // Test with the actor's XY plane (Normal = 0 0 1 1).
2113 float a = -rayOriginLocal.z;
2114 float b = rayDirLocal.z;
2116 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2118 // Ray travels distance * rayDirLocal to intersect with plane.
2121 const Vector3& size = mNode->GetSize( bufferIndex );
2123 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2124 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2126 // Test with the actor's geometry.
2127 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2134 void Actor::SetLeaveRequired( bool required )
2136 mLeaveRequired = required;
2139 bool Actor::GetLeaveRequired() const
2141 return mLeaveRequired;
2144 void Actor::SetKeyboardFocusable( bool focusable )
2146 mKeyboardFocusable = focusable;
2149 bool Actor::IsKeyboardFocusable() const
2151 return mKeyboardFocusable;
2154 bool Actor::GetTouchRequired() const
2156 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2159 bool Actor::GetHoverRequired() const
2161 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2164 bool Actor::GetWheelEventRequired() const
2166 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2169 bool Actor::IsHittable() const
2171 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2174 ActorGestureData& Actor::GetGestureData()
2176 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2177 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2178 if( NULL == mGestureData )
2180 mGestureData = new ActorGestureData;
2182 return *mGestureData;
2185 bool Actor::IsGestureRequred( Gesture::Type type ) const
2187 return mGestureData && mGestureData->IsGestureRequred( type );
2190 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2192 bool consumed = false;
2194 if( !mTouchedSignal.Empty() )
2196 Dali::Actor handle( this );
2197 consumed = mTouchedSignal.Emit( handle, event );
2202 // Notification for derived classes
2203 consumed = OnTouchEvent( event );
2209 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2211 bool consumed = false;
2213 if( !mHoveredSignal.Empty() )
2215 Dali::Actor handle( this );
2216 consumed = mHoveredSignal.Emit( handle, event );
2221 // Notification for derived classes
2222 consumed = OnHoverEvent( event );
2228 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2230 bool consumed = false;
2232 if( !mWheelEventSignal.Empty() )
2234 Dali::Actor handle( this );
2235 consumed = mWheelEventSignal.Emit( handle, event );
2240 // Notification for derived classes
2241 consumed = OnWheelEvent( event );
2247 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2249 return mTouchedSignal;
2252 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2254 return mHoveredSignal;
2257 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2259 return mWheelEventSignal;
2262 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2264 return mOnStageSignal;
2267 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2269 return mOffStageSignal;
2272 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2274 return mOnRelayoutSignal;
2277 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2279 bool connected( true );
2280 Actor* actor = dynamic_cast< Actor* >( object );
2282 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2284 actor->TouchedSignal().Connect( tracker, functor );
2286 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2288 actor->HoveredSignal().Connect( tracker, functor );
2290 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2292 actor->WheelEventSignal().Connect( tracker, functor );
2294 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2296 actor->OnStageSignal().Connect( tracker, functor );
2298 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2300 actor->OffStageSignal().Connect( tracker, functor );
2304 // signalName does not match any signal
2311 Actor::Actor( DerivedType derivedType )
2315 mParentOrigin( NULL ),
2316 mAnchorPoint( NULL ),
2317 mRelayoutData( NULL ),
2318 #ifdef DALI_DYNAMICS_SUPPORT
2319 mDynamicsData( NULL ),
2321 mGestureData( NULL ),
2323 mTargetSize( 0.0f, 0.0f, 0.0f ),
2325 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2327 mIsRoot( ROOT_LAYER == derivedType ),
2328 mIsRenderable( RENDERABLE == derivedType ),
2329 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2330 mIsOnStage( false ),
2331 mIsDynamicsRoot( false ),
2333 mLeaveRequired( false ),
2334 mKeyboardFocusable( false ),
2335 mDerivedRequiresTouch( false ),
2336 mDerivedRequiresHover( false ),
2337 mDerivedRequiresWheelEvent( false ),
2338 mOnStageSignalled( false ),
2339 mInsideOnSizeSet( false ),
2340 mInheritOrientation( true ),
2341 mInheritScale( true ),
2342 mDrawMode( DrawMode::NORMAL ),
2343 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2344 mColorMode( Node::DEFAULT_COLOR_MODE )
2348 void Actor::Initialize()
2351 SceneGraph::Node* node = CreateNode();
2353 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2354 mNode = node; // Keep raw-pointer to Node
2358 GetEventThreadServices().RegisterObject( this );
2363 // Remove mParent pointers from children even if we're destroying core,
2364 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2367 ActorConstIter endIter = mChildren->end();
2368 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2370 (*iter)->SetParent( NULL );
2375 // Guard to allow handle destruction after Core has been destroyed
2376 if( EventThreadServices::IsCoreRunning() )
2380 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2381 mNode = NULL; // Node is about to be destroyed
2384 GetEventThreadServices().UnregisterObject( this );
2387 #ifdef DALI_DYNAMICS_SUPPORT
2389 delete mDynamicsData;
2392 // Cleanup optional gesture data
2393 delete mGestureData;
2395 // Cleanup optional parent origin and anchor
2396 delete mParentOrigin;
2397 delete mAnchorPoint;
2399 // Delete optional relayout data
2402 delete mRelayoutData;
2406 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2408 // This container is used instead of walking the Actor hierachy.
2409 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2410 ActorContainer connectionList;
2413 // This stage is atomic i.e. not interrupted by user callbacks
2414 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2416 // Notify applications about the newly connected actors.
2417 const ActorIter endIter = connectionList.end();
2418 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2420 (*iter)->NotifyStageConnection();
2426 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2428 DALI_ASSERT_ALWAYS( !OnStage() );
2433 ConnectToSceneGraph( index );
2435 // Notification for internal derived classes
2436 OnStageConnectionInternal();
2438 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2439 connectionList.push_back( ActorPtr( this ) );
2441 // Recursively connect children
2444 ActorConstIter endIter = mChildren->end();
2445 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2447 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2453 * This method is called when the Actor is connected to the Stage.
2454 * The parent must have added its Node to the scene-graph.
2455 * The child must connect its Node to the parent's Node.
2456 * This is resursive; the child calls ConnectToStage() for its children.
2458 void Actor::ConnectToSceneGraph( int index )
2460 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2464 // Reparent Node in next Update
2465 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2468 // Notify attachment
2471 mAttachment->Connect();
2474 #ifdef DALI_DYNAMICS_SUPPORT
2476 if( NULL != mDynamicsData )
2482 // Request relayout on all actors that are added to the scenegraph
2485 // Notification for Object::Observers
2489 void Actor::NotifyStageConnection()
2491 // Actors can be removed (in a callback), before the on-stage stage is reported.
2492 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2493 if( OnStage() && !mOnStageSignalled )
2495 // Notification for external (CustomActor) derived classes
2496 OnStageConnectionExternal( mDepth );
2498 if( !mOnStageSignal.Empty() )
2500 Dali::Actor handle( this );
2501 mOnStageSignal.Emit( handle );
2504 // Guard against Remove during callbacks
2507 mOnStageSignalled = true; // signal required next time Actor is removed
2512 void Actor::DisconnectFromStage()
2514 // This container is used instead of walking the Actor hierachy.
2515 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2516 ActorContainer disconnectionList;
2518 // This stage is atomic i.e. not interrupted by user callbacks
2519 RecursiveDisconnectFromStage( disconnectionList );
2521 // Notify applications about the newly disconnected actors.
2522 const ActorIter endIter = disconnectionList.end();
2523 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2525 (*iter)->NotifyStageDisconnection();
2529 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2531 DALI_ASSERT_ALWAYS( OnStage() );
2533 // Recursively disconnect children
2536 ActorConstIter endIter = mChildren->end();
2537 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2539 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2543 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2544 disconnectionList.push_back( ActorPtr( this ) );
2546 // Notification for internal derived classes
2547 OnStageDisconnectionInternal();
2549 DisconnectFromSceneGraph();
2555 * This method is called by an actor or its parent, before a node removal message is sent.
2556 * This is recursive; the child calls DisconnectFromStage() for its children.
2558 void Actor::DisconnectFromSceneGraph()
2560 // Notification for Object::Observers
2561 OnSceneObjectRemove();
2563 // Notify attachment
2566 mAttachment->Disconnect();
2569 #ifdef DALI_DYNAMICS_SUPPORT
2571 if( NULL != mDynamicsData )
2573 DisconnectDynamics();
2578 void Actor::NotifyStageDisconnection()
2580 // Actors can be added (in a callback), before the off-stage state is reported.
2581 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2582 // only do this step if there is a stage, i.e. Core is not being shut down
2583 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2585 // Notification for external (CustomeActor) derived classes
2586 OnStageDisconnectionExternal();
2588 if( !mOffStageSignal.Empty() )
2590 Dali::Actor handle( this );
2591 mOffStageSignal.Emit( handle );
2594 // Guard against Add during callbacks
2597 mOnStageSignalled = false; // signal required next time Actor is added
2602 bool Actor::IsNodeConnected() const
2604 bool connected( false );
2609 if( mNode->IsRoot() || mNode->GetParent() )
2618 unsigned int Actor::GetDefaultPropertyCount() const
2620 return DEFAULT_PROPERTY_COUNT;
2623 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2625 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2627 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2629 indices.PushBack( i );
2633 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2635 if( index < DEFAULT_PROPERTY_COUNT )
2637 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2643 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2645 Property::Index index = Property::INVALID_INDEX;
2647 // Look for name in default properties
2648 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2650 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2651 if( 0 == name.compare( property->name ) )
2661 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2663 if( index < DEFAULT_PROPERTY_COUNT )
2665 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2671 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2673 if( index < DEFAULT_PROPERTY_COUNT )
2675 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2681 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2683 if( index < DEFAULT_PROPERTY_COUNT )
2685 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2691 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2693 if( index < DEFAULT_PROPERTY_COUNT )
2695 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2698 // index out of range...return Property::NONE
2699 return Property::NONE;
2702 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2706 case Dali::Actor::Property::PARENT_ORIGIN:
2708 SetParentOrigin( property.Get< Vector3 >() );
2712 case Dali::Actor::Property::PARENT_ORIGIN_X:
2714 SetParentOriginX( property.Get< float >() );
2718 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2720 SetParentOriginY( property.Get< float >() );
2724 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2726 SetParentOriginZ( property.Get< float >() );
2730 case Dali::Actor::Property::ANCHOR_POINT:
2732 SetAnchorPoint( property.Get< Vector3 >() );
2736 case Dali::Actor::Property::ANCHOR_POINT_X:
2738 SetAnchorPointX( property.Get< float >() );
2742 case Dali::Actor::Property::ANCHOR_POINT_Y:
2744 SetAnchorPointY( property.Get< float >() );
2748 case Dali::Actor::Property::ANCHOR_POINT_Z:
2750 SetAnchorPointZ( property.Get< float >() );
2754 case Dali::Actor::Property::SIZE:
2756 SetSize( property.Get< Vector3 >() );
2760 case Dali::Actor::Property::SIZE_WIDTH:
2762 SetWidth( property.Get< float >() );
2766 case Dali::Actor::Property::SIZE_HEIGHT:
2768 SetHeight( property.Get< float >() );
2772 case Dali::Actor::Property::SIZE_DEPTH:
2774 SetDepth( property.Get< float >() );
2778 case Dali::Actor::Property::POSITION:
2780 SetPosition( property.Get< Vector3 >() );
2784 case Dali::Actor::Property::POSITION_X:
2786 SetX( property.Get< float >() );
2790 case Dali::Actor::Property::POSITION_Y:
2792 SetY( property.Get< float >() );
2796 case Dali::Actor::Property::POSITION_Z:
2798 SetZ( property.Get< float >() );
2802 case Dali::Actor::Property::ORIENTATION:
2804 SetOrientation( property.Get< Quaternion >() );
2808 case Dali::Actor::Property::SCALE:
2810 SetScale( property.Get< Vector3 >() );
2814 case Dali::Actor::Property::SCALE_X:
2816 SetScaleX( property.Get< float >() );
2820 case Dali::Actor::Property::SCALE_Y:
2822 SetScaleY( property.Get< float >() );
2826 case Dali::Actor::Property::SCALE_Z:
2828 SetScaleZ( property.Get< float >() );
2832 case Dali::Actor::Property::VISIBLE:
2834 SetVisible( property.Get< bool >() );
2838 case Dali::Actor::Property::COLOR:
2840 SetColor( property.Get< Vector4 >() );
2844 case Dali::Actor::Property::COLOR_RED:
2846 SetColorRed( property.Get< float >() );
2850 case Dali::Actor::Property::COLOR_GREEN:
2852 SetColorGreen( property.Get< float >() );
2856 case Dali::Actor::Property::COLOR_BLUE:
2858 SetColorBlue( property.Get< float >() );
2862 case Dali::Actor::Property::COLOR_ALPHA:
2864 SetOpacity( property.Get< float >() );
2868 case Dali::Actor::Property::NAME:
2870 SetName( property.Get< std::string >() );
2874 case Dali::Actor::Property::SENSITIVE:
2876 SetSensitive( property.Get< bool >() );
2880 case Dali::Actor::Property::LEAVE_REQUIRED:
2882 SetLeaveRequired( property.Get< bool >() );
2886 case Dali::Actor::Property::INHERIT_ORIENTATION:
2888 SetInheritOrientation( property.Get< bool >() );
2892 case Dali::Actor::Property::INHERIT_SCALE:
2894 SetInheritScale( property.Get< bool >() );
2898 case Dali::Actor::Property::COLOR_MODE:
2900 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2904 case Dali::Actor::Property::POSITION_INHERITANCE:
2906 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2910 case Dali::Actor::Property::DRAW_MODE:
2912 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2916 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2918 SetSizeModeFactor( property.Get< Vector3 >() );
2922 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2924 ResizePolicy::Type type;
2925 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2927 SetResizePolicy( type, Dimension::WIDTH );
2932 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2934 ResizePolicy::Type type;
2935 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2937 SetResizePolicy( type, Dimension::HEIGHT );
2942 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2944 SizeScalePolicy::Type type;
2945 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2947 SetSizeScalePolicy( type );
2952 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2954 if( property.Get< bool >() )
2956 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2961 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2963 if( property.Get< bool >() )
2965 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2970 case Dali::Actor::Property::PADDING:
2972 Vector4 padding = property.Get< Vector4 >();
2973 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2974 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2978 case Dali::Actor::Property::MINIMUM_SIZE:
2980 Vector2 size = property.Get< Vector2 >();
2981 SetMinimumSize( size.x, Dimension::WIDTH );
2982 SetMinimumSize( size.y, Dimension::HEIGHT );
2986 case Dali::Actor::Property::MAXIMUM_SIZE:
2988 Vector2 size = property.Get< Vector2 >();
2989 SetMaximumSize( size.x, Dimension::WIDTH );
2990 SetMaximumSize( size.y, Dimension::HEIGHT );
2996 // this can happen in the case of a non-animatable default property so just do nothing
3002 // TODO: This method needs to be removed
3003 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3005 switch( entry.type )
3007 case Property::BOOLEAN:
3009 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3010 DALI_ASSERT_DEBUG( NULL != property );
3012 // property is being used in a separate thread; queue a message to set the property
3013 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3018 case Property::INTEGER:
3020 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3021 DALI_ASSERT_DEBUG( NULL != property );
3023 // property is being used in a separate thread; queue a message to set the property
3024 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3029 case Property::FLOAT:
3031 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3032 DALI_ASSERT_DEBUG( NULL != property );
3034 // property is being used in a separate thread; queue a message to set the property
3035 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3040 case Property::VECTOR2:
3042 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3043 DALI_ASSERT_DEBUG( NULL != property );
3045 // property is being used in a separate thread; queue a message to set the property
3046 if(entry.componentIndex == 0)
3048 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3050 else if(entry.componentIndex == 1)
3052 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3056 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3062 case Property::VECTOR3:
3064 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3065 DALI_ASSERT_DEBUG( NULL != property );
3067 // property is being used in a separate thread; queue a message to set the property
3068 if(entry.componentIndex == 0)
3070 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3072 else if(entry.componentIndex == 1)
3074 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3076 else if(entry.componentIndex == 2)
3078 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3082 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3088 case Property::VECTOR4:
3090 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3091 DALI_ASSERT_DEBUG( NULL != property );
3093 // property is being used in a separate thread; queue a message to set the property
3094 if(entry.componentIndex == 0)
3096 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3098 else if(entry.componentIndex == 1)
3100 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3102 else if(entry.componentIndex == 2)
3104 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3106 else if(entry.componentIndex == 3)
3108 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3112 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3118 case Property::ROTATION:
3120 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3121 DALI_ASSERT_DEBUG( NULL != property );
3123 // property is being used in a separate thread; queue a message to set the property
3124 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3129 case Property::MATRIX:
3131 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3132 DALI_ASSERT_DEBUG( NULL != property );
3134 // property is being used in a separate thread; queue a message to set the property
3135 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3140 case Property::MATRIX3:
3142 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3143 DALI_ASSERT_DEBUG( NULL != property );
3145 // property is being used in a separate thread; queue a message to set the property
3146 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3153 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3159 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3161 Property::Value value;
3165 case Dali::Actor::Property::PARENT_ORIGIN:
3167 value = GetCurrentParentOrigin();
3171 case Dali::Actor::Property::PARENT_ORIGIN_X:
3173 value = GetCurrentParentOrigin().x;
3177 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3179 value = GetCurrentParentOrigin().y;
3183 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3185 value = GetCurrentParentOrigin().z;
3189 case Dali::Actor::Property::ANCHOR_POINT:
3191 value = GetCurrentAnchorPoint();
3195 case Dali::Actor::Property::ANCHOR_POINT_X:
3197 value = GetCurrentAnchorPoint().x;
3201 case Dali::Actor::Property::ANCHOR_POINT_Y:
3203 value = GetCurrentAnchorPoint().y;
3207 case Dali::Actor::Property::ANCHOR_POINT_Z:
3209 value = GetCurrentAnchorPoint().z;
3213 case Dali::Actor::Property::SIZE:
3215 value = GetCurrentSize();
3219 case Dali::Actor::Property::SIZE_WIDTH:
3221 value = GetCurrentSize().width;
3225 case Dali::Actor::Property::SIZE_HEIGHT:
3227 value = GetCurrentSize().height;
3231 case Dali::Actor::Property::SIZE_DEPTH:
3233 value = GetCurrentSize().depth;
3237 case Dali::Actor::Property::POSITION:
3239 value = GetCurrentPosition();
3243 case Dali::Actor::Property::POSITION_X:
3245 value = GetCurrentPosition().x;
3249 case Dali::Actor::Property::POSITION_Y:
3251 value = GetCurrentPosition().y;
3255 case Dali::Actor::Property::POSITION_Z:
3257 value = GetCurrentPosition().z;
3261 case Dali::Actor::Property::WORLD_POSITION:
3263 value = GetCurrentWorldPosition();
3267 case Dali::Actor::Property::WORLD_POSITION_X:
3269 value = GetCurrentWorldPosition().x;
3273 case Dali::Actor::Property::WORLD_POSITION_Y:
3275 value = GetCurrentWorldPosition().y;
3279 case Dali::Actor::Property::WORLD_POSITION_Z:
3281 value = GetCurrentWorldPosition().z;
3285 case Dali::Actor::Property::ORIENTATION:
3287 value = GetCurrentOrientation();
3291 case Dali::Actor::Property::WORLD_ORIENTATION:
3293 value = GetCurrentWorldOrientation();
3297 case Dali::Actor::Property::SCALE:
3299 value = GetCurrentScale();
3303 case Dali::Actor::Property::SCALE_X:
3305 value = GetCurrentScale().x;
3309 case Dali::Actor::Property::SCALE_Y:
3311 value = GetCurrentScale().y;
3315 case Dali::Actor::Property::SCALE_Z:
3317 value = GetCurrentScale().z;
3321 case Dali::Actor::Property::WORLD_SCALE:
3323 value = GetCurrentWorldScale();
3327 case Dali::Actor::Property::VISIBLE:
3329 value = IsVisible();
3333 case Dali::Actor::Property::COLOR:
3335 value = GetCurrentColor();
3339 case Dali::Actor::Property::COLOR_RED:
3341 value = GetCurrentColor().r;
3345 case Dali::Actor::Property::COLOR_GREEN:
3347 value = GetCurrentColor().g;
3351 case Dali::Actor::Property::COLOR_BLUE:
3353 value = GetCurrentColor().b;
3357 case Dali::Actor::Property::COLOR_ALPHA:
3359 value = GetCurrentColor().a;
3363 case Dali::Actor::Property::WORLD_COLOR:
3365 value = GetCurrentWorldColor();
3369 case Dali::Actor::Property::WORLD_MATRIX:
3371 value = GetCurrentWorldMatrix();
3375 case Dali::Actor::Property::NAME:
3381 case Dali::Actor::Property::SENSITIVE:
3383 value = IsSensitive();
3387 case Dali::Actor::Property::LEAVE_REQUIRED:
3389 value = GetLeaveRequired();
3393 case Dali::Actor::Property::INHERIT_ORIENTATION:
3395 value = IsOrientationInherited();
3399 case Dali::Actor::Property::INHERIT_SCALE:
3401 value = IsScaleInherited();
3405 case Dali::Actor::Property::COLOR_MODE:
3407 value = Scripting::GetColorMode( GetColorMode() );
3411 case Dali::Actor::Property::POSITION_INHERITANCE:
3413 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3417 case Dali::Actor::Property::DRAW_MODE:
3419 value = Scripting::GetDrawMode( GetDrawMode() );
3423 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3425 value = GetSizeModeFactor();
3429 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3431 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3435 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3437 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3441 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3443 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3447 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3449 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3453 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3455 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3459 case Dali::Actor::Property::PADDING:
3461 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3462 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3463 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3467 case Dali::Actor::Property::MINIMUM_SIZE:
3469 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3473 case Dali::Actor::Property::MAXIMUM_SIZE:
3475 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3481 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3489 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3494 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3496 // This method should only return an object connected to the scene-graph
3497 return OnStage() ? mNode : NULL;
3500 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3502 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3504 const PropertyBase* property( NULL );
3506 // This method should only return a property of an object connected to the scene-graph
3512 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3514 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3515 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3517 property = animatable->GetSceneGraphProperty();
3519 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3521 CustomPropertyMetadata* custom = FindCustomProperty( index );
3522 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3524 property = custom->GetSceneGraphProperty();
3526 else if( NULL != mNode )
3530 case Dali::Actor::Property::SIZE:
3531 property = &mNode->mSize;
3534 case Dali::Actor::Property::SIZE_WIDTH:
3535 property = &mNode->mSize;
3538 case Dali::Actor::Property::SIZE_HEIGHT:
3539 property = &mNode->mSize;
3542 case Dali::Actor::Property::SIZE_DEPTH:
3543 property = &mNode->mSize;
3546 case Dali::Actor::Property::POSITION:
3547 property = &mNode->mPosition;
3550 case Dali::Actor::Property::POSITION_X:
3551 property = &mNode->mPosition;
3554 case Dali::Actor::Property::POSITION_Y:
3555 property = &mNode->mPosition;
3558 case Dali::Actor::Property::POSITION_Z:
3559 property = &mNode->mPosition;
3562 case Dali::Actor::Property::ORIENTATION:
3563 property = &mNode->mOrientation;
3566 case Dali::Actor::Property::SCALE:
3567 property = &mNode->mScale;
3570 case Dali::Actor::Property::SCALE_X:
3571 property = &mNode->mScale;
3574 case Dali::Actor::Property::SCALE_Y:
3575 property = &mNode->mScale;
3578 case Dali::Actor::Property::SCALE_Z:
3579 property = &mNode->mScale;
3582 case Dali::Actor::Property::VISIBLE:
3583 property = &mNode->mVisible;
3586 case Dali::Actor::Property::COLOR:
3587 property = &mNode->mColor;
3590 case Dali::Actor::Property::COLOR_RED:
3591 property = &mNode->mColor;
3594 case Dali::Actor::Property::COLOR_GREEN:
3595 property = &mNode->mColor;
3598 case Dali::Actor::Property::COLOR_BLUE:
3599 property = &mNode->mColor;
3602 case Dali::Actor::Property::COLOR_ALPHA:
3603 property = &mNode->mColor;
3614 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3616 const PropertyInputImpl* property( NULL );
3618 // This method should only return a property of an object connected to the scene-graph
3624 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3626 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3627 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3629 property = animatable->GetSceneGraphProperty();
3631 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3633 CustomPropertyMetadata* custom = FindCustomProperty( index );
3634 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3635 property = custom->GetSceneGraphProperty();
3637 else if( NULL != mNode )
3641 case Dali::Actor::Property::PARENT_ORIGIN:
3642 property = &mNode->mParentOrigin;
3645 case Dali::Actor::Property::PARENT_ORIGIN_X:
3646 property = &mNode->mParentOrigin;
3649 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3650 property = &mNode->mParentOrigin;
3653 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3654 property = &mNode->mParentOrigin;
3657 case Dali::Actor::Property::ANCHOR_POINT:
3658 property = &mNode->mAnchorPoint;
3661 case Dali::Actor::Property::ANCHOR_POINT_X:
3662 property = &mNode->mAnchorPoint;
3665 case Dali::Actor::Property::ANCHOR_POINT_Y:
3666 property = &mNode->mAnchorPoint;
3669 case Dali::Actor::Property::ANCHOR_POINT_Z:
3670 property = &mNode->mAnchorPoint;
3673 case Dali::Actor::Property::SIZE:
3674 property = &mNode->mSize;
3677 case Dali::Actor::Property::SIZE_WIDTH:
3678 property = &mNode->mSize;
3681 case Dali::Actor::Property::SIZE_HEIGHT:
3682 property = &mNode->mSize;
3685 case Dali::Actor::Property::SIZE_DEPTH:
3686 property = &mNode->mSize;
3689 case Dali::Actor::Property::POSITION:
3690 property = &mNode->mPosition;
3693 case Dali::Actor::Property::POSITION_X:
3694 property = &mNode->mPosition;
3697 case Dali::Actor::Property::POSITION_Y:
3698 property = &mNode->mPosition;
3701 case Dali::Actor::Property::POSITION_Z:
3702 property = &mNode->mPosition;
3705 case Dali::Actor::Property::WORLD_POSITION:
3706 property = &mNode->mWorldPosition;
3709 case Dali::Actor::Property::WORLD_POSITION_X:
3710 property = &mNode->mWorldPosition;
3713 case Dali::Actor::Property::WORLD_POSITION_Y:
3714 property = &mNode->mWorldPosition;
3717 case Dali::Actor::Property::WORLD_POSITION_Z:
3718 property = &mNode->mWorldPosition;
3721 case Dali::Actor::Property::ORIENTATION:
3722 property = &mNode->mOrientation;
3725 case Dali::Actor::Property::WORLD_ORIENTATION:
3726 property = &mNode->mWorldOrientation;
3729 case Dali::Actor::Property::SCALE:
3730 property = &mNode->mScale;
3733 case Dali::Actor::Property::SCALE_X:
3734 property = &mNode->mScale;
3737 case Dali::Actor::Property::SCALE_Y:
3738 property = &mNode->mScale;
3741 case Dali::Actor::Property::SCALE_Z:
3742 property = &mNode->mScale;
3745 case Dali::Actor::Property::WORLD_SCALE:
3746 property = &mNode->mWorldScale;
3749 case Dali::Actor::Property::VISIBLE:
3750 property = &mNode->mVisible;
3753 case Dali::Actor::Property::COLOR:
3754 property = &mNode->mColor;
3757 case Dali::Actor::Property::COLOR_RED:
3758 property = &mNode->mColor;
3761 case Dali::Actor::Property::COLOR_GREEN:
3762 property = &mNode->mColor;
3765 case Dali::Actor::Property::COLOR_BLUE:
3766 property = &mNode->mColor;
3769 case Dali::Actor::Property::COLOR_ALPHA:
3770 property = &mNode->mColor;
3773 case Dali::Actor::Property::WORLD_COLOR:
3774 property = &mNode->mWorldColor;
3777 case Dali::Actor::Property::WORLD_MATRIX:
3778 property = &mNode->mWorldMatrix;
3789 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3791 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3793 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3795 // check whether the animatable property is registered already, if not then register one.
3796 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3797 if( animatableProperty )
3799 componentIndex = animatableProperty->componentIndex;
3806 case Dali::Actor::Property::PARENT_ORIGIN_X:
3807 case Dali::Actor::Property::ANCHOR_POINT_X:
3808 case Dali::Actor::Property::SIZE_WIDTH:
3809 case Dali::Actor::Property::POSITION_X:
3810 case Dali::Actor::Property::WORLD_POSITION_X:
3811 case Dali::Actor::Property::SCALE_X:
3812 case Dali::Actor::Property::COLOR_RED:
3818 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3819 case Dali::Actor::Property::ANCHOR_POINT_Y:
3820 case Dali::Actor::Property::SIZE_HEIGHT:
3821 case Dali::Actor::Property::POSITION_Y:
3822 case Dali::Actor::Property::WORLD_POSITION_Y:
3823 case Dali::Actor::Property::SCALE_Y:
3824 case Dali::Actor::Property::COLOR_GREEN:
3830 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3831 case Dali::Actor::Property::ANCHOR_POINT_Z:
3832 case Dali::Actor::Property::SIZE_DEPTH:
3833 case Dali::Actor::Property::POSITION_Z:
3834 case Dali::Actor::Property::WORLD_POSITION_Z:
3835 case Dali::Actor::Property::SCALE_Z:
3836 case Dali::Actor::Property::COLOR_BLUE:
3842 case Dali::Actor::Property::COLOR_ALPHA:
3856 return componentIndex;
3859 void Actor::SetParent( Actor* parent, int index )
3863 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3867 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3870 // Instruct each actor to create a corresponding node in the scene graph
3871 ConnectToStage( parent->GetHierarchyDepth(), index );
3874 else // parent being set to NULL
3876 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3880 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3883 DALI_ASSERT_ALWAYS( mNode != NULL );
3887 // Disconnect the Node & its children from the scene-graph.
3888 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3891 // Instruct each actor to discard pointers to the scene-graph
3892 DisconnectFromStage();
3897 SceneGraph::Node* Actor::CreateNode() const
3902 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3905 Actor* actor = dynamic_cast< Actor* >( object );
3909 if( 0 == actionName.compare( ACTION_SHOW ) )
3911 actor->SetVisible( true );
3914 else if( 0 == actionName.compare( ACTION_HIDE ) )
3916 actor->SetVisible( false );
3924 void Actor::EnsureRelayoutData()
3926 // Assign relayout data.
3927 if( !mRelayoutData )
3929 mRelayoutData = new RelayoutData();
3933 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3935 // Check if actor is dependent on parent
3936 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3938 if( ( dimension & ( 1 << i ) ) )
3940 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3941 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3951 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3953 // Check if actor is dependent on children
3954 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3956 if( ( dimension & ( 1 << i ) ) )
3958 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3959 switch( resizePolicy )
3961 case ResizePolicy::FIT_TO_CHILDREN:
3962 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3978 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3980 return Actor::RelayoutDependentOnChildren( dimension );
3983 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3985 // Check each possible dimension and see if it is dependent on the input one
3986 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3988 if( dimension & ( 1 << i ) )
3990 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3997 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3999 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4001 if( dimension & ( 1 << i ) )
4003 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4008 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4010 // If more than one dimension is requested, just return the first one found
4011 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4013 if( ( dimension & ( 1 << i ) ) )
4015 return mRelayoutData->negotiatedDimensions[ i ];
4019 return 0.0f; // Default
4022 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4024 EnsureRelayoutData();
4026 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4028 if( dimension & ( 1 << i ) )
4030 mRelayoutData->dimensionPadding[ i ] = padding;
4035 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4037 if ( mRelayoutData )
4039 // If more than one dimension is requested, just return the first one found
4040 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4042 if( ( dimension & ( 1 << i ) ) )
4044 return mRelayoutData->dimensionPadding[ i ];
4049 return GetDefaultDimensionPadding();
4052 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4054 EnsureRelayoutData();
4056 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4058 if( dimension & ( 1 << i ) )
4060 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4065 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4067 if ( mRelayoutData )
4069 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4071 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4081 float Actor::GetHeightForWidthBase( float width )
4083 float height = 0.0f;
4085 const Vector3 naturalSize = GetNaturalSize();
4086 if( naturalSize.width > 0.0f )
4088 height = naturalSize.height * width / naturalSize.width;
4090 else // we treat 0 as 1:1 aspect ratio
4098 float Actor::GetWidthForHeightBase( float height )
4102 const Vector3 naturalSize = GetNaturalSize();
4103 if( naturalSize.height > 0.0f )
4105 width = naturalSize.width * height / naturalSize.height;
4107 else // we treat 0 as 1:1 aspect ratio
4115 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4117 // Fill to parent, taking size mode factor into account
4118 switch( child.GetResizePolicy( dimension ) )
4120 case ResizePolicy::FILL_TO_PARENT:
4122 return GetLatestSize( dimension );
4125 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4127 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4130 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4132 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4137 return GetLatestSize( dimension );
4142 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4144 // Can be overridden in derived class
4145 return CalculateChildSizeBase( child, dimension );
4148 float Actor::GetHeightForWidth( float width )
4150 // Can be overridden in derived class
4151 return GetHeightForWidthBase( width );
4154 float Actor::GetWidthForHeight( float height )
4156 // Can be overridden in derived class
4157 return GetWidthForHeightBase( height );
4160 float Actor::GetLatestSize( Dimension::Type dimension ) const
4162 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4165 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4167 Vector2 padding = GetPadding( dimension );
4169 return GetLatestSize( dimension ) + padding.x + padding.y;
4172 float Actor::NegotiateFromParent( Dimension::Type dimension )
4174 Actor* parent = GetParent();
4177 Vector2 padding( GetPadding( dimension ) );
4178 Vector2 parentPadding( parent->GetPadding( dimension ) );
4179 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4185 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4187 float maxDimensionPoint = 0.0f;
4189 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4191 ActorPtr child = GetChildAt( i );
4193 if( !child->RelayoutDependentOnParent( dimension ) )
4195 // Calculate the min and max points that the children range across
4196 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4197 float dimensionSize = child->GetRelayoutSize( dimension );
4198 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4202 return maxDimensionPoint;
4205 float Actor::GetSize( Dimension::Type dimension ) const
4207 return GetDimensionValue( GetTargetSize(), dimension );
4210 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4212 return GetDimensionValue( GetNaturalSize(), dimension );
4215 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4217 switch( GetResizePolicy( dimension ) )
4219 case ResizePolicy::USE_NATURAL_SIZE:
4221 return GetNaturalSize( dimension );
4224 case ResizePolicy::FIXED:
4226 return GetDimensionValue( GetPreferredSize(), dimension );
4229 case ResizePolicy::USE_ASSIGNED_SIZE:
4231 return GetDimensionValue( maximumSize, dimension );
4234 case ResizePolicy::FILL_TO_PARENT:
4235 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4236 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4238 return NegotiateFromParent( dimension );
4241 case ResizePolicy::FIT_TO_CHILDREN:
4243 return NegotiateFromChildren( dimension );
4246 case ResizePolicy::DIMENSION_DEPENDENCY:
4248 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4251 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4253 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4256 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4258 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4270 return 0.0f; // Default
4273 float Actor::ClampDimension( float size, Dimension::Type dimension )
4275 const float minSize = GetMinimumSize( dimension );
4276 const float maxSize = GetMaximumSize( dimension );
4278 return std::max( minSize, std::min( size, maxSize ) );
4281 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4283 // Check if it needs to be negotiated
4284 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4286 // Check that we havn't gotten into an infinite loop
4287 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4288 bool recursionFound = false;
4289 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4291 if( *it == searchActor )
4293 recursionFound = true;
4298 if( !recursionFound )
4300 // Record the path that we have taken
4301 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4303 // Dimension dependency check
4304 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4306 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4308 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4310 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4314 // Parent dependency check
4315 Actor* parent = GetParent();
4316 if( parent && RelayoutDependentOnParent( dimension ) )
4318 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4321 // Children dependency check
4322 if( RelayoutDependentOnChildren( dimension ) )
4324 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4326 ActorPtr child = GetChildAt( i );
4328 // Only relayout child first if it is not dependent on this actor
4329 if( !child->RelayoutDependentOnParent( dimension ) )
4331 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4336 // For deriving classes
4337 OnCalculateRelayoutSize( dimension );
4339 // All dependencies checked, calculate the size and set negotiated flag
4340 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4342 SetNegotiatedDimension( newSize, dimension );
4343 SetLayoutNegotiated( true, dimension );
4345 // For deriving classes
4346 OnLayoutNegotiated( newSize, dimension );
4348 // This actor has been successfully processed, pop it off the recursion stack
4349 recursionStack.pop_back();
4353 // TODO: Break infinite loop
4354 SetLayoutNegotiated( true, dimension );
4359 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4361 // Negotiate all dimensions that require it
4362 ActorDimensionStack recursionStack;
4364 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4366 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4369 NegotiateDimension( dimension, allocatedSize, recursionStack );
4373 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4375 switch( mRelayoutData->sizeSetPolicy )
4377 case SizeScalePolicy::USE_SIZE_SET:
4382 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4384 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4385 const Vector3 naturalSize = GetNaturalSize();
4386 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4388 const float sizeRatio = size.width / size.height;
4389 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4391 if( naturalSizeRatio < sizeRatio )
4393 return Vector2( naturalSizeRatio * size.height, size.height );
4395 else if( naturalSizeRatio > sizeRatio )
4397 return Vector2( size.width, size.width / naturalSizeRatio );
4408 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4410 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4411 const Vector3 naturalSize = GetNaturalSize();
4412 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4414 const float sizeRatio = size.width / size.height;
4415 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4417 if( naturalSizeRatio < sizeRatio )
4419 return Vector2( size.width, size.width / naturalSizeRatio );
4421 else if( naturalSizeRatio > sizeRatio )
4423 return Vector2( naturalSizeRatio * size.height, size.height );
4441 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4443 // Do the set actor size
4444 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4446 // Adjust for size set policy
4447 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4449 // Lock the flag to stop recursive relayouts on set size
4450 mRelayoutData->insideRelayout = true;
4451 SetSize( negotiatedSize );
4452 mRelayoutData->insideRelayout = false;
4454 // Clear flags for all dimensions
4455 SetLayoutDirty( false );
4457 // Give deriving classes a chance to respond
4458 OnRelayout( negotiatedSize, container );
4460 if( !mOnRelayoutSignal.Empty() )
4462 Dali::Actor handle( this );
4463 mOnRelayoutSignal.Emit( handle );
4467 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4469 // Do the negotiation
4470 NegotiateDimensions( allocatedSize );
4472 // Set the actor size
4473 SetNegotiatedSize( container );
4475 // Negotiate down to children
4476 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4478 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4480 ActorPtr child = GetChildAt( i );
4482 // Only relayout if required
4483 if( child->RelayoutRequired() )
4485 container.Add( Dali::Actor( child.Get() ), newBounds );
4490 void Actor::RelayoutRequest( Dimension::Type dimension )
4492 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4493 if( relayoutController )
4495 Dali::Actor self( this );
4496 relayoutController->RequestRelayout( self, dimension );
4500 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4504 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4508 void Actor::SetPreferredSize( const Vector2& size )
4510 EnsureRelayoutData();
4512 if( size.width > 0.0f )
4514 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4517 if( size.height > 0.0f )
4519 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4522 mRelayoutData->preferredSize = size;
4527 Vector2 Actor::GetPreferredSize() const
4529 if ( mRelayoutData )
4531 return mRelayoutData->preferredSize;
4534 return GetDefaultPreferredSize();
4537 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4539 EnsureRelayoutData();
4541 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4543 if( dimension & ( 1 << i ) )
4545 mRelayoutData->minimumSize[ i ] = size;
4552 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4554 if ( mRelayoutData )
4556 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4558 if( dimension & ( 1 << i ) )
4560 return mRelayoutData->minimumSize[ i ];
4565 return 0.0f; // Default
4568 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4570 EnsureRelayoutData();
4572 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4574 if( dimension & ( 1 << i ) )
4576 mRelayoutData->maximumSize[ i ] = size;
4583 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4585 if ( mRelayoutData )
4587 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4589 if( dimension & ( 1 << i ) )
4591 return mRelayoutData->maximumSize[ i ];
4596 return FLT_MAX; // Default
4599 } // namespace Internal