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::UNSIGNED_INTEGER:
3031 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( 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<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3040 case Property::FLOAT:
3042 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3051 case Property::VECTOR2:
3053 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3054 DALI_ASSERT_DEBUG( NULL != property );
3056 // property is being used in a separate thread; queue a message to set the property
3057 if(entry.componentIndex == 0)
3059 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3061 else if(entry.componentIndex == 1)
3063 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3067 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3073 case Property::VECTOR3:
3075 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3076 DALI_ASSERT_DEBUG( NULL != property );
3078 // property is being used in a separate thread; queue a message to set the property
3079 if(entry.componentIndex == 0)
3081 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3083 else if(entry.componentIndex == 1)
3085 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3087 else if(entry.componentIndex == 2)
3089 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3093 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3099 case Property::VECTOR4:
3101 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3102 DALI_ASSERT_DEBUG( NULL != property );
3104 // property is being used in a separate thread; queue a message to set the property
3105 if(entry.componentIndex == 0)
3107 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3109 else if(entry.componentIndex == 1)
3111 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3113 else if(entry.componentIndex == 2)
3115 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3117 else if(entry.componentIndex == 3)
3119 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3123 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3129 case Property::ROTATION:
3131 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( 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<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3140 case Property::MATRIX:
3142 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( 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<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3151 case Property::MATRIX3:
3153 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3154 DALI_ASSERT_DEBUG( NULL != property );
3156 // property is being used in a separate thread; queue a message to set the property
3157 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3164 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3170 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3172 Property::Value value;
3176 case Dali::Actor::Property::PARENT_ORIGIN:
3178 value = GetCurrentParentOrigin();
3182 case Dali::Actor::Property::PARENT_ORIGIN_X:
3184 value = GetCurrentParentOrigin().x;
3188 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3190 value = GetCurrentParentOrigin().y;
3194 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3196 value = GetCurrentParentOrigin().z;
3200 case Dali::Actor::Property::ANCHOR_POINT:
3202 value = GetCurrentAnchorPoint();
3206 case Dali::Actor::Property::ANCHOR_POINT_X:
3208 value = GetCurrentAnchorPoint().x;
3212 case Dali::Actor::Property::ANCHOR_POINT_Y:
3214 value = GetCurrentAnchorPoint().y;
3218 case Dali::Actor::Property::ANCHOR_POINT_Z:
3220 value = GetCurrentAnchorPoint().z;
3224 case Dali::Actor::Property::SIZE:
3226 value = GetCurrentSize();
3230 case Dali::Actor::Property::SIZE_WIDTH:
3232 value = GetCurrentSize().width;
3236 case Dali::Actor::Property::SIZE_HEIGHT:
3238 value = GetCurrentSize().height;
3242 case Dali::Actor::Property::SIZE_DEPTH:
3244 value = GetCurrentSize().depth;
3248 case Dali::Actor::Property::POSITION:
3250 value = GetCurrentPosition();
3254 case Dali::Actor::Property::POSITION_X:
3256 value = GetCurrentPosition().x;
3260 case Dali::Actor::Property::POSITION_Y:
3262 value = GetCurrentPosition().y;
3266 case Dali::Actor::Property::POSITION_Z:
3268 value = GetCurrentPosition().z;
3272 case Dali::Actor::Property::WORLD_POSITION:
3274 value = GetCurrentWorldPosition();
3278 case Dali::Actor::Property::WORLD_POSITION_X:
3280 value = GetCurrentWorldPosition().x;
3284 case Dali::Actor::Property::WORLD_POSITION_Y:
3286 value = GetCurrentWorldPosition().y;
3290 case Dali::Actor::Property::WORLD_POSITION_Z:
3292 value = GetCurrentWorldPosition().z;
3296 case Dali::Actor::Property::ORIENTATION:
3298 value = GetCurrentOrientation();
3302 case Dali::Actor::Property::WORLD_ORIENTATION:
3304 value = GetCurrentWorldOrientation();
3308 case Dali::Actor::Property::SCALE:
3310 value = GetCurrentScale();
3314 case Dali::Actor::Property::SCALE_X:
3316 value = GetCurrentScale().x;
3320 case Dali::Actor::Property::SCALE_Y:
3322 value = GetCurrentScale().y;
3326 case Dali::Actor::Property::SCALE_Z:
3328 value = GetCurrentScale().z;
3332 case Dali::Actor::Property::WORLD_SCALE:
3334 value = GetCurrentWorldScale();
3338 case Dali::Actor::Property::VISIBLE:
3340 value = IsVisible();
3344 case Dali::Actor::Property::COLOR:
3346 value = GetCurrentColor();
3350 case Dali::Actor::Property::COLOR_RED:
3352 value = GetCurrentColor().r;
3356 case Dali::Actor::Property::COLOR_GREEN:
3358 value = GetCurrentColor().g;
3362 case Dali::Actor::Property::COLOR_BLUE:
3364 value = GetCurrentColor().b;
3368 case Dali::Actor::Property::COLOR_ALPHA:
3370 value = GetCurrentColor().a;
3374 case Dali::Actor::Property::WORLD_COLOR:
3376 value = GetCurrentWorldColor();
3380 case Dali::Actor::Property::WORLD_MATRIX:
3382 value = GetCurrentWorldMatrix();
3386 case Dali::Actor::Property::NAME:
3392 case Dali::Actor::Property::SENSITIVE:
3394 value = IsSensitive();
3398 case Dali::Actor::Property::LEAVE_REQUIRED:
3400 value = GetLeaveRequired();
3404 case Dali::Actor::Property::INHERIT_ORIENTATION:
3406 value = IsOrientationInherited();
3410 case Dali::Actor::Property::INHERIT_SCALE:
3412 value = IsScaleInherited();
3416 case Dali::Actor::Property::COLOR_MODE:
3418 value = Scripting::GetColorMode( GetColorMode() );
3422 case Dali::Actor::Property::POSITION_INHERITANCE:
3424 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3428 case Dali::Actor::Property::DRAW_MODE:
3430 value = Scripting::GetDrawMode( GetDrawMode() );
3434 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3436 value = GetSizeModeFactor();
3440 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3442 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3446 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3448 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3452 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3454 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3458 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3460 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3464 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3466 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3470 case Dali::Actor::Property::PADDING:
3472 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3473 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3474 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3478 case Dali::Actor::Property::MINIMUM_SIZE:
3480 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3484 case Dali::Actor::Property::MAXIMUM_SIZE:
3486 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3492 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3500 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3505 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3507 // This method should only return an object connected to the scene-graph
3508 return OnStage() ? mNode : NULL;
3511 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3513 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3515 const PropertyBase* property( NULL );
3517 // This method should only return a property of an object connected to the scene-graph
3523 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3525 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3526 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3528 property = animatable->GetSceneGraphProperty();
3530 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3532 CustomPropertyMetadata* custom = FindCustomProperty( index );
3533 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3535 property = custom->GetSceneGraphProperty();
3537 else if( NULL != mNode )
3541 case Dali::Actor::Property::SIZE:
3542 property = &mNode->mSize;
3545 case Dali::Actor::Property::SIZE_WIDTH:
3546 property = &mNode->mSize;
3549 case Dali::Actor::Property::SIZE_HEIGHT:
3550 property = &mNode->mSize;
3553 case Dali::Actor::Property::SIZE_DEPTH:
3554 property = &mNode->mSize;
3557 case Dali::Actor::Property::POSITION:
3558 property = &mNode->mPosition;
3561 case Dali::Actor::Property::POSITION_X:
3562 property = &mNode->mPosition;
3565 case Dali::Actor::Property::POSITION_Y:
3566 property = &mNode->mPosition;
3569 case Dali::Actor::Property::POSITION_Z:
3570 property = &mNode->mPosition;
3573 case Dali::Actor::Property::ORIENTATION:
3574 property = &mNode->mOrientation;
3577 case Dali::Actor::Property::SCALE:
3578 property = &mNode->mScale;
3581 case Dali::Actor::Property::SCALE_X:
3582 property = &mNode->mScale;
3585 case Dali::Actor::Property::SCALE_Y:
3586 property = &mNode->mScale;
3589 case Dali::Actor::Property::SCALE_Z:
3590 property = &mNode->mScale;
3593 case Dali::Actor::Property::VISIBLE:
3594 property = &mNode->mVisible;
3597 case Dali::Actor::Property::COLOR:
3598 property = &mNode->mColor;
3601 case Dali::Actor::Property::COLOR_RED:
3602 property = &mNode->mColor;
3605 case Dali::Actor::Property::COLOR_GREEN:
3606 property = &mNode->mColor;
3609 case Dali::Actor::Property::COLOR_BLUE:
3610 property = &mNode->mColor;
3613 case Dali::Actor::Property::COLOR_ALPHA:
3614 property = &mNode->mColor;
3625 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3627 const PropertyInputImpl* property( NULL );
3629 // This method should only return a property of an object connected to the scene-graph
3635 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3637 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3638 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3640 property = animatable->GetSceneGraphProperty();
3642 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3644 CustomPropertyMetadata* custom = FindCustomProperty( index );
3645 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3646 property = custom->GetSceneGraphProperty();
3648 else if( NULL != mNode )
3652 case Dali::Actor::Property::PARENT_ORIGIN:
3653 property = &mNode->mParentOrigin;
3656 case Dali::Actor::Property::PARENT_ORIGIN_X:
3657 property = &mNode->mParentOrigin;
3660 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3661 property = &mNode->mParentOrigin;
3664 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3665 property = &mNode->mParentOrigin;
3668 case Dali::Actor::Property::ANCHOR_POINT:
3669 property = &mNode->mAnchorPoint;
3672 case Dali::Actor::Property::ANCHOR_POINT_X:
3673 property = &mNode->mAnchorPoint;
3676 case Dali::Actor::Property::ANCHOR_POINT_Y:
3677 property = &mNode->mAnchorPoint;
3680 case Dali::Actor::Property::ANCHOR_POINT_Z:
3681 property = &mNode->mAnchorPoint;
3684 case Dali::Actor::Property::SIZE:
3685 property = &mNode->mSize;
3688 case Dali::Actor::Property::SIZE_WIDTH:
3689 property = &mNode->mSize;
3692 case Dali::Actor::Property::SIZE_HEIGHT:
3693 property = &mNode->mSize;
3696 case Dali::Actor::Property::SIZE_DEPTH:
3697 property = &mNode->mSize;
3700 case Dali::Actor::Property::POSITION:
3701 property = &mNode->mPosition;
3704 case Dali::Actor::Property::POSITION_X:
3705 property = &mNode->mPosition;
3708 case Dali::Actor::Property::POSITION_Y:
3709 property = &mNode->mPosition;
3712 case Dali::Actor::Property::POSITION_Z:
3713 property = &mNode->mPosition;
3716 case Dali::Actor::Property::WORLD_POSITION:
3717 property = &mNode->mWorldPosition;
3720 case Dali::Actor::Property::WORLD_POSITION_X:
3721 property = &mNode->mWorldPosition;
3724 case Dali::Actor::Property::WORLD_POSITION_Y:
3725 property = &mNode->mWorldPosition;
3728 case Dali::Actor::Property::WORLD_POSITION_Z:
3729 property = &mNode->mWorldPosition;
3732 case Dali::Actor::Property::ORIENTATION:
3733 property = &mNode->mOrientation;
3736 case Dali::Actor::Property::WORLD_ORIENTATION:
3737 property = &mNode->mWorldOrientation;
3740 case Dali::Actor::Property::SCALE:
3741 property = &mNode->mScale;
3744 case Dali::Actor::Property::SCALE_X:
3745 property = &mNode->mScale;
3748 case Dali::Actor::Property::SCALE_Y:
3749 property = &mNode->mScale;
3752 case Dali::Actor::Property::SCALE_Z:
3753 property = &mNode->mScale;
3756 case Dali::Actor::Property::WORLD_SCALE:
3757 property = &mNode->mWorldScale;
3760 case Dali::Actor::Property::VISIBLE:
3761 property = &mNode->mVisible;
3764 case Dali::Actor::Property::COLOR:
3765 property = &mNode->mColor;
3768 case Dali::Actor::Property::COLOR_RED:
3769 property = &mNode->mColor;
3772 case Dali::Actor::Property::COLOR_GREEN:
3773 property = &mNode->mColor;
3776 case Dali::Actor::Property::COLOR_BLUE:
3777 property = &mNode->mColor;
3780 case Dali::Actor::Property::COLOR_ALPHA:
3781 property = &mNode->mColor;
3784 case Dali::Actor::Property::WORLD_COLOR:
3785 property = &mNode->mWorldColor;
3788 case Dali::Actor::Property::WORLD_MATRIX:
3789 property = &mNode->mWorldMatrix;
3800 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3802 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3804 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3806 // check whether the animatable property is registered already, if not then register one.
3807 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3808 if( animatableProperty )
3810 componentIndex = animatableProperty->componentIndex;
3817 case Dali::Actor::Property::PARENT_ORIGIN_X:
3818 case Dali::Actor::Property::ANCHOR_POINT_X:
3819 case Dali::Actor::Property::SIZE_WIDTH:
3820 case Dali::Actor::Property::POSITION_X:
3821 case Dali::Actor::Property::WORLD_POSITION_X:
3822 case Dali::Actor::Property::SCALE_X:
3823 case Dali::Actor::Property::COLOR_RED:
3829 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3830 case Dali::Actor::Property::ANCHOR_POINT_Y:
3831 case Dali::Actor::Property::SIZE_HEIGHT:
3832 case Dali::Actor::Property::POSITION_Y:
3833 case Dali::Actor::Property::WORLD_POSITION_Y:
3834 case Dali::Actor::Property::SCALE_Y:
3835 case Dali::Actor::Property::COLOR_GREEN:
3841 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3842 case Dali::Actor::Property::ANCHOR_POINT_Z:
3843 case Dali::Actor::Property::SIZE_DEPTH:
3844 case Dali::Actor::Property::POSITION_Z:
3845 case Dali::Actor::Property::WORLD_POSITION_Z:
3846 case Dali::Actor::Property::SCALE_Z:
3847 case Dali::Actor::Property::COLOR_BLUE:
3853 case Dali::Actor::Property::COLOR_ALPHA:
3867 return componentIndex;
3870 void Actor::SetParent( Actor* parent, int index )
3874 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3878 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3881 // Instruct each actor to create a corresponding node in the scene graph
3882 ConnectToStage( parent->GetHierarchyDepth(), index );
3885 else // parent being set to NULL
3887 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3891 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3894 DALI_ASSERT_ALWAYS( mNode != NULL );
3898 // Disconnect the Node & its children from the scene-graph.
3899 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3902 // Instruct each actor to discard pointers to the scene-graph
3903 DisconnectFromStage();
3908 SceneGraph::Node* Actor::CreateNode() const
3913 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3916 Actor* actor = dynamic_cast< Actor* >( object );
3920 if( 0 == actionName.compare( ACTION_SHOW ) )
3922 actor->SetVisible( true );
3925 else if( 0 == actionName.compare( ACTION_HIDE ) )
3927 actor->SetVisible( false );
3935 void Actor::EnsureRelayoutData()
3937 // Assign relayout data.
3938 if( !mRelayoutData )
3940 mRelayoutData = new RelayoutData();
3944 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3946 // Check if actor is dependent on parent
3947 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3949 if( ( dimension & ( 1 << i ) ) )
3951 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3952 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3962 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3964 // Check if actor is dependent on children
3965 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3967 if( ( dimension & ( 1 << i ) ) )
3969 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3970 switch( resizePolicy )
3972 case ResizePolicy::FIT_TO_CHILDREN:
3973 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3989 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3991 return Actor::RelayoutDependentOnChildren( dimension );
3994 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3996 // Check each possible dimension and see if it is dependent on the input one
3997 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3999 if( dimension & ( 1 << i ) )
4001 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4008 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4010 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4012 if( dimension & ( 1 << i ) )
4014 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4019 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4021 // If more than one dimension is requested, just return the first one found
4022 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4024 if( ( dimension & ( 1 << i ) ) )
4026 return mRelayoutData->negotiatedDimensions[ i ];
4030 return 0.0f; // Default
4033 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4035 EnsureRelayoutData();
4037 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4039 if( dimension & ( 1 << i ) )
4041 mRelayoutData->dimensionPadding[ i ] = padding;
4046 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4048 if ( mRelayoutData )
4050 // If more than one dimension is requested, just return the first one found
4051 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4053 if( ( dimension & ( 1 << i ) ) )
4055 return mRelayoutData->dimensionPadding[ i ];
4060 return GetDefaultDimensionPadding();
4063 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4065 EnsureRelayoutData();
4067 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4069 if( dimension & ( 1 << i ) )
4071 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4076 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4078 if ( mRelayoutData )
4080 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4082 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4092 float Actor::GetHeightForWidthBase( float width )
4094 float height = 0.0f;
4096 const Vector3 naturalSize = GetNaturalSize();
4097 if( naturalSize.width > 0.0f )
4099 height = naturalSize.height * width / naturalSize.width;
4101 else // we treat 0 as 1:1 aspect ratio
4109 float Actor::GetWidthForHeightBase( float height )
4113 const Vector3 naturalSize = GetNaturalSize();
4114 if( naturalSize.height > 0.0f )
4116 width = naturalSize.width * height / naturalSize.height;
4118 else // we treat 0 as 1:1 aspect ratio
4126 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4128 // Fill to parent, taking size mode factor into account
4129 switch( child.GetResizePolicy( dimension ) )
4131 case ResizePolicy::FILL_TO_PARENT:
4133 return GetLatestSize( dimension );
4136 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4138 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4141 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4143 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4148 return GetLatestSize( dimension );
4153 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4155 // Can be overridden in derived class
4156 return CalculateChildSizeBase( child, dimension );
4159 float Actor::GetHeightForWidth( float width )
4161 // Can be overridden in derived class
4162 return GetHeightForWidthBase( width );
4165 float Actor::GetWidthForHeight( float height )
4167 // Can be overridden in derived class
4168 return GetWidthForHeightBase( height );
4171 float Actor::GetLatestSize( Dimension::Type dimension ) const
4173 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4176 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4178 Vector2 padding = GetPadding( dimension );
4180 return GetLatestSize( dimension ) + padding.x + padding.y;
4183 float Actor::NegotiateFromParent( Dimension::Type dimension )
4185 Actor* parent = GetParent();
4188 Vector2 padding( GetPadding( dimension ) );
4189 Vector2 parentPadding( parent->GetPadding( dimension ) );
4190 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4196 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4198 float maxDimensionPoint = 0.0f;
4200 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4202 ActorPtr child = GetChildAt( i );
4204 if( !child->RelayoutDependentOnParent( dimension ) )
4206 // Calculate the min and max points that the children range across
4207 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4208 float dimensionSize = child->GetRelayoutSize( dimension );
4209 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4213 return maxDimensionPoint;
4216 float Actor::GetSize( Dimension::Type dimension ) const
4218 return GetDimensionValue( GetTargetSize(), dimension );
4221 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4223 return GetDimensionValue( GetNaturalSize(), dimension );
4226 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4228 switch( GetResizePolicy( dimension ) )
4230 case ResizePolicy::USE_NATURAL_SIZE:
4232 return GetNaturalSize( dimension );
4235 case ResizePolicy::FIXED:
4237 return GetDimensionValue( GetPreferredSize(), dimension );
4240 case ResizePolicy::USE_ASSIGNED_SIZE:
4242 return GetDimensionValue( maximumSize, dimension );
4245 case ResizePolicy::FILL_TO_PARENT:
4246 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4247 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4249 return NegotiateFromParent( dimension );
4252 case ResizePolicy::FIT_TO_CHILDREN:
4254 return NegotiateFromChildren( dimension );
4257 case ResizePolicy::DIMENSION_DEPENDENCY:
4259 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4262 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4264 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4267 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4269 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4281 return 0.0f; // Default
4284 float Actor::ClampDimension( float size, Dimension::Type dimension )
4286 const float minSize = GetMinimumSize( dimension );
4287 const float maxSize = GetMaximumSize( dimension );
4289 return std::max( minSize, std::min( size, maxSize ) );
4292 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4294 // Check if it needs to be negotiated
4295 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4297 // Check that we havn't gotten into an infinite loop
4298 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4299 bool recursionFound = false;
4300 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4302 if( *it == searchActor )
4304 recursionFound = true;
4309 if( !recursionFound )
4311 // Record the path that we have taken
4312 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4314 // Dimension dependency check
4315 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4317 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4319 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4321 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4325 // Parent dependency check
4326 Actor* parent = GetParent();
4327 if( parent && RelayoutDependentOnParent( dimension ) )
4329 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4332 // Children dependency check
4333 if( RelayoutDependentOnChildren( dimension ) )
4335 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4337 ActorPtr child = GetChildAt( i );
4339 // Only relayout child first if it is not dependent on this actor
4340 if( !child->RelayoutDependentOnParent( dimension ) )
4342 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4347 // For deriving classes
4348 OnCalculateRelayoutSize( dimension );
4350 // All dependencies checked, calculate the size and set negotiated flag
4351 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4353 SetNegotiatedDimension( newSize, dimension );
4354 SetLayoutNegotiated( true, dimension );
4356 // For deriving classes
4357 OnLayoutNegotiated( newSize, dimension );
4359 // This actor has been successfully processed, pop it off the recursion stack
4360 recursionStack.pop_back();
4364 // TODO: Break infinite loop
4365 SetLayoutNegotiated( true, dimension );
4370 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4372 // Negotiate all dimensions that require it
4373 ActorDimensionStack recursionStack;
4375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4377 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4380 NegotiateDimension( dimension, allocatedSize, recursionStack );
4384 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4386 switch( mRelayoutData->sizeSetPolicy )
4388 case SizeScalePolicy::USE_SIZE_SET:
4393 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4395 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4396 const Vector3 naturalSize = GetNaturalSize();
4397 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4399 const float sizeRatio = size.width / size.height;
4400 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4402 if( naturalSizeRatio < sizeRatio )
4404 return Vector2( naturalSizeRatio * size.height, size.height );
4406 else if( naturalSizeRatio > sizeRatio )
4408 return Vector2( size.width, size.width / naturalSizeRatio );
4419 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4421 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4422 const Vector3 naturalSize = GetNaturalSize();
4423 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4425 const float sizeRatio = size.width / size.height;
4426 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4428 if( naturalSizeRatio < sizeRatio )
4430 return Vector2( size.width, size.width / naturalSizeRatio );
4432 else if( naturalSizeRatio > sizeRatio )
4434 return Vector2( naturalSizeRatio * size.height, size.height );
4452 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4454 // Do the set actor size
4455 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4457 // Adjust for size set policy
4458 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4460 // Lock the flag to stop recursive relayouts on set size
4461 mRelayoutData->insideRelayout = true;
4462 SetSize( negotiatedSize );
4463 mRelayoutData->insideRelayout = false;
4465 // Clear flags for all dimensions
4466 SetLayoutDirty( false );
4468 // Give deriving classes a chance to respond
4469 OnRelayout( negotiatedSize, container );
4471 if( !mOnRelayoutSignal.Empty() )
4473 Dali::Actor handle( this );
4474 mOnRelayoutSignal.Emit( handle );
4478 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4480 // Do the negotiation
4481 NegotiateDimensions( allocatedSize );
4483 // Set the actor size
4484 SetNegotiatedSize( container );
4486 // Negotiate down to children
4487 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4489 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4491 ActorPtr child = GetChildAt( i );
4493 // Only relayout if required
4494 if( child->RelayoutRequired() )
4496 container.Add( Dali::Actor( child.Get() ), newBounds );
4501 void Actor::RelayoutRequest( Dimension::Type dimension )
4503 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4504 if( relayoutController )
4506 Dali::Actor self( this );
4507 relayoutController->RequestRelayout( self, dimension );
4511 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4515 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4519 void Actor::SetPreferredSize( const Vector2& size )
4521 EnsureRelayoutData();
4523 if( size.width > 0.0f )
4525 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4528 if( size.height > 0.0f )
4530 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4533 mRelayoutData->preferredSize = size;
4538 Vector2 Actor::GetPreferredSize() const
4540 if ( mRelayoutData )
4542 return mRelayoutData->preferredSize;
4545 return GetDefaultPreferredSize();
4548 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4550 EnsureRelayoutData();
4552 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4554 if( dimension & ( 1 << i ) )
4556 mRelayoutData->minimumSize[ i ] = size;
4563 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4565 if ( mRelayoutData )
4567 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4569 if( dimension & ( 1 << i ) )
4571 return mRelayoutData->minimumSize[ i ];
4576 return 0.0f; // Default
4579 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4581 EnsureRelayoutData();
4583 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4585 if( dimension & ( 1 << i ) )
4587 mRelayoutData->maximumSize[ i ] = size;
4594 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4596 if ( mRelayoutData )
4598 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4600 if( dimension & ( 1 << i ) )
4602 return mRelayoutData->maximumSize[ i ];
4607 return FLT_MAX; // Default
4610 } // namespace Internal