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 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;
108 * Struct to collect relayout variables
110 struct Actor::RelayoutData
113 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
115 // Set size negotiation defaults
116 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
118 resizePolicies[ i ] = ResizePolicy::DEFAULT;
119 negotiatedDimensions[ i ] = 0.0f;
120 dimensionNegotiated[ i ] = false;
121 dimensionDirty[ i ] = false;
122 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
123 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
124 minimumSize[ i ] = 0.0f;
125 maximumSize[ i ] = FLT_MAX;
129 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
131 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
133 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
135 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
137 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
138 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
140 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
141 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
143 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
145 Vector2 preferredSize; ///< The preferred size of the actor
147 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
149 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
150 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
153 #ifdef DYNAMICS_SUPPORT
155 // Encapsulate actor related dynamics data
158 DynamicsData( Actor* slotOwner )
159 : slotDelegate( slotOwner )
163 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
164 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
166 DynamicsBodyPtr body;
167 JointContainer joints;
168 ReferencedJointContainer referencedJoints;
170 SlotDelegate< Actor > slotDelegate;
173 #endif // DYNAMICS_SUPPORT
175 namespace // unnamed namespace
181 * We want to discourage the use of property strings (minimize string comparisons),
182 * particularly for the default properties.
183 * Name Type writable animatable constraint-input enum for index-checking
185 DALI_PROPERTY_TABLE_BEGIN
186 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
187 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
188 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
189 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
190 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
191 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
192 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
193 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
194 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
195 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
196 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
197 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
198 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
199 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
200 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
201 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
202 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
203 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
204 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
205 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
206 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
207 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
208 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
209 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
210 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
211 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
212 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
213 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
214 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
215 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
216 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
217 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
218 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
219 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
220 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
221 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
222 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
223 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
224 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
225 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
226 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
227 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
228 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
229 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
230 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
231 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
232 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
233 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
234 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
235 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
236 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
237 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
238 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
242 const char* const SIGNAL_TOUCHED = "touched";
243 const char* const SIGNAL_HOVERED = "hovered";
244 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
245 const char* const SIGNAL_ON_STAGE = "on-stage";
246 const char* const SIGNAL_OFF_STAGE = "off-stage";
250 const char* const ACTION_SHOW = "show";
251 const char* const ACTION_HIDE = "hide";
253 BaseHandle CreateActor()
255 return Dali::Actor::New();
258 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
260 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
263 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
265 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
266 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
269 * @brief Extract a given dimension from a Vector2
271 * @param[in] values The values to extract from
272 * @param[in] dimension The dimension to extract
273 * @return Return the value for the dimension
275 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
279 case Dimension::WIDTH:
284 case Dimension::HEIGHT:
286 return values.height;
299 * @brief Extract a given dimension from a Vector3
301 * @param[in] values The values to extract from
302 * @param[in] dimension The dimension to extract
303 * @return Return the value for the dimension
305 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
307 return GetDimensionValue( values.GetVectorXY(), dimension );
310 } // unnamed namespace
312 ActorPtr Actor::New()
314 ActorPtr actor( new Actor( BASIC ) );
316 // Second-phase construction
322 const std::string& Actor::GetName() const
327 void Actor::SetName( const std::string& name )
333 // ATTENTION: string for debug purposes is not thread safe.
334 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
338 unsigned int Actor::GetId() const
343 void Actor::Attach( ActorAttachment& attachment )
345 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
349 attachment.Connect();
352 mAttachment = ActorAttachmentPtr( &attachment );
355 ActorAttachmentPtr Actor::GetAttachment()
360 bool Actor::OnStage() const
365 Dali::Layer Actor::GetLayer()
369 // Short-circuit for Layer derived actors
372 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
375 // Find the immediate Layer parent
376 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
378 if( parent->IsLayer() )
380 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
387 void Actor::Add( Actor& child )
389 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
390 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
394 mChildren = new ActorContainer;
397 Actor* const oldParent( child.mParent );
399 // child might already be ours
400 if( this != oldParent )
402 // if we already have parent, unparent us first
405 oldParent->Remove( child ); // This causes OnChildRemove callback
407 // Old parent may need to readjust to missing child
408 if( oldParent->RelayoutDependentOnChildren() )
410 oldParent->RelayoutRequest();
414 // Guard against Add() during previous OnChildRemove callback
417 // Do this first, since user callbacks from within SetParent() may need to remove child
418 mChildren->push_back( Dali::Actor( &child ) );
420 // SetParent asserts that child can be added
421 child.SetParent( this );
423 // Notification for derived classes
426 // Only put in a relayout request if there is a suitable dependency
427 if( RelayoutDependentOnChildren() )
435 void Actor::Insert( unsigned int index, Actor& child )
437 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
438 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
442 mChildren = new ActorContainer;
445 Actor* const oldParent( child.mParent );
447 // since an explicit position has been given, always insert, even if already a child
450 oldParent->Remove( child ); // This causes OnChildRemove callback
452 // Old parent may need to readjust to missing child
453 if( oldParent->RelayoutDependentOnChildren() )
455 oldParent->RelayoutRequest();
459 // Guard against Add() during previous OnChildRemove callback
462 // Do this first, since user callbacks from within SetParent() may need to remove child
463 if( index < GetChildCount() )
465 ActorIter it = mChildren->begin();
466 std::advance( it, index );
467 mChildren->insert( it, Dali::Actor( &child ) );
471 mChildren->push_back( Dali::Actor( &child ) );
473 // SetParent asserts that child can be added
474 child.SetParent( this, index );
476 // Notification for derived classes
479 // Only put in a relayout request if there is a suitable dependency
480 if( RelayoutDependentOnChildren() )
485 if( child.RelayoutDependentOnParent() )
487 child.RelayoutRequest();
492 void Actor::Remove( Actor& child )
494 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
504 // Find the child in mChildren, and unparent it
505 ActorIter end = mChildren->end();
506 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
508 Actor& actor = GetImplementation( *iter );
510 if( &actor == &child )
512 // Keep handle for OnChildRemove notification
513 removed = Dali::Actor( &actor );
515 // Do this first, since user callbacks from within SetParent() may need to add the child
516 mChildren->erase( iter );
518 DALI_ASSERT_DEBUG( actor.GetParent() == this );
519 actor.SetParent( NULL );
527 // Notification for derived classes
528 OnChildRemove( GetImplementation( removed ) );
530 // Only put in a relayout request if there is a suitable dependency
531 if( RelayoutDependentOnChildren() )
538 void Actor::Unparent()
542 // Remove this actor from the parent. The remove will put a relayout request in for
543 // the parent if required
544 mParent->Remove( *this );
545 // mParent is now NULL!
549 unsigned int Actor::GetChildCount() const
551 return ( NULL != mChildren ) ? mChildren->size() : 0;
554 Dali::Actor Actor::GetChildAt( unsigned int index ) const
556 DALI_ASSERT_ALWAYS( index < GetChildCount() );
558 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
561 ActorPtr Actor::FindChildByName( const std::string& actorName )
564 if( actorName == mName )
570 ActorIter end = mChildren->end();
571 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
573 child = GetImplementation( *iter ).FindChildByName( actorName );
584 ActorPtr Actor::FindChildById( const unsigned int id )
593 ActorIter end = mChildren->end();
594 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
596 child = GetImplementation( *iter ).FindChildById( id );
607 void Actor::SetParentOrigin( const Vector3& origin )
611 // mNode is being used in a separate thread; queue a message to set the value & base value
612 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
615 // Cache for event-thread access
618 // not allocated, check if different from default
619 if( ParentOrigin::DEFAULT != origin )
621 mParentOrigin = new Vector3( origin );
626 // check if different from current costs more than just set
627 *mParentOrigin = origin;
631 void Actor::SetParentOriginX( float x )
633 const Vector3& current = GetCurrentParentOrigin();
635 SetParentOrigin( Vector3( x, current.y, current.z ) );
638 void Actor::SetParentOriginY( float y )
640 const Vector3& current = GetCurrentParentOrigin();
642 SetParentOrigin( Vector3( current.x, y, current.z ) );
645 void Actor::SetParentOriginZ( float z )
647 const Vector3& current = GetCurrentParentOrigin();
649 SetParentOrigin( Vector3( current.x, current.y, z ) );
652 const Vector3& Actor::GetCurrentParentOrigin() const
654 // Cached for event-thread access
655 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
658 void Actor::SetAnchorPoint( const Vector3& anchor )
662 // mNode is being used in a separate thread; queue a message to set the value & base value
663 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
666 // Cache for event-thread access
669 // not allocated, check if different from default
670 if( AnchorPoint::DEFAULT != anchor )
672 mAnchorPoint = new Vector3( anchor );
677 // check if different from current costs more than just set
678 *mAnchorPoint = anchor;
682 void Actor::SetAnchorPointX( float x )
684 const Vector3& current = GetCurrentAnchorPoint();
686 SetAnchorPoint( Vector3( x, current.y, current.z ) );
689 void Actor::SetAnchorPointY( float y )
691 const Vector3& current = GetCurrentAnchorPoint();
693 SetAnchorPoint( Vector3( current.x, y, current.z ) );
696 void Actor::SetAnchorPointZ( float z )
698 const Vector3& current = GetCurrentAnchorPoint();
700 SetAnchorPoint( Vector3( current.x, current.y, z ) );
703 const Vector3& Actor::GetCurrentAnchorPoint() const
705 // Cached for event-thread access
706 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
709 void Actor::SetPosition( float x, float y )
711 SetPosition( Vector3( x, y, 0.0f ) );
714 void Actor::SetPosition( float x, float y, float z )
716 SetPosition( Vector3( x, y, z ) );
719 void Actor::SetPosition( const Vector3& position )
721 mTargetPosition = position;
725 // mNode is being used in a separate thread; queue a message to set the value & base value
726 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
730 void Actor::SetX( float x )
732 mTargetPosition.x = x;
736 // mNode is being used in a separate thread; queue a message to set the value & base value
737 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
741 void Actor::SetY( float y )
743 mTargetPosition.y = y;
747 // mNode is being used in a separate thread; queue a message to set the value & base value
748 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
752 void Actor::SetZ( float z )
754 mTargetPosition.z = z;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
763 void Actor::TranslateBy( const Vector3& distance )
765 mTargetPosition += distance;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
774 const Vector3& Actor::GetCurrentPosition() const
778 // mNode is being used in a separate thread; copy the value from the previous update
779 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
782 return Vector3::ZERO;
785 const Vector3& Actor::GetTargetPosition() const
787 return mTargetPosition;
790 const Vector3& Actor::GetCurrentWorldPosition() const
794 // mNode is being used in a separate thread; copy the value from the previous update
795 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
798 return Vector3::ZERO;
801 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
803 // this flag is not animatable so keep the value
804 mPositionInheritanceMode = mode;
807 // mNode is being used in a separate thread; queue a message to set the value
808 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
812 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
814 // Cached for event-thread access
815 return mPositionInheritanceMode;
818 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
820 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
821 normalizedAxis.Normalize();
823 Quaternion orientation( angle, normalizedAxis );
825 SetOrientation( orientation );
828 void Actor::SetOrientation( const Quaternion& orientation )
832 // mNode is being used in a separate thread; queue a message to set the value & base value
833 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
837 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
841 // mNode is being used in a separate thread; queue a message to set the value & base value
842 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
846 void Actor::RotateBy( const Quaternion& relativeRotation )
850 // mNode is being used in a separate thread; queue a message to set the value & base value
851 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
855 const Quaternion& Actor::GetCurrentOrientation() const
859 // mNode is being used in a separate thread; copy the value from the previous update
860 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
863 return Quaternion::IDENTITY;
866 const Quaternion& Actor::GetCurrentWorldOrientation() const
870 // mNode is being used in a separate thread; copy the value from the previous update
871 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
874 return Quaternion::IDENTITY;
877 void Actor::SetScale( float scale )
879 SetScale( Vector3( scale, scale, scale ) );
882 void Actor::SetScale( float x, float y, float z )
884 SetScale( Vector3( x, y, z ) );
887 void Actor::SetScale( const Vector3& scale )
891 // mNode is being used in a separate thread; queue a message to set the value & base value
892 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
896 void Actor::SetScaleX( float x )
900 // mNode is being used in a separate thread; queue a message to set the value & base value
901 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
905 void Actor::SetScaleY( float y )
909 // mNode is being used in a separate thread; queue a message to set the value & base value
910 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
914 void Actor::SetScaleZ( float z )
918 // mNode is being used in a separate thread; queue a message to set the value & base value
919 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
923 void Actor::ScaleBy(const Vector3& relativeScale)
927 // mNode is being used in a separate thread; queue a message to set the value & base value
928 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
932 const Vector3& Actor::GetCurrentScale() const
936 // mNode is being used in a separate thread; copy the value from the previous update
937 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
943 const Vector3& Actor::GetCurrentWorldScale() const
947 // mNode is being used in a separate thread; copy the value from the previous update
948 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
954 void Actor::SetInheritScale( bool inherit )
956 // non animateable so keep local copy
957 mInheritScale = inherit;
960 // mNode is being used in a separate thread; queue a message to set the value
961 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
965 bool Actor::IsScaleInherited() const
967 return mInheritScale;
970 Matrix Actor::GetCurrentWorldMatrix() const
974 // World matrix is no longer updated unless there is something observing the node.
975 // Need to calculate it from node's world position, orientation and scale:
976 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
977 Matrix worldMatrix(false);
978 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
979 mNode->GetWorldOrientation( updateBufferIndex ),
980 mNode->GetWorldPosition( updateBufferIndex ) );
984 return Matrix::IDENTITY;
987 void Actor::SetVisible( bool visible )
991 // mNode is being used in a separate thread; queue a message to set the value & base value
992 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
996 bool Actor::IsVisible() const
1000 // mNode is being used in a separate thread; copy the value from the previous update
1001 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1007 void Actor::SetOpacity( float opacity )
1011 // mNode is being used in a separate thread; queue a message to set the value & base value
1012 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1016 float Actor::GetCurrentOpacity() const
1020 // mNode is being used in a separate thread; copy the value from the previous update
1021 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1027 const Vector4& Actor::GetCurrentWorldColor() const
1031 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1034 return Color::WHITE;
1037 void Actor::SetColor( const Vector4& color )
1041 // mNode is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1046 void Actor::SetColorRed( float red )
1050 // mNode is being used in a separate thread; queue a message to set the value & base value
1051 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1055 void Actor::SetColorGreen( float green )
1059 // mNode is being used in a separate thread; queue a message to set the value & base value
1060 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1064 void Actor::SetColorBlue( float blue )
1068 // mNode is being used in a separate thread; queue a message to set the value & base value
1069 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1073 const Vector4& Actor::GetCurrentColor() const
1077 // mNode is being used in a separate thread; copy the value from the previous update
1078 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1081 return Color::WHITE;
1084 void Actor::SetInheritOrientation( bool inherit )
1086 // non animateable so keep local copy
1087 mInheritOrientation = inherit;
1090 // mNode is being used in a separate thread; queue a message to set the value
1091 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1095 bool Actor::IsOrientationInherited() const
1097 return mInheritOrientation;
1100 void Actor::SetSizeModeFactor( const Vector3& factor )
1102 EnsureRelayoutData();
1104 mRelayoutData->sizeModeFactor = factor;
1107 const Vector3& Actor::GetSizeModeFactor() const
1109 EnsureRelayoutData();
1111 return mRelayoutData->sizeModeFactor;
1114 void Actor::SetColorMode( ColorMode colorMode )
1116 // non animateable so keep local copy
1117 mColorMode = colorMode;
1120 // mNode is being used in a separate thread; queue a message to set the value
1121 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1125 ColorMode Actor::GetColorMode() const
1127 // we have cached copy
1131 void Actor::SetSize( float width, float height )
1133 SetSize( Vector2( width, height ) );
1136 void Actor::SetSize( float width, float height, float depth )
1138 SetSize( Vector3( width, height, depth ) );
1141 void Actor::SetSize( const Vector2& size )
1143 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1146 void Actor::SetSizeInternal( const Vector2& size )
1148 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1151 float Actor::CalculateSizeZ( const Vector2& size ) const
1153 return std::min( size.width, size.height );
1156 void Actor::SetSize( const Vector3& size )
1158 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1160 SetPreferredSize( size.GetVectorXY() );
1164 SetSizeInternal( size );
1168 void Actor::SetSizeInternal( const Vector3& size )
1170 // dont allow recursive loop
1171 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1172 // 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
1173 if( ( NULL != mNode )&&
1174 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1175 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1176 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1180 // mNode is being used in a separate thread; queue a message to set the value & base value
1181 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1183 // Notification for derived classes
1184 mInsideOnSizeSet = true;
1185 OnSizeSet( mTargetSize );
1186 mInsideOnSizeSet = false;
1188 // Raise a relayout request if the flag is not locked
1189 if( mRelayoutData && !mRelayoutData->insideRelayout )
1196 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1198 mTargetSize = targetSize;
1200 // Notify deriving classes
1201 OnSizeAnimation( animation, mTargetSize );
1204 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1206 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1208 mTargetSize.width = targetSize;
1210 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1212 mTargetSize.height = targetSize;
1214 // Notify deriving classes
1215 OnSizeAnimation( animation, mTargetSize );
1218 void Actor::SetWidth( float width )
1222 // mNode is being used in a separate thread; queue a message to set the value & base value
1223 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1227 void Actor::SetHeight( float height )
1231 // mNode is being used in a separate thread; queue a message to set the value & base value
1232 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1236 void Actor::SetDepth( float depth )
1240 // mNode is being used in a separate thread; queue a message to set the value & base value
1241 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1245 const Vector3& Actor::GetTargetSize() const
1250 const Vector3& Actor::GetCurrentSize() const
1254 // mNode is being used in a separate thread; copy the value from the previous update
1255 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1258 return Vector3::ZERO;
1261 Vector3 Actor::GetNaturalSize() const
1263 // It is up to deriving classes to return the appropriate natural size
1264 return Vector3( 0.0f, 0.0f, 0.0f );
1267 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1269 EnsureRelayoutData();
1271 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1273 if( dimension & ( 1 << i ) )
1275 mRelayoutData->resizePolicies[ i ] = policy;
1279 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1281 if( dimension & Dimension::WIDTH )
1283 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1286 if( dimension & Dimension::HEIGHT )
1288 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1292 // If calling SetResizePolicy, assume we want relayout enabled
1293 SetRelayoutEnabled( true );
1295 OnSetResizePolicy( policy, dimension );
1297 // Trigger relayout on this control
1301 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1303 EnsureRelayoutData();
1305 // If more than one dimension is requested, just return the first one found
1306 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1308 if( ( dimension & ( 1 << i ) ) )
1310 return mRelayoutData->resizePolicies[ i ];
1314 return ResizePolicy::DEFAULT;
1317 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1319 EnsureRelayoutData();
1321 mRelayoutData->sizeSetPolicy = policy;
1324 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1326 EnsureRelayoutData();
1328 return mRelayoutData->sizeSetPolicy;
1331 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1333 EnsureRelayoutData();
1335 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1337 if( dimension & ( 1 << i ) )
1339 mRelayoutData->dimensionDependencies[ i ] = dependency;
1344 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1346 EnsureRelayoutData();
1348 // If more than one dimension is requested, just return the first one found
1349 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1351 if( ( dimension & ( 1 << i ) ) )
1353 return mRelayoutData->dimensionDependencies[ i ];
1357 return Dimension::ALL_DIMENSIONS; // Default
1360 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1362 // If relayout data has not been allocated yet and the client is requesting
1363 // to disable it, do nothing
1364 if( mRelayoutData || relayoutEnabled )
1366 EnsureRelayoutData();
1368 mRelayoutData->relayoutEnabled = relayoutEnabled;
1372 bool Actor::IsRelayoutEnabled() const
1374 // Assume that if relayout data has not been allocated yet then
1375 // relayout is disabled
1376 return mRelayoutData && mRelayoutData->relayoutEnabled;
1379 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1381 EnsureRelayoutData();
1383 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1385 if( dimension & ( 1 << i ) )
1387 mRelayoutData->dimensionDirty[ i ] = dirty;
1392 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1394 EnsureRelayoutData();
1396 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1398 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1407 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1409 EnsureRelayoutData();
1411 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1414 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1416 EnsureRelayoutData();
1418 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1421 unsigned int Actor::AddRenderer( Renderer& renderer )
1423 //TODO: MESH_REWORK : Add support for multiple renderers
1424 if ( ! mAttachment )
1426 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1432 unsigned int Actor::GetRendererCount() const
1434 //TODO: MESH_REWORK : Add support for multiple renderers
1435 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1436 return attachment ? 1u : 0u;
1439 Renderer& Actor::GetRendererAt( unsigned int index )
1441 //TODO: MESH_REWORK : Add support for multiple renderers
1442 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1444 //TODO: MESH_REWORK : Temporary code
1445 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1446 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1448 return attachment->GetRenderer();
1451 void Actor::RemoveRenderer( Renderer& renderer )
1453 //TODO: MESH_REWORK : Add support for multiple renderers
1457 void Actor::RemoveRenderer( unsigned int index )
1459 //TODO: MESH_REWORK : Add support for multiple renderers
1464 #ifdef DYNAMICS_SUPPORT
1466 //--------------- Dynamics ---------------
1468 void Actor::DisableDynamics()
1470 if( NULL != mDynamicsData )
1472 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1474 // ensure dynamics object are disconnected from scene
1475 DisconnectDynamics();
1477 // delete joint owned by this actor
1478 while( !mDynamicsData->joints.empty() )
1480 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1483 // delete other joints referencing this actor
1484 while( !mDynamicsData->referencedJoints.empty() )
1486 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1487 ActorPtr jointOwner( joint->GetActor( true ) );
1490 jointOwner->RemoveDynamicsJoint( joint );
1494 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1497 // delete the DynamicsBody object
1498 mDynamicsData->body.Reset();
1500 // Discard Dynamics data structure
1501 delete mDynamicsData;
1502 mDynamicsData = NULL;
1506 DynamicsBodyPtr Actor::GetDynamicsBody() const
1508 DynamicsBodyPtr body;
1510 if( NULL != mDynamicsData )
1512 body = mDynamicsData->body;
1518 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1520 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1522 if( NULL == mDynamicsData )
1524 mDynamicsData = new DynamicsData( this );
1527 if( !mDynamicsData->body )
1529 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1533 DynamicsWorldPtr world( DynamicsWorld::Get() );
1536 if( mParent == world->GetRootActor().Get() )
1538 mDynamicsData->body->Connect( GetEventThreadServices() );
1544 return mDynamicsData->body;
1547 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1549 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1550 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1553 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1555 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1556 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1558 DynamicsJointPtr joint;
1560 DynamicsWorldPtr world( DynamicsWorld::Get() );
1564 if( NULL != mDynamicsData )
1566 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1568 if( mDynamicsData->joints.end() != it )
1570 // use existing joint
1576 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1577 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1581 bodyA = EnableDynamics( new DynamicsBodyConfig );
1586 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1589 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1590 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1592 if( OnStage() && attachedActor->OnStage() )
1594 joint->Connect( GetEventThreadServices() );
1597 attachedActor->ReferenceJoint( joint );
1599 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1600 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1607 const int Actor::GetNumberOfJoints() const
1609 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1612 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1614 DynamicsJointPtr joint;
1616 if( NULL != mDynamicsData )
1618 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1620 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1622 for( int i = 0; i < index; ++i )
1634 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1636 DynamicsJointPtr joint;
1638 if( NULL != mDynamicsData )
1640 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1642 if( mDynamicsData->joints.end() != it )
1644 // use existing joint
1652 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1654 if( NULL != mDynamicsData )
1656 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1657 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1659 for(; it != endIt; ++it )
1661 if( it->second == joint.Get() )
1663 ActorPtr attachedActor( it->first );
1665 if( OnStage() && attachedActor && attachedActor->OnStage() )
1667 joint->Disconnect( GetEventThreadServices() );
1672 attachedActor->ReleaseJoint( joint );
1673 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1674 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1677 mDynamicsData->joints.erase(it);
1684 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1686 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1688 if( NULL != mDynamicsData )
1690 mDynamicsData->referencedJoints.push_back(joint);
1694 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1696 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1698 if( NULL != mDynamicsData )
1700 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1702 if( it != mDynamicsData->referencedJoints.end() )
1704 mDynamicsData->referencedJoints.erase( it );
1709 void Actor::SetDynamicsRoot(bool flag)
1711 if( mIsDynamicsRoot != flag )
1713 mIsDynamicsRoot = flag;
1715 if( OnStage() && mChildren )
1717 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1718 ActorIter end = mChildren->end();
1719 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1721 Actor& child = GetImplementation(*iter);
1723 if( child.GetDynamicsBody() )
1725 if( mIsDynamicsRoot )
1727 child.ConnectDynamics();
1731 child.DisconnectDynamics();
1739 bool Actor::IsDynamicsRoot() const
1741 return mIsDynamicsRoot;
1744 void Actor::AttachedActorOnStage( Dali::Actor actor )
1746 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1750 ActorPtr attachedActor( &GetImplementation(actor) );
1752 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1753 if( NULL != mDynamicsData )
1755 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1756 if( mDynamicsData->joints.end() != it )
1758 DynamicsJointPtr joint( it->second );
1759 joint->Connect( GetEventThreadServices() );
1765 void Actor::AttachedActorOffStage( Dali::Actor actor )
1767 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1771 ActorPtr attachedActor( &GetImplementation(actor) );
1773 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1774 if( NULL != mDynamicsData )
1776 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1777 if( mDynamicsData->joints.end() != it )
1779 DynamicsJointPtr joint( it->second );
1780 joint->Disconnect( GetEventThreadServices() );
1786 void Actor::ConnectDynamics()
1788 if( NULL != mDynamicsData && mDynamicsData->body )
1790 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1792 mDynamicsData->body->Connect( GetEventThreadServices() );
1794 // Connect all joints where attachedActor is also on stage
1795 if( !mDynamicsData->joints.empty() )
1797 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1798 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1800 for(; it != endIt; ++it )
1802 Actor* attachedActor( it->first );
1803 if( NULL != attachedActor && attachedActor->OnStage() )
1805 DynamicsJointPtr joint( it->second );
1807 joint->Connect( GetEventThreadServices() );
1815 void Actor::DisconnectDynamics()
1817 if( NULL != mDynamicsData && mDynamicsData->body )
1821 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1823 // Disconnect all joints
1824 if( !mDynamicsData->joints.empty() )
1826 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1827 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1829 for(; it != endIt; ++it )
1831 DynamicsJointPtr joint( it->second );
1833 joint->Disconnect( GetEventThreadServices() );
1840 #endif // DYNAMICS_SUPPORT
1842 void Actor::SetOverlay( bool enable )
1844 // Setting STENCIL will override OVERLAY
1845 if( DrawMode::STENCIL != mDrawMode )
1847 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1851 bool Actor::IsOverlay() const
1853 return ( DrawMode::OVERLAY == mDrawMode );
1856 void Actor::SetDrawMode( DrawMode::Type drawMode )
1858 // this flag is not animatable so keep the value
1859 mDrawMode = drawMode;
1862 // mNode is being used in a separate thread; queue a message to set the value
1863 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1867 DrawMode::Type Actor::GetDrawMode() const
1872 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1874 // only valid when on-stage
1877 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1879 Vector2 converted( screenX, screenY );
1881 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1882 const int taskCount = taskList.GetTaskCount();
1883 for( int i = taskCount - 1; i >= 0; --i )
1885 Dali::RenderTask task = taskList.GetTask( i );
1886 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1888 // found a task where this conversion was ok so return
1896 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1898 bool retval = false;
1899 // only valid when on-stage
1902 CameraActor* camera = renderTask.GetCameraActor();
1906 renderTask.GetViewport( viewport );
1908 // need to translate coordinates to render tasks coordinate space
1909 Vector2 converted( screenX, screenY );
1910 if( renderTask.TranslateCoordinates( converted ) )
1912 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1919 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1921 // Early-out if mNode is NULL
1927 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1929 // Calculate the ModelView matrix
1930 Matrix modelView( false/*don't init*/);
1931 // need to use the components as world matrix is only updated for actors that need it
1932 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1933 Matrix::Multiply( modelView, modelView, viewMatrix );
1935 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1936 Matrix invertedMvp( false/*don't init*/);
1937 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1938 bool success = invertedMvp.Invert();
1940 // Convert to GL coordinates
1941 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1946 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1953 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1959 if( XyPlaneIntersect( nearPos, farPos, local ) )
1961 Vector3 size = GetCurrentSize();
1962 localX = local.x + size.x * 0.5f;
1963 localY = local.y + size.y * 0.5f;
1974 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1977 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1979 Mathematical Formulation
1981 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1983 ( p - c ) dot ( p - c ) = r^2
1985 Given a ray with a point of origin 'o', and a direction vector 'd':
1987 ray(t) = o + td, t >= 0
1989 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1991 (o + td - c ) dot ( o + td - c ) = r^2
1993 To solve for t we first expand the above into a more recognisable quadratic equation form
1995 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
2004 B = 2( o - c ) dot d
2005 C = ( o - c ) dot ( o - c ) - r^2
2007 which can be solved using a standard quadratic formula.
2009 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
2011 Practical Simplification
2013 In a renderer, we often differentiate between world space and object space. In the object space
2014 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2015 into object space, the mathematical solution presented above can be simplified significantly.
2017 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2021 and we can find the t at which the (transformed) ray intersects the sphere by
2023 ( o + td ) dot ( o + td ) = r^2
2025 According to the reasoning above, we expand the above quadratic equation into the general form
2029 which now has coefficients:
2036 // Early out if mNode is NULL
2042 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2044 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2045 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2046 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2048 // Compute the radius is not needed, square radius it's enough.
2049 const Vector3& size( mNode->GetSize( bufferIndex ) );
2051 // Scale the sphere.
2052 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2054 const float width = size.width * scale.width;
2055 const float height = size.height * scale.height;
2057 float squareSphereRadius = 0.5f * ( width * width + height * height );
2059 float a = rayDir.Dot( rayDir ); // a
2060 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2061 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2063 return ( b2 * b2 - a * c ) >= 0.f;
2066 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2073 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2075 // Transforms the ray to the local reference system.
2077 // Calculate the inverse of Model matrix
2078 Matrix invModelMatrix( false/*don't init*/);
2079 // need to use the components as world matrix is only updated for actors that need it
2080 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2082 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2083 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2085 // Test with the actor's XY plane (Normal = 0 0 1 1).
2087 float a = -rayOriginLocal.z;
2088 float b = rayDirLocal.z;
2090 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2092 // Ray travels distance * rayDirLocal to intersect with plane.
2095 const Vector3& size = mNode->GetSize( bufferIndex );
2097 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2098 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2100 // Test with the actor's geometry.
2101 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2108 void Actor::SetLeaveRequired( bool required )
2110 mLeaveRequired = required;
2113 bool Actor::GetLeaveRequired() const
2115 return mLeaveRequired;
2118 void Actor::SetKeyboardFocusable( bool focusable )
2120 mKeyboardFocusable = focusable;
2123 bool Actor::IsKeyboardFocusable() const
2125 return mKeyboardFocusable;
2128 bool Actor::GetTouchRequired() const
2130 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2133 bool Actor::GetHoverRequired() const
2135 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2138 bool Actor::GetWheelEventRequired() const
2140 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
2143 bool Actor::IsHittable() const
2145 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2148 ActorGestureData& Actor::GetGestureData()
2150 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2151 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2152 if( NULL == mGestureData )
2154 mGestureData = new ActorGestureData;
2156 return *mGestureData;
2159 bool Actor::IsGestureRequred( Gesture::Type type ) const
2161 return mGestureData && mGestureData->IsGestureRequred( type );
2164 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2166 bool consumed = false;
2168 if( !mTouchedSignal.Empty() )
2170 Dali::Actor handle( this );
2171 consumed = mTouchedSignal.Emit( handle, event );
2176 // Notification for derived classes
2177 consumed = OnTouchEvent( event );
2183 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2185 bool consumed = false;
2187 if( !mHoveredSignal.Empty() )
2189 Dali::Actor handle( this );
2190 consumed = mHoveredSignal.Emit( handle, event );
2195 // Notification for derived classes
2196 consumed = OnHoverEvent( event );
2202 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2204 bool consumed = false;
2206 if( !mWheelEventSignal.Empty() )
2208 Dali::Actor handle( this );
2209 consumed = mWheelEventSignal.Emit( handle, event );
2214 // Notification for derived classes
2215 consumed = OnWheelEvent( event );
2221 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2223 return mTouchedSignal;
2226 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2228 return mHoveredSignal;
2231 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2233 return mWheelEventSignal;
2236 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2238 return mOnStageSignal;
2241 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2243 return mOffStageSignal;
2246 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2248 return mOnRelayoutSignal;
2251 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2253 bool connected( true );
2254 Actor* actor = dynamic_cast< Actor* >( object );
2256 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2258 actor->TouchedSignal().Connect( tracker, functor );
2260 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2262 actor->HoveredSignal().Connect( tracker, functor );
2264 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2266 actor->WheelEventSignal().Connect( tracker, functor );
2268 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2270 actor->OnStageSignal().Connect( tracker, functor );
2272 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2274 actor->OffStageSignal().Connect( tracker, functor );
2278 // signalName does not match any signal
2285 Actor::Actor( DerivedType derivedType )
2289 mParentOrigin( NULL ),
2290 mAnchorPoint( NULL ),
2291 mRelayoutData( NULL ),
2292 #ifdef DYNAMICS_SUPPORT
2293 mDynamicsData( NULL ),
2295 mGestureData( NULL ),
2297 mTargetSize( 0.0f, 0.0f, 0.0f ),
2299 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2301 mIsRoot( ROOT_LAYER == derivedType ),
2302 mIsRenderable( RENDERABLE == derivedType ),
2303 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2304 mIsOnStage( false ),
2305 mIsDynamicsRoot( false ),
2307 mLeaveRequired( false ),
2308 mKeyboardFocusable( false ),
2309 mDerivedRequiresTouch( false ),
2310 mDerivedRequiresHover( false ),
2311 mDerivedRequiresWheelEvent( false ),
2312 mOnStageSignalled( false ),
2313 mInsideOnSizeSet( false ),
2314 mInheritOrientation( true ),
2315 mInheritScale( true ),
2316 mDrawMode( DrawMode::NORMAL ),
2317 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2318 mColorMode( Node::DEFAULT_COLOR_MODE )
2322 void Actor::Initialize()
2325 SceneGraph::Node* node = CreateNode();
2327 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2328 mNode = node; // Keep raw-pointer to Node
2332 GetEventThreadServices().RegisterObject( this );
2337 // Remove mParent pointers from children even if we're destroying core,
2338 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2341 ActorConstIter endIter = mChildren->end();
2342 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2344 Actor& actor = GetImplementation( *iter );
2345 actor.SetParent( NULL );
2350 // Guard to allow handle destruction after Core has been destroyed
2351 if( EventThreadServices::IsCoreRunning() )
2355 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2356 mNode = NULL; // Node is about to be destroyed
2359 GetEventThreadServices().UnregisterObject( this );
2362 #ifdef DYNAMICS_SUPPORT
2364 delete mDynamicsData;
2367 // Cleanup optional gesture data
2368 delete mGestureData;
2370 // Cleanup optional parent origin and anchor
2371 delete mParentOrigin;
2372 delete mAnchorPoint;
2374 // Delete optional relayout data
2377 delete mRelayoutData;
2381 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2383 // This container is used instead of walking the Actor hierachy.
2384 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2385 ActorContainer connectionList;
2388 // This stage is atomic i.e. not interrupted by user callbacks
2389 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2391 // Notify applications about the newly connected actors.
2392 const ActorIter endIter = connectionList.end();
2393 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2395 Actor& actor = GetImplementation( *iter );
2396 actor.NotifyStageConnection();
2402 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2404 DALI_ASSERT_ALWAYS( !OnStage() );
2409 ConnectToSceneGraph( index );
2411 // Notification for internal derived classes
2412 OnStageConnectionInternal();
2414 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2415 connectionList.push_back( Dali::Actor( this ) );
2417 // Recursively connect children
2420 ActorConstIter endIter = mChildren->end();
2421 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2423 Actor& actor = GetImplementation( *iter );
2424 actor.RecursiveConnectToStage( connectionList, depth+1 );
2430 * This method is called when the Actor is connected to the Stage.
2431 * The parent must have added its Node to the scene-graph.
2432 * The child must connect its Node to the parent's Node.
2433 * This is resursive; the child calls ConnectToStage() for its children.
2435 void Actor::ConnectToSceneGraph( int index )
2437 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2441 // Reparent Node in next Update
2442 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2445 // Notify attachment
2448 mAttachment->Connect();
2451 #ifdef DYNAMICS_SUPPORT
2453 if( NULL != mDynamicsData )
2459 // Request relayout on all actors that are added to the scenegraph
2462 // Notification for Object::Observers
2466 void Actor::NotifyStageConnection()
2468 // Actors can be removed (in a callback), before the on-stage stage is reported.
2469 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2470 if( OnStage() && !mOnStageSignalled )
2472 // Notification for external (CustomActor) derived classes
2473 OnStageConnectionExternal( mDepth );
2475 if( !mOnStageSignal.Empty() )
2477 Dali::Actor handle( this );
2478 mOnStageSignal.Emit( handle );
2481 // Guard against Remove during callbacks
2484 mOnStageSignalled = true; // signal required next time Actor is removed
2489 void Actor::DisconnectFromStage()
2491 // This container is used instead of walking the Actor hierachy.
2492 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2493 ActorContainer disconnectionList;
2495 // This stage is atomic i.e. not interrupted by user callbacks
2496 RecursiveDisconnectFromStage( disconnectionList );
2498 // Notify applications about the newly disconnected actors.
2499 const ActorIter endIter = disconnectionList.end();
2500 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2502 Actor& actor = GetImplementation( *iter );
2503 actor.NotifyStageDisconnection();
2507 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2509 DALI_ASSERT_ALWAYS( OnStage() );
2511 // Recursively disconnect children
2514 ActorConstIter endIter = mChildren->end();
2515 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2517 Actor& actor = GetImplementation( *iter );
2518 actor.RecursiveDisconnectFromStage( disconnectionList );
2522 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2523 disconnectionList.push_back( Dali::Actor( this ) );
2525 // Notification for internal derived classes
2526 OnStageDisconnectionInternal();
2528 DisconnectFromSceneGraph();
2534 * This method is called by an actor or its parent, before a node removal message is sent.
2535 * This is recursive; the child calls DisconnectFromStage() for its children.
2537 void Actor::DisconnectFromSceneGraph()
2539 // Notification for Object::Observers
2540 OnSceneObjectRemove();
2542 // Notify attachment
2545 mAttachment->Disconnect();
2548 #ifdef DYNAMICS_SUPPORT
2550 if( NULL != mDynamicsData )
2552 DisconnectDynamics();
2557 void Actor::NotifyStageDisconnection()
2559 // Actors can be added (in a callback), before the off-stage state is reported.
2560 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2561 // only do this step if there is a stage, i.e. Core is not being shut down
2562 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2564 // Notification for external (CustomeActor) derived classes
2565 OnStageDisconnectionExternal();
2567 if( !mOffStageSignal.Empty() )
2569 Dali::Actor handle( this );
2570 mOffStageSignal.Emit( handle );
2573 // Guard against Add during callbacks
2576 mOnStageSignalled = false; // signal required next time Actor is added
2581 bool Actor::IsNodeConnected() const
2583 bool connected( false );
2588 if( mNode->IsRoot() || mNode->GetParent() )
2597 unsigned int Actor::GetDefaultPropertyCount() const
2599 return DEFAULT_PROPERTY_COUNT;
2602 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2604 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2606 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2608 indices.PushBack( i );
2612 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2614 if( index < DEFAULT_PROPERTY_COUNT )
2616 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2622 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2624 Property::Index index = Property::INVALID_INDEX;
2626 // Look for name in default properties
2627 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2629 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2630 if( 0 == name.compare( property->name ) )
2640 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2642 if( index < DEFAULT_PROPERTY_COUNT )
2644 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2650 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2652 if( index < DEFAULT_PROPERTY_COUNT )
2654 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2660 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2662 if( index < DEFAULT_PROPERTY_COUNT )
2664 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2670 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2672 if( index < DEFAULT_PROPERTY_COUNT )
2674 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2677 // index out of range...return Property::NONE
2678 return Property::NONE;
2681 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2685 case Dali::Actor::Property::PARENT_ORIGIN:
2687 SetParentOrigin( property.Get< Vector3 >() );
2691 case Dali::Actor::Property::PARENT_ORIGIN_X:
2693 SetParentOriginX( property.Get< float >() );
2697 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2699 SetParentOriginY( property.Get< float >() );
2703 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2705 SetParentOriginZ( property.Get< float >() );
2709 case Dali::Actor::Property::ANCHOR_POINT:
2711 SetAnchorPoint( property.Get< Vector3 >() );
2715 case Dali::Actor::Property::ANCHOR_POINT_X:
2717 SetAnchorPointX( property.Get< float >() );
2721 case Dali::Actor::Property::ANCHOR_POINT_Y:
2723 SetAnchorPointY( property.Get< float >() );
2727 case Dali::Actor::Property::ANCHOR_POINT_Z:
2729 SetAnchorPointZ( property.Get< float >() );
2733 case Dali::Actor::Property::SIZE:
2735 SetSize( property.Get< Vector3 >() );
2739 case Dali::Actor::Property::SIZE_WIDTH:
2741 SetWidth( property.Get< float >() );
2745 case Dali::Actor::Property::SIZE_HEIGHT:
2747 SetHeight( property.Get< float >() );
2751 case Dali::Actor::Property::SIZE_DEPTH:
2753 SetDepth( property.Get< float >() );
2757 case Dali::Actor::Property::POSITION:
2759 SetPosition( property.Get< Vector3 >() );
2763 case Dali::Actor::Property::POSITION_X:
2765 SetX( property.Get< float >() );
2769 case Dali::Actor::Property::POSITION_Y:
2771 SetY( property.Get< float >() );
2775 case Dali::Actor::Property::POSITION_Z:
2777 SetZ( property.Get< float >() );
2781 case Dali::Actor::Property::ORIENTATION:
2783 SetOrientation( property.Get< Quaternion >() );
2787 case Dali::Actor::Property::SCALE:
2789 SetScale( property.Get< Vector3 >() );
2793 case Dali::Actor::Property::SCALE_X:
2795 SetScaleX( property.Get< float >() );
2799 case Dali::Actor::Property::SCALE_Y:
2801 SetScaleY( property.Get< float >() );
2805 case Dali::Actor::Property::SCALE_Z:
2807 SetScaleZ( property.Get< float >() );
2811 case Dali::Actor::Property::VISIBLE:
2813 SetVisible( property.Get< bool >() );
2817 case Dali::Actor::Property::COLOR:
2819 SetColor( property.Get< Vector4 >() );
2823 case Dali::Actor::Property::COLOR_RED:
2825 SetColorRed( property.Get< float >() );
2829 case Dali::Actor::Property::COLOR_GREEN:
2831 SetColorGreen( property.Get< float >() );
2835 case Dali::Actor::Property::COLOR_BLUE:
2837 SetColorBlue( property.Get< float >() );
2841 case Dali::Actor::Property::COLOR_ALPHA:
2843 SetOpacity( property.Get< float >() );
2847 case Dali::Actor::Property::NAME:
2849 SetName( property.Get< std::string >() );
2853 case Dali::Actor::Property::SENSITIVE:
2855 SetSensitive( property.Get< bool >() );
2859 case Dali::Actor::Property::LEAVE_REQUIRED:
2861 SetLeaveRequired( property.Get< bool >() );
2865 case Dali::Actor::Property::INHERIT_ORIENTATION:
2867 SetInheritOrientation( property.Get< bool >() );
2871 case Dali::Actor::Property::INHERIT_SCALE:
2873 SetInheritScale( property.Get< bool >() );
2877 case Dali::Actor::Property::COLOR_MODE:
2879 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2883 case Dali::Actor::Property::POSITION_INHERITANCE:
2885 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2889 case Dali::Actor::Property::DRAW_MODE:
2891 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2895 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2897 SetSizeModeFactor( property.Get< Vector3 >() );
2901 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2903 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2907 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2909 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2913 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2915 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2919 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2921 if( property.Get< bool >() )
2923 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2928 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2930 if( property.Get< bool >() )
2932 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2937 case Dali::Actor::Property::PADDING:
2939 Vector4 padding = property.Get< Vector4 >();
2940 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2941 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2945 case Dali::Actor::Property::MINIMUM_SIZE:
2947 Vector2 size = property.Get< Vector2 >();
2948 SetMinimumSize( size.x, Dimension::WIDTH );
2949 SetMinimumSize( size.y, Dimension::HEIGHT );
2953 case Dali::Actor::Property::MAXIMUM_SIZE:
2955 Vector2 size = property.Get< Vector2 >();
2956 SetMaximumSize( size.x, Dimension::WIDTH );
2957 SetMaximumSize( size.y, Dimension::HEIGHT );
2963 // this can happen in the case of a non-animatable default property so just do nothing
2969 // TODO: This method needs to be removed
2970 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2972 switch( entry.type )
2974 case Property::BOOLEAN:
2976 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2977 DALI_ASSERT_DEBUG( NULL != property );
2979 // property is being used in a separate thread; queue a message to set the property
2980 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2985 case Property::INTEGER:
2987 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2988 DALI_ASSERT_DEBUG( NULL != property );
2990 // property is being used in a separate thread; queue a message to set the property
2991 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2996 case Property::UNSIGNED_INTEGER:
2998 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2999 DALI_ASSERT_DEBUG( NULL != property );
3001 // property is being used in a separate thread; queue a message to set the property
3002 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3007 case Property::FLOAT:
3009 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3018 case Property::VECTOR2:
3020 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( 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 if(entry.componentIndex == 0)
3026 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3028 else if(entry.componentIndex == 1)
3030 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3034 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3040 case Property::VECTOR3:
3042 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3043 DALI_ASSERT_DEBUG( NULL != property );
3045 // property is being used in a separate thread; queue a message to set the property
3046 if(entry.componentIndex == 0)
3048 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3050 else if(entry.componentIndex == 1)
3052 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3054 else if(entry.componentIndex == 2)
3056 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3060 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3066 case Property::VECTOR4:
3068 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3069 DALI_ASSERT_DEBUG( NULL != property );
3071 // property is being used in a separate thread; queue a message to set the property
3072 if(entry.componentIndex == 0)
3074 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3076 else if(entry.componentIndex == 1)
3078 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3080 else if(entry.componentIndex == 2)
3082 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3084 else if(entry.componentIndex == 3)
3086 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3090 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3096 case Property::ROTATION:
3098 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3099 DALI_ASSERT_DEBUG( NULL != property );
3101 // property is being used in a separate thread; queue a message to set the property
3102 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3107 case Property::MATRIX:
3109 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3110 DALI_ASSERT_DEBUG( NULL != property );
3112 // property is being used in a separate thread; queue a message to set the property
3113 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3118 case Property::MATRIX3:
3120 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3121 DALI_ASSERT_DEBUG( NULL != property );
3123 // property is being used in a separate thread; queue a message to set the property
3124 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3131 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3137 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3139 Property::Value value;
3143 case Dali::Actor::Property::PARENT_ORIGIN:
3145 value = GetCurrentParentOrigin();
3149 case Dali::Actor::Property::PARENT_ORIGIN_X:
3151 value = GetCurrentParentOrigin().x;
3155 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3157 value = GetCurrentParentOrigin().y;
3161 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3163 value = GetCurrentParentOrigin().z;
3167 case Dali::Actor::Property::ANCHOR_POINT:
3169 value = GetCurrentAnchorPoint();
3173 case Dali::Actor::Property::ANCHOR_POINT_X:
3175 value = GetCurrentAnchorPoint().x;
3179 case Dali::Actor::Property::ANCHOR_POINT_Y:
3181 value = GetCurrentAnchorPoint().y;
3185 case Dali::Actor::Property::ANCHOR_POINT_Z:
3187 value = GetCurrentAnchorPoint().z;
3191 case Dali::Actor::Property::SIZE:
3193 value = GetCurrentSize();
3197 case Dali::Actor::Property::SIZE_WIDTH:
3199 value = GetCurrentSize().width;
3203 case Dali::Actor::Property::SIZE_HEIGHT:
3205 value = GetCurrentSize().height;
3209 case Dali::Actor::Property::SIZE_DEPTH:
3211 value = GetCurrentSize().depth;
3215 case Dali::Actor::Property::POSITION:
3217 value = GetCurrentPosition();
3221 case Dali::Actor::Property::POSITION_X:
3223 value = GetCurrentPosition().x;
3227 case Dali::Actor::Property::POSITION_Y:
3229 value = GetCurrentPosition().y;
3233 case Dali::Actor::Property::POSITION_Z:
3235 value = GetCurrentPosition().z;
3239 case Dali::Actor::Property::WORLD_POSITION:
3241 value = GetCurrentWorldPosition();
3245 case Dali::Actor::Property::WORLD_POSITION_X:
3247 value = GetCurrentWorldPosition().x;
3251 case Dali::Actor::Property::WORLD_POSITION_Y:
3253 value = GetCurrentWorldPosition().y;
3257 case Dali::Actor::Property::WORLD_POSITION_Z:
3259 value = GetCurrentWorldPosition().z;
3263 case Dali::Actor::Property::ORIENTATION:
3265 value = GetCurrentOrientation();
3269 case Dali::Actor::Property::WORLD_ORIENTATION:
3271 value = GetCurrentWorldOrientation();
3275 case Dali::Actor::Property::SCALE:
3277 value = GetCurrentScale();
3281 case Dali::Actor::Property::SCALE_X:
3283 value = GetCurrentScale().x;
3287 case Dali::Actor::Property::SCALE_Y:
3289 value = GetCurrentScale().y;
3293 case Dali::Actor::Property::SCALE_Z:
3295 value = GetCurrentScale().z;
3299 case Dali::Actor::Property::WORLD_SCALE:
3301 value = GetCurrentWorldScale();
3305 case Dali::Actor::Property::VISIBLE:
3307 value = IsVisible();
3311 case Dali::Actor::Property::COLOR:
3313 value = GetCurrentColor();
3317 case Dali::Actor::Property::COLOR_RED:
3319 value = GetCurrentColor().r;
3323 case Dali::Actor::Property::COLOR_GREEN:
3325 value = GetCurrentColor().g;
3329 case Dali::Actor::Property::COLOR_BLUE:
3331 value = GetCurrentColor().b;
3335 case Dali::Actor::Property::COLOR_ALPHA:
3337 value = GetCurrentColor().a;
3341 case Dali::Actor::Property::WORLD_COLOR:
3343 value = GetCurrentWorldColor();
3347 case Dali::Actor::Property::WORLD_MATRIX:
3349 value = GetCurrentWorldMatrix();
3353 case Dali::Actor::Property::NAME:
3359 case Dali::Actor::Property::SENSITIVE:
3361 value = IsSensitive();
3365 case Dali::Actor::Property::LEAVE_REQUIRED:
3367 value = GetLeaveRequired();
3371 case Dali::Actor::Property::INHERIT_ORIENTATION:
3373 value = IsOrientationInherited();
3377 case Dali::Actor::Property::INHERIT_SCALE:
3379 value = IsScaleInherited();
3383 case Dali::Actor::Property::COLOR_MODE:
3385 value = Scripting::GetColorMode( GetColorMode() );
3389 case Dali::Actor::Property::POSITION_INHERITANCE:
3391 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3395 case Dali::Actor::Property::DRAW_MODE:
3397 value = Scripting::GetDrawMode( GetDrawMode() );
3401 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3403 value = GetSizeModeFactor();
3407 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3409 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3413 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3415 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3419 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3421 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3425 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3427 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3431 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3433 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3437 case Dali::Actor::Property::PADDING:
3439 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3440 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3441 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3445 case Dali::Actor::Property::MINIMUM_SIZE:
3447 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3451 case Dali::Actor::Property::MAXIMUM_SIZE:
3453 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3459 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3467 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3472 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3474 // This method should only return an object connected to the scene-graph
3475 return OnStage() ? mNode : NULL;
3478 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3480 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3482 const PropertyBase* property( NULL );
3484 // This method should only return a property of an object connected to the scene-graph
3490 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3492 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3493 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3495 property = animatable->GetSceneGraphProperty();
3497 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3499 CustomPropertyMetadata* custom = FindCustomProperty( index );
3500 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3502 property = custom->GetSceneGraphProperty();
3504 else if( NULL != mNode )
3508 case Dali::Actor::Property::SIZE:
3509 property = &mNode->mSize;
3512 case Dali::Actor::Property::SIZE_WIDTH:
3513 property = &mNode->mSize;
3516 case Dali::Actor::Property::SIZE_HEIGHT:
3517 property = &mNode->mSize;
3520 case Dali::Actor::Property::SIZE_DEPTH:
3521 property = &mNode->mSize;
3524 case Dali::Actor::Property::POSITION:
3525 property = &mNode->mPosition;
3528 case Dali::Actor::Property::POSITION_X:
3529 property = &mNode->mPosition;
3532 case Dali::Actor::Property::POSITION_Y:
3533 property = &mNode->mPosition;
3536 case Dali::Actor::Property::POSITION_Z:
3537 property = &mNode->mPosition;
3540 case Dali::Actor::Property::ORIENTATION:
3541 property = &mNode->mOrientation;
3544 case Dali::Actor::Property::SCALE:
3545 property = &mNode->mScale;
3548 case Dali::Actor::Property::SCALE_X:
3549 property = &mNode->mScale;
3552 case Dali::Actor::Property::SCALE_Y:
3553 property = &mNode->mScale;
3556 case Dali::Actor::Property::SCALE_Z:
3557 property = &mNode->mScale;
3560 case Dali::Actor::Property::VISIBLE:
3561 property = &mNode->mVisible;
3564 case Dali::Actor::Property::COLOR:
3565 property = &mNode->mColor;
3568 case Dali::Actor::Property::COLOR_RED:
3569 property = &mNode->mColor;
3572 case Dali::Actor::Property::COLOR_GREEN:
3573 property = &mNode->mColor;
3576 case Dali::Actor::Property::COLOR_BLUE:
3577 property = &mNode->mColor;
3580 case Dali::Actor::Property::COLOR_ALPHA:
3581 property = &mNode->mColor;
3592 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3594 const PropertyInputImpl* property( NULL );
3596 // This method should only return a property of an object connected to the scene-graph
3602 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3604 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3605 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3607 property = animatable->GetSceneGraphProperty();
3609 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3611 CustomPropertyMetadata* custom = FindCustomProperty( index );
3612 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3613 property = custom->GetSceneGraphProperty();
3615 else if( NULL != mNode )
3619 case Dali::Actor::Property::PARENT_ORIGIN:
3620 property = &mNode->mParentOrigin;
3623 case Dali::Actor::Property::PARENT_ORIGIN_X:
3624 property = &mNode->mParentOrigin;
3627 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3628 property = &mNode->mParentOrigin;
3631 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3632 property = &mNode->mParentOrigin;
3635 case Dali::Actor::Property::ANCHOR_POINT:
3636 property = &mNode->mAnchorPoint;
3639 case Dali::Actor::Property::ANCHOR_POINT_X:
3640 property = &mNode->mAnchorPoint;
3643 case Dali::Actor::Property::ANCHOR_POINT_Y:
3644 property = &mNode->mAnchorPoint;
3647 case Dali::Actor::Property::ANCHOR_POINT_Z:
3648 property = &mNode->mAnchorPoint;
3651 case Dali::Actor::Property::SIZE:
3652 property = &mNode->mSize;
3655 case Dali::Actor::Property::SIZE_WIDTH:
3656 property = &mNode->mSize;
3659 case Dali::Actor::Property::SIZE_HEIGHT:
3660 property = &mNode->mSize;
3663 case Dali::Actor::Property::SIZE_DEPTH:
3664 property = &mNode->mSize;
3667 case Dali::Actor::Property::POSITION:
3668 property = &mNode->mPosition;
3671 case Dali::Actor::Property::POSITION_X:
3672 property = &mNode->mPosition;
3675 case Dali::Actor::Property::POSITION_Y:
3676 property = &mNode->mPosition;
3679 case Dali::Actor::Property::POSITION_Z:
3680 property = &mNode->mPosition;
3683 case Dali::Actor::Property::WORLD_POSITION:
3684 property = &mNode->mWorldPosition;
3687 case Dali::Actor::Property::WORLD_POSITION_X:
3688 property = &mNode->mWorldPosition;
3691 case Dali::Actor::Property::WORLD_POSITION_Y:
3692 property = &mNode->mWorldPosition;
3695 case Dali::Actor::Property::WORLD_POSITION_Z:
3696 property = &mNode->mWorldPosition;
3699 case Dali::Actor::Property::ORIENTATION:
3700 property = &mNode->mOrientation;
3703 case Dali::Actor::Property::WORLD_ORIENTATION:
3704 property = &mNode->mWorldOrientation;
3707 case Dali::Actor::Property::SCALE:
3708 property = &mNode->mScale;
3711 case Dali::Actor::Property::SCALE_X:
3712 property = &mNode->mScale;
3715 case Dali::Actor::Property::SCALE_Y:
3716 property = &mNode->mScale;
3719 case Dali::Actor::Property::SCALE_Z:
3720 property = &mNode->mScale;
3723 case Dali::Actor::Property::WORLD_SCALE:
3724 property = &mNode->mWorldScale;
3727 case Dali::Actor::Property::VISIBLE:
3728 property = &mNode->mVisible;
3731 case Dali::Actor::Property::COLOR:
3732 property = &mNode->mColor;
3735 case Dali::Actor::Property::COLOR_RED:
3736 property = &mNode->mColor;
3739 case Dali::Actor::Property::COLOR_GREEN:
3740 property = &mNode->mColor;
3743 case Dali::Actor::Property::COLOR_BLUE:
3744 property = &mNode->mColor;
3747 case Dali::Actor::Property::COLOR_ALPHA:
3748 property = &mNode->mColor;
3751 case Dali::Actor::Property::WORLD_COLOR:
3752 property = &mNode->mWorldColor;
3755 case Dali::Actor::Property::WORLD_MATRIX:
3756 property = &mNode->mWorldMatrix;
3767 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3769 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3771 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3773 // check whether the animatable property is registered already, if not then register one.
3774 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3775 if( animatableProperty )
3777 componentIndex = animatableProperty->componentIndex;
3784 case Dali::Actor::Property::PARENT_ORIGIN_X:
3785 case Dali::Actor::Property::ANCHOR_POINT_X:
3786 case Dali::Actor::Property::SIZE_WIDTH:
3787 case Dali::Actor::Property::POSITION_X:
3788 case Dali::Actor::Property::WORLD_POSITION_X:
3789 case Dali::Actor::Property::SCALE_X:
3790 case Dali::Actor::Property::COLOR_RED:
3796 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3797 case Dali::Actor::Property::ANCHOR_POINT_Y:
3798 case Dali::Actor::Property::SIZE_HEIGHT:
3799 case Dali::Actor::Property::POSITION_Y:
3800 case Dali::Actor::Property::WORLD_POSITION_Y:
3801 case Dali::Actor::Property::SCALE_Y:
3802 case Dali::Actor::Property::COLOR_GREEN:
3808 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3809 case Dali::Actor::Property::ANCHOR_POINT_Z:
3810 case Dali::Actor::Property::SIZE_DEPTH:
3811 case Dali::Actor::Property::POSITION_Z:
3812 case Dali::Actor::Property::WORLD_POSITION_Z:
3813 case Dali::Actor::Property::SCALE_Z:
3814 case Dali::Actor::Property::COLOR_BLUE:
3820 case Dali::Actor::Property::COLOR_ALPHA:
3834 return componentIndex;
3837 void Actor::SetParent( Actor* parent, int index )
3841 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3845 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3848 // Instruct each actor to create a corresponding node in the scene graph
3849 ConnectToStage( parent->GetDepth(), index );
3852 else // parent being set to NULL
3854 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3858 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3861 DALI_ASSERT_ALWAYS( mNode != NULL );
3865 // Disconnect the Node & its children from the scene-graph.
3866 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3869 // Instruct each actor to discard pointers to the scene-graph
3870 DisconnectFromStage();
3875 SceneGraph::Node* Actor::CreateNode() const
3880 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3883 Actor* actor = dynamic_cast< Actor* >( object );
3887 if( 0 == actionName.compare( ACTION_SHOW ) )
3889 actor->SetVisible( true );
3892 else if( 0 == actionName.compare( ACTION_HIDE ) )
3894 actor->SetVisible( false );
3902 void Actor::EnsureRelayoutData() const
3904 // Assign relayout data.
3905 if( !mRelayoutData )
3907 mRelayoutData = new RelayoutData();
3911 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3913 // Check if actor is dependent on parent
3914 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3916 if( ( dimension & ( 1 << i ) ) )
3918 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3919 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3929 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3931 // Check if actor is dependent on children
3932 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3934 if( ( dimension & ( 1 << i ) ) )
3936 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3937 switch( resizePolicy )
3939 case ResizePolicy::FIT_TO_CHILDREN:
3940 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3956 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3958 return Actor::RelayoutDependentOnChildren( dimension );
3961 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3963 // Check each possible dimension and see if it is dependent on the input one
3964 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3966 if( dimension & ( 1 << i ) )
3968 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3975 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3977 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3979 if( dimension & ( 1 << i ) )
3981 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3986 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3988 // If more than one dimension is requested, just return the first one found
3989 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3991 if( ( dimension & ( 1 << i ) ) )
3993 return mRelayoutData->negotiatedDimensions[ i ];
3997 return 0.0f; // Default
4000 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4002 EnsureRelayoutData();
4004 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4006 if( dimension & ( 1 << i ) )
4008 mRelayoutData->dimensionPadding[ i ] = padding;
4013 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4015 EnsureRelayoutData();
4017 // If more than one dimension is requested, just return the first one found
4018 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4020 if( ( dimension & ( 1 << i ) ) )
4022 return mRelayoutData->dimensionPadding[ i ];
4026 return Vector2( 0.0f, 0.0f ); // Default
4029 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4031 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4033 if( dimension & ( 1 << i ) )
4035 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4040 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4042 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4044 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4053 float Actor::GetHeightForWidthBase( float width )
4055 float height = 0.0f;
4057 const Vector3 naturalSize = GetNaturalSize();
4058 if( naturalSize.width > 0.0f )
4060 height = naturalSize.height * width / naturalSize.width;
4062 else // we treat 0 as 1:1 aspect ratio
4070 float Actor::GetWidthForHeightBase( float height )
4074 const Vector3 naturalSize = GetNaturalSize();
4075 if( naturalSize.height > 0.0f )
4077 width = naturalSize.width * height / naturalSize.height;
4079 else // we treat 0 as 1:1 aspect ratio
4087 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4089 // Fill to parent, taking size mode factor into account
4090 switch( child.GetResizePolicy( dimension ) )
4092 case ResizePolicy::FILL_TO_PARENT:
4094 return GetLatestSize( dimension );
4097 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4099 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4102 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4104 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4109 return GetLatestSize( dimension );
4114 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4116 // Can be overridden in derived class
4117 return CalculateChildSizeBase( child, dimension );
4120 float Actor::GetHeightForWidth( float width )
4122 // Can be overridden in derived class
4123 return GetHeightForWidthBase( width );
4126 float Actor::GetWidthForHeight( float height )
4128 // Can be overridden in derived class
4129 return GetWidthForHeightBase( height );
4132 float Actor::GetLatestSize( Dimension::Type dimension ) const
4134 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4137 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4139 Vector2 padding = GetPadding( dimension );
4141 return GetLatestSize( dimension ) + padding.x + padding.y;
4144 float Actor::NegotiateFromParent( Dimension::Type dimension )
4146 Actor* parent = GetParent();
4149 Vector2 padding( GetPadding( dimension ) );
4150 Vector2 parentPadding( parent->GetPadding( dimension ) );
4151 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4157 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4159 float maxDimensionPoint = 0.0f;
4161 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4163 Dali::Actor child = GetChildAt( i );
4164 Actor& childImpl = GetImplementation( child );
4166 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4168 // Calculate the min and max points that the children range across
4169 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4170 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4171 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4175 return maxDimensionPoint;
4178 float Actor::GetSize( Dimension::Type dimension ) const
4180 return GetDimensionValue( GetTargetSize(), dimension );
4183 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4185 return GetDimensionValue( GetNaturalSize(), dimension );
4188 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4190 switch( GetResizePolicy( dimension ) )
4192 case ResizePolicy::USE_NATURAL_SIZE:
4194 return GetNaturalSize( dimension );
4197 case ResizePolicy::FIXED:
4199 return GetDimensionValue( GetPreferredSize(), dimension );
4202 case ResizePolicy::USE_ASSIGNED_SIZE:
4204 return GetDimensionValue( maximumSize, dimension );
4207 case ResizePolicy::FILL_TO_PARENT:
4208 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4209 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4211 return NegotiateFromParent( dimension );
4214 case ResizePolicy::FIT_TO_CHILDREN:
4216 return NegotiateFromChildren( dimension );
4219 case ResizePolicy::DIMENSION_DEPENDENCY:
4221 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4224 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4226 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4229 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4231 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4243 return 0.0f; // Default
4246 float Actor::ClampDimension( float size, Dimension::Type dimension )
4248 const float minSize = GetMinimumSize( dimension );
4249 const float maxSize = GetMaximumSize( dimension );
4251 return std::max( minSize, std::min( size, maxSize ) );
4254 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4256 // Check if it needs to be negotiated
4257 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4259 // Check that we havn't gotten into an infinite loop
4260 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4261 bool recursionFound = false;
4262 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4264 if( *it == searchActor )
4266 recursionFound = true;
4271 if( !recursionFound )
4273 // Record the path that we have taken
4274 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4276 // Dimension dependency check
4277 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4279 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4281 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4283 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4287 // Parent dependency check
4288 Actor* parent = GetParent();
4289 if( parent && RelayoutDependentOnParent( dimension ) )
4291 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4294 // Children dependency check
4295 if( RelayoutDependentOnChildren( dimension ) )
4297 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4299 Dali::Actor child = GetChildAt( i );
4300 Actor& childImpl = GetImplementation( child );
4302 // Only relayout child first if it is not dependent on this actor
4303 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4305 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4310 // For deriving classes
4311 OnCalculateRelayoutSize( dimension );
4313 // All dependencies checked, calculate the size and set negotiated flag
4314 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4316 SetNegotiatedDimension( newSize, dimension );
4317 SetLayoutNegotiated( true, dimension );
4319 // For deriving classes
4320 OnLayoutNegotiated( newSize, dimension );
4322 // This actor has been successfully processed, pop it off the recursion stack
4323 recursionStack.pop_back();
4327 // TODO: Break infinite loop
4328 SetLayoutNegotiated( true, dimension );
4333 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4335 // Negotiate all dimensions that require it
4336 ActorDimensionStack recursionStack;
4338 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4340 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4343 NegotiateDimension( dimension, allocatedSize, recursionStack );
4347 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4349 switch( mRelayoutData->sizeSetPolicy )
4351 case SizeScalePolicy::USE_SIZE_SET:
4356 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4358 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4359 const Vector3 naturalSize = GetNaturalSize();
4360 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4362 const float sizeRatio = size.width / size.height;
4363 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4365 if( naturalSizeRatio < sizeRatio )
4367 return Vector2( naturalSizeRatio * size.height, size.height );
4369 else if( naturalSizeRatio > sizeRatio )
4371 return Vector2( size.width, size.width / naturalSizeRatio );
4382 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4384 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4385 const Vector3 naturalSize = GetNaturalSize();
4386 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4388 const float sizeRatio = size.width / size.height;
4389 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4391 if( naturalSizeRatio < sizeRatio )
4393 return Vector2( size.width, size.width / naturalSizeRatio );
4395 else if( naturalSizeRatio > sizeRatio )
4397 return Vector2( naturalSizeRatio * size.height, size.height );
4415 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4417 // Do the set actor size
4418 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4420 // Adjust for size set policy
4421 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4423 // Lock the flag to stop recursive relayouts on set size
4424 mRelayoutData->insideRelayout = true;
4425 SetSize( negotiatedSize );
4426 mRelayoutData->insideRelayout = false;
4428 // Clear flags for all dimensions
4429 SetLayoutDirty( false );
4431 // Give deriving classes a chance to respond
4432 OnRelayout( negotiatedSize, container );
4434 if( !mOnRelayoutSignal.Empty() )
4436 Dali::Actor handle( this );
4437 mOnRelayoutSignal.Emit( handle );
4441 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4443 // Do the negotiation
4444 NegotiateDimensions( allocatedSize );
4446 // Set the actor size
4447 SetNegotiatedSize( container );
4449 // Negotiate down to children
4450 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4452 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4454 Dali::Actor child = GetChildAt( i );
4456 // Only relayout if required
4457 if( GetImplementation( child ).RelayoutRequired() )
4459 container.Add( child, newBounds );
4464 void Actor::RelayoutRequest( Dimension::Type dimension )
4466 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4467 if( relayoutController )
4469 Dali::Actor self( this );
4470 relayoutController->RequestRelayout( self, dimension );
4474 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4478 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4482 void Actor::SetPreferredSize( const Vector2& size )
4484 EnsureRelayoutData();
4486 if( size.width > 0.0f )
4488 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4491 if( size.height > 0.0f )
4493 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4496 mRelayoutData->preferredSize = size;
4501 Vector2 Actor::GetPreferredSize() const
4503 EnsureRelayoutData();
4505 return mRelayoutData->preferredSize;
4508 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4510 EnsureRelayoutData();
4512 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4514 if( dimension & ( 1 << i ) )
4516 mRelayoutData->minimumSize[ i ] = size;
4523 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4525 EnsureRelayoutData();
4527 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4529 if( dimension & ( 1 << i ) )
4531 return mRelayoutData->minimumSize[ i ];
4535 return 0.0f; // Default
4538 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4540 EnsureRelayoutData();
4542 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4544 if( dimension & ( 1 << i ) )
4546 mRelayoutData->maximumSize[ i ] = size;
4553 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4555 EnsureRelayoutData();
4557 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4559 if( dimension & ( 1 << i ) )
4561 return mRelayoutData->maximumSize[ i ];
4565 return 0.0f; // Default
4568 } // namespace Internal