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
2300 mIsRoot( ROOT_LAYER == derivedType ),
2301 mIsRenderable( RENDERABLE == derivedType ),
2302 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2303 mIsOnStage( false ),
2304 mIsDynamicsRoot( false ),
2306 mLeaveRequired( false ),
2307 mKeyboardFocusable( false ),
2308 mDerivedRequiresTouch( false ),
2309 mDerivedRequiresHover( false ),
2310 mDerivedRequiresWheelEvent( false ),
2311 mOnStageSignalled( false ),
2312 mInsideOnSizeSet( false ),
2313 mInheritOrientation( true ),
2314 mInheritScale( true ),
2315 mDrawMode( DrawMode::NORMAL ),
2316 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2317 mColorMode( Node::DEFAULT_COLOR_MODE )
2321 void Actor::Initialize()
2324 SceneGraph::Node* node = CreateNode();
2326 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2327 mNode = node; // Keep raw-pointer to Node
2331 GetEventThreadServices().RegisterObject( this );
2336 // Remove mParent pointers from children even if we're destroying core,
2337 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2340 ActorConstIter endIter = mChildren->end();
2341 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2343 Actor& actor = GetImplementation( *iter );
2344 actor.SetParent( NULL );
2349 // Guard to allow handle destruction after Core has been destroyed
2350 if( EventThreadServices::IsCoreRunning() )
2354 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2355 mNode = NULL; // Node is about to be destroyed
2358 GetEventThreadServices().UnregisterObject( this );
2361 #ifdef DYNAMICS_SUPPORT
2363 delete mDynamicsData;
2366 // Cleanup optional gesture data
2367 delete mGestureData;
2369 // Cleanup optional parent origin and anchor
2370 delete mParentOrigin;
2371 delete mAnchorPoint;
2373 // Delete optional relayout data
2376 delete mRelayoutData;
2380 void Actor::ConnectToStage( unsigned int parentDepth, int index )
2382 // This container is used instead of walking the Actor hierachy.
2383 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2384 ActorContainer connectionList;
2387 // This stage is atomic i.e. not interrupted by user callbacks
2388 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2390 // Notify applications about the newly connected actors.
2391 const ActorIter endIter = connectionList.end();
2392 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2394 Actor& actor = GetImplementation( *iter );
2395 actor.NotifyStageConnection();
2401 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2403 DALI_ASSERT_ALWAYS( !OnStage() );
2408 ConnectToSceneGraph( index );
2410 // Notification for internal derived classes
2411 OnStageConnectionInternal();
2413 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2414 connectionList.push_back( Dali::Actor( this ) );
2416 // Recursively connect children
2419 ActorConstIter endIter = mChildren->end();
2420 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2422 Actor& actor = GetImplementation( *iter );
2423 actor.RecursiveConnectToStage( connectionList, depth+1 );
2429 * This method is called when the Actor is connected to the Stage.
2430 * The parent must have added its Node to the scene-graph.
2431 * The child must connect its Node to the parent's Node.
2432 * This is resursive; the child calls ConnectToStage() for its children.
2434 void Actor::ConnectToSceneGraph( int index )
2436 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2440 // Reparent Node in next Update
2441 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2444 // Notify attachment
2447 mAttachment->Connect();
2450 #ifdef DYNAMICS_SUPPORT
2452 if( NULL != mDynamicsData )
2458 // Request relayout on all actors that are added to the scenegraph
2461 // Notification for Object::Observers
2465 void Actor::NotifyStageConnection()
2467 // Actors can be removed (in a callback), before the on-stage stage is reported.
2468 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2469 if( OnStage() && !mOnStageSignalled )
2471 // Notification for external (CustomActor) derived classes
2472 OnStageConnectionExternal( mDepth );
2474 if( !mOnStageSignal.Empty() )
2476 Dali::Actor handle( this );
2477 mOnStageSignal.Emit( handle );
2480 // Guard against Remove during callbacks
2483 mOnStageSignalled = true; // signal required next time Actor is removed
2488 void Actor::DisconnectFromStage()
2490 // This container is used instead of walking the Actor hierachy.
2491 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2492 ActorContainer disconnectionList;
2494 // This stage is atomic i.e. not interrupted by user callbacks
2495 RecursiveDisconnectFromStage( disconnectionList );
2497 // Notify applications about the newly disconnected actors.
2498 const ActorIter endIter = disconnectionList.end();
2499 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2501 Actor& actor = GetImplementation( *iter );
2502 actor.NotifyStageDisconnection();
2506 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2508 DALI_ASSERT_ALWAYS( OnStage() );
2510 // Recursively disconnect children
2513 ActorConstIter endIter = mChildren->end();
2514 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2516 Actor& actor = GetImplementation( *iter );
2517 actor.RecursiveDisconnectFromStage( disconnectionList );
2521 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2522 disconnectionList.push_back( Dali::Actor( this ) );
2524 // Notification for internal derived classes
2525 OnStageDisconnectionInternal();
2527 DisconnectFromSceneGraph();
2533 * This method is called by an actor or its parent, before a node removal message is sent.
2534 * This is recursive; the child calls DisconnectFromStage() for its children.
2536 void Actor::DisconnectFromSceneGraph()
2538 // Notification for Object::Observers
2539 OnSceneObjectRemove();
2541 // Notify attachment
2544 mAttachment->Disconnect();
2547 #ifdef DYNAMICS_SUPPORT
2549 if( NULL != mDynamicsData )
2551 DisconnectDynamics();
2556 void Actor::NotifyStageDisconnection()
2558 // Actors can be added (in a callback), before the off-stage state is reported.
2559 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2560 // only do this step if there is a stage, i.e. Core is not being shut down
2561 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2563 // Notification for external (CustomeActor) derived classes
2564 OnStageDisconnectionExternal();
2566 if( !mOffStageSignal.Empty() )
2568 Dali::Actor handle( this );
2569 mOffStageSignal.Emit( handle );
2572 // Guard against Add during callbacks
2575 mOnStageSignalled = false; // signal required next time Actor is added
2580 bool Actor::IsNodeConnected() const
2582 bool connected( false );
2587 if( mNode->IsRoot() || mNode->GetParent() )
2596 unsigned int Actor::GetDefaultPropertyCount() const
2598 return DEFAULT_PROPERTY_COUNT;
2601 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2603 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2605 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2607 indices.PushBack( i );
2611 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2613 if( index < DEFAULT_PROPERTY_COUNT )
2615 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2621 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2623 Property::Index index = Property::INVALID_INDEX;
2625 // Look for name in default properties
2626 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2628 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2629 if( 0 == name.compare( property->name ) )
2639 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2641 if( index < DEFAULT_PROPERTY_COUNT )
2643 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2649 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2651 if( index < DEFAULT_PROPERTY_COUNT )
2653 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2659 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2661 if( index < DEFAULT_PROPERTY_COUNT )
2663 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2669 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2671 if( index < DEFAULT_PROPERTY_COUNT )
2673 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2676 // index out of range...return Property::NONE
2677 return Property::NONE;
2680 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2684 case Dali::Actor::Property::PARENT_ORIGIN:
2686 SetParentOrigin( property.Get< Vector3 >() );
2690 case Dali::Actor::Property::PARENT_ORIGIN_X:
2692 SetParentOriginX( property.Get< float >() );
2696 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2698 SetParentOriginY( property.Get< float >() );
2702 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2704 SetParentOriginZ( property.Get< float >() );
2708 case Dali::Actor::Property::ANCHOR_POINT:
2710 SetAnchorPoint( property.Get< Vector3 >() );
2714 case Dali::Actor::Property::ANCHOR_POINT_X:
2716 SetAnchorPointX( property.Get< float >() );
2720 case Dali::Actor::Property::ANCHOR_POINT_Y:
2722 SetAnchorPointY( property.Get< float >() );
2726 case Dali::Actor::Property::ANCHOR_POINT_Z:
2728 SetAnchorPointZ( property.Get< float >() );
2732 case Dali::Actor::Property::SIZE:
2734 SetSize( property.Get< Vector3 >() );
2738 case Dali::Actor::Property::SIZE_WIDTH:
2740 SetWidth( property.Get< float >() );
2744 case Dali::Actor::Property::SIZE_HEIGHT:
2746 SetHeight( property.Get< float >() );
2750 case Dali::Actor::Property::SIZE_DEPTH:
2752 SetDepth( property.Get< float >() );
2756 case Dali::Actor::Property::POSITION:
2758 SetPosition( property.Get< Vector3 >() );
2762 case Dali::Actor::Property::POSITION_X:
2764 SetX( property.Get< float >() );
2768 case Dali::Actor::Property::POSITION_Y:
2770 SetY( property.Get< float >() );
2774 case Dali::Actor::Property::POSITION_Z:
2776 SetZ( property.Get< float >() );
2780 case Dali::Actor::Property::ORIENTATION:
2782 SetOrientation( property.Get< Quaternion >() );
2786 case Dali::Actor::Property::SCALE:
2788 SetScale( property.Get< Vector3 >() );
2792 case Dali::Actor::Property::SCALE_X:
2794 SetScaleX( property.Get< float >() );
2798 case Dali::Actor::Property::SCALE_Y:
2800 SetScaleY( property.Get< float >() );
2804 case Dali::Actor::Property::SCALE_Z:
2806 SetScaleZ( property.Get< float >() );
2810 case Dali::Actor::Property::VISIBLE:
2812 SetVisible( property.Get< bool >() );
2816 case Dali::Actor::Property::COLOR:
2818 SetColor( property.Get< Vector4 >() );
2822 case Dali::Actor::Property::COLOR_RED:
2824 SetColorRed( property.Get< float >() );
2828 case Dali::Actor::Property::COLOR_GREEN:
2830 SetColorGreen( property.Get< float >() );
2834 case Dali::Actor::Property::COLOR_BLUE:
2836 SetColorBlue( property.Get< float >() );
2840 case Dali::Actor::Property::COLOR_ALPHA:
2842 SetOpacity( property.Get< float >() );
2846 case Dali::Actor::Property::NAME:
2848 SetName( property.Get< std::string >() );
2852 case Dali::Actor::Property::SENSITIVE:
2854 SetSensitive( property.Get< bool >() );
2858 case Dali::Actor::Property::LEAVE_REQUIRED:
2860 SetLeaveRequired( property.Get< bool >() );
2864 case Dali::Actor::Property::INHERIT_ORIENTATION:
2866 SetInheritOrientation( property.Get< bool >() );
2870 case Dali::Actor::Property::INHERIT_SCALE:
2872 SetInheritScale( property.Get< bool >() );
2876 case Dali::Actor::Property::COLOR_MODE:
2878 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2882 case Dali::Actor::Property::POSITION_INHERITANCE:
2884 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2888 case Dali::Actor::Property::DRAW_MODE:
2890 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2894 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2896 SetSizeModeFactor( property.Get< Vector3 >() );
2900 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2902 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2906 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2908 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2912 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2914 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2918 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2920 if( property.Get< bool >() )
2922 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2927 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2929 if( property.Get< bool >() )
2931 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2936 case Dali::Actor::Property::PADDING:
2938 Vector4 padding = property.Get< Vector4 >();
2939 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2940 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2944 case Dali::Actor::Property::MINIMUM_SIZE:
2946 Vector2 size = property.Get< Vector2 >();
2947 SetMinimumSize( size.x, Dimension::WIDTH );
2948 SetMinimumSize( size.y, Dimension::HEIGHT );
2952 case Dali::Actor::Property::MAXIMUM_SIZE:
2954 Vector2 size = property.Get< Vector2 >();
2955 SetMaximumSize( size.x, Dimension::WIDTH );
2956 SetMaximumSize( size.y, Dimension::HEIGHT );
2962 // this can happen in the case of a non-animatable default property so just do nothing
2968 // TODO: This method needs to be removed
2969 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2971 switch( entry.type )
2973 case Property::BOOLEAN:
2975 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2976 DALI_ASSERT_DEBUG( NULL != property );
2978 // property is being used in a separate thread; queue a message to set the property
2979 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2984 case Property::INTEGER:
2986 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2987 DALI_ASSERT_DEBUG( NULL != property );
2989 // property is being used in a separate thread; queue a message to set the property
2990 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2995 case Property::UNSIGNED_INTEGER:
2997 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2998 DALI_ASSERT_DEBUG( NULL != property );
3000 // property is being used in a separate thread; queue a message to set the property
3001 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3006 case Property::FLOAT:
3008 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3009 DALI_ASSERT_DEBUG( NULL != property );
3011 // property is being used in a separate thread; queue a message to set the property
3012 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3017 case Property::VECTOR2:
3019 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3020 DALI_ASSERT_DEBUG( NULL != property );
3022 // property is being used in a separate thread; queue a message to set the property
3023 if(entry.componentIndex == 0)
3025 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3027 else if(entry.componentIndex == 1)
3029 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3033 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3039 case Property::VECTOR3:
3041 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3042 DALI_ASSERT_DEBUG( NULL != property );
3044 // property is being used in a separate thread; queue a message to set the property
3045 if(entry.componentIndex == 0)
3047 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3049 else if(entry.componentIndex == 1)
3051 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3053 else if(entry.componentIndex == 2)
3055 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3059 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3065 case Property::VECTOR4:
3067 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3068 DALI_ASSERT_DEBUG( NULL != property );
3070 // property is being used in a separate thread; queue a message to set the property
3071 if(entry.componentIndex == 0)
3073 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3075 else if(entry.componentIndex == 1)
3077 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3079 else if(entry.componentIndex == 2)
3081 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3083 else if(entry.componentIndex == 3)
3085 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3089 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3095 case Property::ROTATION:
3097 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3098 DALI_ASSERT_DEBUG( NULL != property );
3100 // property is being used in a separate thread; queue a message to set the property
3101 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3106 case Property::MATRIX:
3108 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3109 DALI_ASSERT_DEBUG( NULL != property );
3111 // property is being used in a separate thread; queue a message to set the property
3112 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3117 case Property::MATRIX3:
3119 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3120 DALI_ASSERT_DEBUG( NULL != property );
3122 // property is being used in a separate thread; queue a message to set the property
3123 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3130 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3136 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3138 Property::Value value;
3142 case Dali::Actor::Property::PARENT_ORIGIN:
3144 value = GetCurrentParentOrigin();
3148 case Dali::Actor::Property::PARENT_ORIGIN_X:
3150 value = GetCurrentParentOrigin().x;
3154 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3156 value = GetCurrentParentOrigin().y;
3160 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3162 value = GetCurrentParentOrigin().z;
3166 case Dali::Actor::Property::ANCHOR_POINT:
3168 value = GetCurrentAnchorPoint();
3172 case Dali::Actor::Property::ANCHOR_POINT_X:
3174 value = GetCurrentAnchorPoint().x;
3178 case Dali::Actor::Property::ANCHOR_POINT_Y:
3180 value = GetCurrentAnchorPoint().y;
3184 case Dali::Actor::Property::ANCHOR_POINT_Z:
3186 value = GetCurrentAnchorPoint().z;
3190 case Dali::Actor::Property::SIZE:
3192 value = GetCurrentSize();
3196 case Dali::Actor::Property::SIZE_WIDTH:
3198 value = GetCurrentSize().width;
3202 case Dali::Actor::Property::SIZE_HEIGHT:
3204 value = GetCurrentSize().height;
3208 case Dali::Actor::Property::SIZE_DEPTH:
3210 value = GetCurrentSize().depth;
3214 case Dali::Actor::Property::POSITION:
3216 value = GetCurrentPosition();
3220 case Dali::Actor::Property::POSITION_X:
3222 value = GetCurrentPosition().x;
3226 case Dali::Actor::Property::POSITION_Y:
3228 value = GetCurrentPosition().y;
3232 case Dali::Actor::Property::POSITION_Z:
3234 value = GetCurrentPosition().z;
3238 case Dali::Actor::Property::WORLD_POSITION:
3240 value = GetCurrentWorldPosition();
3244 case Dali::Actor::Property::WORLD_POSITION_X:
3246 value = GetCurrentWorldPosition().x;
3250 case Dali::Actor::Property::WORLD_POSITION_Y:
3252 value = GetCurrentWorldPosition().y;
3256 case Dali::Actor::Property::WORLD_POSITION_Z:
3258 value = GetCurrentWorldPosition().z;
3262 case Dali::Actor::Property::ORIENTATION:
3264 value = GetCurrentOrientation();
3268 case Dali::Actor::Property::WORLD_ORIENTATION:
3270 value = GetCurrentWorldOrientation();
3274 case Dali::Actor::Property::SCALE:
3276 value = GetCurrentScale();
3280 case Dali::Actor::Property::SCALE_X:
3282 value = GetCurrentScale().x;
3286 case Dali::Actor::Property::SCALE_Y:
3288 value = GetCurrentScale().y;
3292 case Dali::Actor::Property::SCALE_Z:
3294 value = GetCurrentScale().z;
3298 case Dali::Actor::Property::WORLD_SCALE:
3300 value = GetCurrentWorldScale();
3304 case Dali::Actor::Property::VISIBLE:
3306 value = IsVisible();
3310 case Dali::Actor::Property::COLOR:
3312 value = GetCurrentColor();
3316 case Dali::Actor::Property::COLOR_RED:
3318 value = GetCurrentColor().r;
3322 case Dali::Actor::Property::COLOR_GREEN:
3324 value = GetCurrentColor().g;
3328 case Dali::Actor::Property::COLOR_BLUE:
3330 value = GetCurrentColor().b;
3334 case Dali::Actor::Property::COLOR_ALPHA:
3336 value = GetCurrentColor().a;
3340 case Dali::Actor::Property::WORLD_COLOR:
3342 value = GetCurrentWorldColor();
3346 case Dali::Actor::Property::WORLD_MATRIX:
3348 value = GetCurrentWorldMatrix();
3352 case Dali::Actor::Property::NAME:
3358 case Dali::Actor::Property::SENSITIVE:
3360 value = IsSensitive();
3364 case Dali::Actor::Property::LEAVE_REQUIRED:
3366 value = GetLeaveRequired();
3370 case Dali::Actor::Property::INHERIT_ORIENTATION:
3372 value = IsOrientationInherited();
3376 case Dali::Actor::Property::INHERIT_SCALE:
3378 value = IsScaleInherited();
3382 case Dali::Actor::Property::COLOR_MODE:
3384 value = Scripting::GetColorMode( GetColorMode() );
3388 case Dali::Actor::Property::POSITION_INHERITANCE:
3390 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3394 case Dali::Actor::Property::DRAW_MODE:
3396 value = Scripting::GetDrawMode( GetDrawMode() );
3400 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3402 value = GetSizeModeFactor();
3406 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3408 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3412 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3414 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3418 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3420 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3424 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3426 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3430 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3432 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3436 case Dali::Actor::Property::PADDING:
3438 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3439 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3440 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3444 case Dali::Actor::Property::MINIMUM_SIZE:
3446 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3450 case Dali::Actor::Property::MAXIMUM_SIZE:
3452 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3458 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3466 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3471 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3473 // This method should only return an object connected to the scene-graph
3474 return OnStage() ? mNode : NULL;
3477 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3479 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3481 const PropertyBase* property( NULL );
3483 // This method should only return a property of an object connected to the scene-graph
3489 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3491 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3492 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3494 property = animatable->GetSceneGraphProperty();
3496 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3498 CustomPropertyMetadata* custom = FindCustomProperty( index );
3499 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3501 property = custom->GetSceneGraphProperty();
3503 else if( NULL != mNode )
3507 case Dali::Actor::Property::SIZE:
3508 property = &mNode->mSize;
3511 case Dali::Actor::Property::SIZE_WIDTH:
3512 property = &mNode->mSize;
3515 case Dali::Actor::Property::SIZE_HEIGHT:
3516 property = &mNode->mSize;
3519 case Dali::Actor::Property::SIZE_DEPTH:
3520 property = &mNode->mSize;
3523 case Dali::Actor::Property::POSITION:
3524 property = &mNode->mPosition;
3527 case Dali::Actor::Property::POSITION_X:
3528 property = &mNode->mPosition;
3531 case Dali::Actor::Property::POSITION_Y:
3532 property = &mNode->mPosition;
3535 case Dali::Actor::Property::POSITION_Z:
3536 property = &mNode->mPosition;
3539 case Dali::Actor::Property::ORIENTATION:
3540 property = &mNode->mOrientation;
3543 case Dali::Actor::Property::SCALE:
3544 property = &mNode->mScale;
3547 case Dali::Actor::Property::SCALE_X:
3548 property = &mNode->mScale;
3551 case Dali::Actor::Property::SCALE_Y:
3552 property = &mNode->mScale;
3555 case Dali::Actor::Property::SCALE_Z:
3556 property = &mNode->mScale;
3559 case Dali::Actor::Property::VISIBLE:
3560 property = &mNode->mVisible;
3563 case Dali::Actor::Property::COLOR:
3564 property = &mNode->mColor;
3567 case Dali::Actor::Property::COLOR_RED:
3568 property = &mNode->mColor;
3571 case Dali::Actor::Property::COLOR_GREEN:
3572 property = &mNode->mColor;
3575 case Dali::Actor::Property::COLOR_BLUE:
3576 property = &mNode->mColor;
3579 case Dali::Actor::Property::COLOR_ALPHA:
3580 property = &mNode->mColor;
3591 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3593 const PropertyInputImpl* property( NULL );
3595 // This method should only return a property of an object connected to the scene-graph
3601 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3603 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3604 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3606 property = animatable->GetSceneGraphProperty();
3608 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3610 CustomPropertyMetadata* custom = FindCustomProperty( index );
3611 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3612 property = custom->GetSceneGraphProperty();
3614 else if( NULL != mNode )
3618 case Dali::Actor::Property::PARENT_ORIGIN:
3619 property = &mNode->mParentOrigin;
3622 case Dali::Actor::Property::PARENT_ORIGIN_X:
3623 property = &mNode->mParentOrigin;
3626 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3627 property = &mNode->mParentOrigin;
3630 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3631 property = &mNode->mParentOrigin;
3634 case Dali::Actor::Property::ANCHOR_POINT:
3635 property = &mNode->mAnchorPoint;
3638 case Dali::Actor::Property::ANCHOR_POINT_X:
3639 property = &mNode->mAnchorPoint;
3642 case Dali::Actor::Property::ANCHOR_POINT_Y:
3643 property = &mNode->mAnchorPoint;
3646 case Dali::Actor::Property::ANCHOR_POINT_Z:
3647 property = &mNode->mAnchorPoint;
3650 case Dali::Actor::Property::SIZE:
3651 property = &mNode->mSize;
3654 case Dali::Actor::Property::SIZE_WIDTH:
3655 property = &mNode->mSize;
3658 case Dali::Actor::Property::SIZE_HEIGHT:
3659 property = &mNode->mSize;
3662 case Dali::Actor::Property::SIZE_DEPTH:
3663 property = &mNode->mSize;
3666 case Dali::Actor::Property::POSITION:
3667 property = &mNode->mPosition;
3670 case Dali::Actor::Property::POSITION_X:
3671 property = &mNode->mPosition;
3674 case Dali::Actor::Property::POSITION_Y:
3675 property = &mNode->mPosition;
3678 case Dali::Actor::Property::POSITION_Z:
3679 property = &mNode->mPosition;
3682 case Dali::Actor::Property::WORLD_POSITION:
3683 property = &mNode->mWorldPosition;
3686 case Dali::Actor::Property::WORLD_POSITION_X:
3687 property = &mNode->mWorldPosition;
3690 case Dali::Actor::Property::WORLD_POSITION_Y:
3691 property = &mNode->mWorldPosition;
3694 case Dali::Actor::Property::WORLD_POSITION_Z:
3695 property = &mNode->mWorldPosition;
3698 case Dali::Actor::Property::ORIENTATION:
3699 property = &mNode->mOrientation;
3702 case Dali::Actor::Property::WORLD_ORIENTATION:
3703 property = &mNode->mWorldOrientation;
3706 case Dali::Actor::Property::SCALE:
3707 property = &mNode->mScale;
3710 case Dali::Actor::Property::SCALE_X:
3711 property = &mNode->mScale;
3714 case Dali::Actor::Property::SCALE_Y:
3715 property = &mNode->mScale;
3718 case Dali::Actor::Property::SCALE_Z:
3719 property = &mNode->mScale;
3722 case Dali::Actor::Property::WORLD_SCALE:
3723 property = &mNode->mWorldScale;
3726 case Dali::Actor::Property::VISIBLE:
3727 property = &mNode->mVisible;
3730 case Dali::Actor::Property::COLOR:
3731 property = &mNode->mColor;
3734 case Dali::Actor::Property::COLOR_RED:
3735 property = &mNode->mColor;
3738 case Dali::Actor::Property::COLOR_GREEN:
3739 property = &mNode->mColor;
3742 case Dali::Actor::Property::COLOR_BLUE:
3743 property = &mNode->mColor;
3746 case Dali::Actor::Property::COLOR_ALPHA:
3747 property = &mNode->mColor;
3750 case Dali::Actor::Property::WORLD_COLOR:
3751 property = &mNode->mWorldColor;
3754 case Dali::Actor::Property::WORLD_MATRIX:
3755 property = &mNode->mWorldMatrix;
3766 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3768 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3770 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3772 // check whether the animatable property is registered already, if not then register one.
3773 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3774 if( animatableProperty )
3776 componentIndex = animatableProperty->componentIndex;
3783 case Dali::Actor::Property::PARENT_ORIGIN_X:
3784 case Dali::Actor::Property::ANCHOR_POINT_X:
3785 case Dali::Actor::Property::SIZE_WIDTH:
3786 case Dali::Actor::Property::POSITION_X:
3787 case Dali::Actor::Property::WORLD_POSITION_X:
3788 case Dali::Actor::Property::SCALE_X:
3789 case Dali::Actor::Property::COLOR_RED:
3795 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3796 case Dali::Actor::Property::ANCHOR_POINT_Y:
3797 case Dali::Actor::Property::SIZE_HEIGHT:
3798 case Dali::Actor::Property::POSITION_Y:
3799 case Dali::Actor::Property::WORLD_POSITION_Y:
3800 case Dali::Actor::Property::SCALE_Y:
3801 case Dali::Actor::Property::COLOR_GREEN:
3807 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3808 case Dali::Actor::Property::ANCHOR_POINT_Z:
3809 case Dali::Actor::Property::SIZE_DEPTH:
3810 case Dali::Actor::Property::POSITION_Z:
3811 case Dali::Actor::Property::WORLD_POSITION_Z:
3812 case Dali::Actor::Property::SCALE_Z:
3813 case Dali::Actor::Property::COLOR_BLUE:
3819 case Dali::Actor::Property::COLOR_ALPHA:
3833 return componentIndex;
3836 void Actor::SetParent( Actor* parent, int index )
3840 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3844 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3847 // Instruct each actor to create a corresponding node in the scene graph
3848 ConnectToStage( parent->GetDepth(), index );
3851 else // parent being set to NULL
3853 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3857 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3860 DALI_ASSERT_ALWAYS( mNode != NULL );
3864 // Disconnect the Node & its children from the scene-graph.
3865 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3868 // Instruct each actor to discard pointers to the scene-graph
3869 DisconnectFromStage();
3874 SceneGraph::Node* Actor::CreateNode() const
3879 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3882 Actor* actor = dynamic_cast< Actor* >( object );
3886 if( 0 == actionName.compare( ACTION_SHOW ) )
3888 actor->SetVisible( true );
3891 else if( 0 == actionName.compare( ACTION_HIDE ) )
3893 actor->SetVisible( false );
3901 void Actor::EnsureRelayoutData() const
3903 // Assign relayout data.
3904 if( !mRelayoutData )
3906 mRelayoutData = new RelayoutData();
3910 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3912 // Check if actor is dependent on parent
3913 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3915 if( ( dimension & ( 1 << i ) ) )
3917 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3918 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3928 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3930 // Check if actor is dependent on children
3931 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3933 if( ( dimension & ( 1 << i ) ) )
3935 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3936 switch( resizePolicy )
3938 case ResizePolicy::FIT_TO_CHILDREN:
3939 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3955 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3957 return Actor::RelayoutDependentOnChildren( dimension );
3960 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3962 // Check each possible dimension and see if it is dependent on the input one
3963 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3965 if( dimension & ( 1 << i ) )
3967 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3974 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3976 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3978 if( dimension & ( 1 << i ) )
3980 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3985 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3987 // If more than one dimension is requested, just return the first one found
3988 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3990 if( ( dimension & ( 1 << i ) ) )
3992 return mRelayoutData->negotiatedDimensions[ i ];
3996 return 0.0f; // Default
3999 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4001 EnsureRelayoutData();
4003 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4005 if( dimension & ( 1 << i ) )
4007 mRelayoutData->dimensionPadding[ i ] = padding;
4012 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4014 EnsureRelayoutData();
4016 // If more than one dimension is requested, just return the first one found
4017 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4019 if( ( dimension & ( 1 << i ) ) )
4021 return mRelayoutData->dimensionPadding[ i ];
4025 return Vector2( 0.0f, 0.0f ); // Default
4028 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4030 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4032 if( dimension & ( 1 << i ) )
4034 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4039 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4041 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4043 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4052 float Actor::GetHeightForWidthBase( float width )
4054 float height = 0.0f;
4056 const Vector3 naturalSize = GetNaturalSize();
4057 if( naturalSize.width > 0.0f )
4059 height = naturalSize.height * width / naturalSize.width;
4061 else // we treat 0 as 1:1 aspect ratio
4069 float Actor::GetWidthForHeightBase( float height )
4073 const Vector3 naturalSize = GetNaturalSize();
4074 if( naturalSize.height > 0.0f )
4076 width = naturalSize.width * height / naturalSize.height;
4078 else // we treat 0 as 1:1 aspect ratio
4086 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4088 // Fill to parent, taking size mode factor into account
4089 switch( child.GetResizePolicy( dimension ) )
4091 case ResizePolicy::FILL_TO_PARENT:
4093 return GetLatestSize( dimension );
4096 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4098 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4101 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4103 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4108 return GetLatestSize( dimension );
4113 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4115 // Can be overridden in derived class
4116 return CalculateChildSizeBase( child, dimension );
4119 float Actor::GetHeightForWidth( float width )
4121 // Can be overridden in derived class
4122 return GetHeightForWidthBase( width );
4125 float Actor::GetWidthForHeight( float height )
4127 // Can be overridden in derived class
4128 return GetWidthForHeightBase( height );
4131 float Actor::GetLatestSize( Dimension::Type dimension ) const
4133 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4136 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4138 Vector2 padding = GetPadding( dimension );
4140 return GetLatestSize( dimension ) + padding.x + padding.y;
4143 float Actor::NegotiateFromParent( Dimension::Type dimension )
4145 Actor* parent = GetParent();
4148 Vector2 padding( GetPadding( dimension ) );
4149 Vector2 parentPadding( parent->GetPadding( dimension ) );
4150 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4156 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4158 float maxDimensionPoint = 0.0f;
4160 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4162 Dali::Actor child = GetChildAt( i );
4163 Actor& childImpl = GetImplementation( child );
4165 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4167 // Calculate the min and max points that the children range across
4168 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4169 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4170 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4174 return maxDimensionPoint;
4177 float Actor::GetSize( Dimension::Type dimension ) const
4179 return GetDimensionValue( GetTargetSize(), dimension );
4182 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4184 return GetDimensionValue( GetNaturalSize(), dimension );
4187 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4189 switch( GetResizePolicy( dimension ) )
4191 case ResizePolicy::USE_NATURAL_SIZE:
4193 return GetNaturalSize( dimension );
4196 case ResizePolicy::FIXED:
4198 return GetDimensionValue( GetPreferredSize(), dimension );
4201 case ResizePolicy::USE_ASSIGNED_SIZE:
4203 return GetDimensionValue( maximumSize, dimension );
4206 case ResizePolicy::FILL_TO_PARENT:
4207 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4208 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4210 return NegotiateFromParent( dimension );
4213 case ResizePolicy::FIT_TO_CHILDREN:
4215 return NegotiateFromChildren( dimension );
4218 case ResizePolicy::DIMENSION_DEPENDENCY:
4220 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4223 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4225 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4228 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4230 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4242 return 0.0f; // Default
4245 float Actor::ClampDimension( float size, Dimension::Type dimension )
4247 const float minSize = GetMinimumSize( dimension );
4248 const float maxSize = GetMaximumSize( dimension );
4250 return std::max( minSize, std::min( size, maxSize ) );
4253 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4255 // Check if it needs to be negotiated
4256 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4258 // Check that we havn't gotten into an infinite loop
4259 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4260 bool recursionFound = false;
4261 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4263 if( *it == searchActor )
4265 recursionFound = true;
4270 if( !recursionFound )
4272 // Record the path that we have taken
4273 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4275 // Dimension dependency check
4276 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4278 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4280 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4282 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4286 // Parent dependency check
4287 Actor* parent = GetParent();
4288 if( parent && RelayoutDependentOnParent( dimension ) )
4290 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4293 // Children dependency check
4294 if( RelayoutDependentOnChildren( dimension ) )
4296 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4298 Dali::Actor child = GetChildAt( i );
4299 Actor& childImpl = GetImplementation( child );
4301 // Only relayout child first if it is not dependent on this actor
4302 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4304 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4309 // For deriving classes
4310 OnCalculateRelayoutSize( dimension );
4312 // All dependencies checked, calculate the size and set negotiated flag
4313 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4315 SetNegotiatedDimension( newSize, dimension );
4316 SetLayoutNegotiated( true, dimension );
4318 // For deriving classes
4319 OnLayoutNegotiated( newSize, dimension );
4321 // This actor has been successfully processed, pop it off the recursion stack
4322 recursionStack.pop_back();
4326 // TODO: Break infinite loop
4327 SetLayoutNegotiated( true, dimension );
4332 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4334 // Negotiate all dimensions that require it
4335 ActorDimensionStack recursionStack;
4337 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4339 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4342 NegotiateDimension( dimension, allocatedSize, recursionStack );
4346 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4348 switch( mRelayoutData->sizeSetPolicy )
4350 case SizeScalePolicy::USE_SIZE_SET:
4355 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4357 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4358 const Vector3 naturalSize = GetNaturalSize();
4359 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4361 const float sizeRatio = size.width / size.height;
4362 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4364 if( naturalSizeRatio < sizeRatio )
4366 return Vector2( naturalSizeRatio * size.height, size.height );
4368 else if( naturalSizeRatio > sizeRatio )
4370 return Vector2( size.width, size.width / naturalSizeRatio );
4381 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4383 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4384 const Vector3 naturalSize = GetNaturalSize();
4385 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4387 const float sizeRatio = size.width / size.height;
4388 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4390 if( naturalSizeRatio < sizeRatio )
4392 return Vector2( size.width, size.width / naturalSizeRatio );
4394 else if( naturalSizeRatio > sizeRatio )
4396 return Vector2( naturalSizeRatio * size.height, size.height );
4414 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4416 // Do the set actor size
4417 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4419 // Adjust for size set policy
4420 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4422 // Lock the flag to stop recursive relayouts on set size
4423 mRelayoutData->insideRelayout = true;
4424 SetSize( negotiatedSize );
4425 mRelayoutData->insideRelayout = false;
4427 // Clear flags for all dimensions
4428 SetLayoutDirty( false );
4430 // Give deriving classes a chance to respond
4431 OnRelayout( negotiatedSize, container );
4433 if( !mOnRelayoutSignal.Empty() )
4435 Dali::Actor handle( this );
4436 mOnRelayoutSignal.Emit( handle );
4440 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4442 // Do the negotiation
4443 NegotiateDimensions( allocatedSize );
4445 // Set the actor size
4446 SetNegotiatedSize( container );
4448 // Negotiate down to children
4449 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4451 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4453 Dali::Actor child = GetChildAt( i );
4455 // Only relayout if required
4456 if( GetImplementation( child ).RelayoutRequired() )
4458 container.Add( child, newBounds );
4463 void Actor::RelayoutRequest( Dimension::Type dimension )
4465 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4466 if( relayoutController )
4468 Dali::Actor self( this );
4469 relayoutController->RequestRelayout( self, dimension );
4473 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4477 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4481 void Actor::SetPreferredSize( const Vector2& size )
4483 EnsureRelayoutData();
4485 if( size.width > 0.0f )
4487 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4490 if( size.height > 0.0f )
4492 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4495 mRelayoutData->preferredSize = size;
4500 Vector2 Actor::GetPreferredSize() const
4502 EnsureRelayoutData();
4504 return mRelayoutData->preferredSize;
4507 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4509 EnsureRelayoutData();
4511 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4513 if( dimension & ( 1 << i ) )
4515 mRelayoutData->minimumSize[ i ] = size;
4522 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4524 EnsureRelayoutData();
4526 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4528 if( dimension & ( 1 << i ) )
4530 return mRelayoutData->minimumSize[ i ];
4534 return 0.0f; // Default
4537 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4539 EnsureRelayoutData();
4541 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4543 if( dimension & ( 1 << i ) )
4545 mRelayoutData->maximumSize[ i ] = size;
4552 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4554 EnsureRelayoutData();
4556 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4558 if( dimension & ( 1 << i ) )
4560 return mRelayoutData->maximumSize[ i ];
4564 return 0.0f; // Default
4567 } // namespace Internal