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( 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;
2386 // This stage is atomic i.e. not interrupted by user callbacks
2387 RecursiveConnectToStage( connectionList, index );
2389 // Notify applications about the newly connected actors.
2390 const ActorIter endIter = connectionList.end();
2391 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2393 Actor& actor = GetImplementation( *iter );
2394 actor.NotifyStageConnection();
2400 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2402 DALI_ASSERT_ALWAYS( !OnStage() );
2406 ConnectToSceneGraph( index );
2408 // Notification for internal derived classes
2409 OnStageConnectionInternal();
2411 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2412 connectionList.push_back( Dali::Actor( this ) );
2414 // Recursively connect children
2417 ActorConstIter endIter = mChildren->end();
2418 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2420 Actor& actor = GetImplementation( *iter );
2421 actor.RecursiveConnectToStage( connectionList );
2427 * This method is called when the Actor is connected to the Stage.
2428 * The parent must have added its Node to the scene-graph.
2429 * The child must connect its Node to the parent's Node.
2430 * This is resursive; the child calls ConnectToStage() for its children.
2432 void Actor::ConnectToSceneGraph( int index )
2434 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2438 // Reparent Node in next Update
2439 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2442 // Notify attachment
2445 mAttachment->Connect();
2448 #ifdef DYNAMICS_SUPPORT
2450 if( NULL != mDynamicsData )
2456 // Request relayout on all actors that are added to the scenegraph
2459 // Notification for Object::Observers
2463 void Actor::NotifyStageConnection()
2465 // Actors can be removed (in a callback), before the on-stage stage is reported.
2466 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2467 if( OnStage() && !mOnStageSignalled )
2469 // Notification for external (CustomActor) derived classes
2470 OnStageConnectionExternal();
2472 if( !mOnStageSignal.Empty() )
2474 Dali::Actor handle( this );
2475 mOnStageSignal.Emit( handle );
2478 // Guard against Remove during callbacks
2481 mOnStageSignalled = true; // signal required next time Actor is removed
2486 void Actor::DisconnectFromStage()
2488 // This container is used instead of walking the Actor hierachy.
2489 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2490 ActorContainer disconnectionList;
2492 // This stage is atomic i.e. not interrupted by user callbacks
2493 RecursiveDisconnectFromStage( disconnectionList );
2495 // Notify applications about the newly disconnected actors.
2496 const ActorIter endIter = disconnectionList.end();
2497 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2499 Actor& actor = GetImplementation( *iter );
2500 actor.NotifyStageDisconnection();
2504 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2506 DALI_ASSERT_ALWAYS( OnStage() );
2508 // Recursively disconnect children
2511 ActorConstIter endIter = mChildren->end();
2512 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2514 Actor& actor = GetImplementation( *iter );
2515 actor.RecursiveDisconnectFromStage( disconnectionList );
2519 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2520 disconnectionList.push_back( Dali::Actor( this ) );
2522 // Notification for internal derived classes
2523 OnStageDisconnectionInternal();
2525 DisconnectFromSceneGraph();
2531 * This method is called by an actor or its parent, before a node removal message is sent.
2532 * This is recursive; the child calls DisconnectFromStage() for its children.
2534 void Actor::DisconnectFromSceneGraph()
2536 // Notification for Object::Observers
2537 OnSceneObjectRemove();
2539 // Notify attachment
2542 mAttachment->Disconnect();
2545 #ifdef DYNAMICS_SUPPORT
2547 if( NULL != mDynamicsData )
2549 DisconnectDynamics();
2554 void Actor::NotifyStageDisconnection()
2556 // Actors can be added (in a callback), before the off-stage state is reported.
2557 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2558 // only do this step if there is a stage, i.e. Core is not being shut down
2559 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2561 // Notification for external (CustomeActor) derived classes
2562 OnStageDisconnectionExternal();
2564 if( !mOffStageSignal.Empty() )
2566 Dali::Actor handle( this );
2567 mOffStageSignal.Emit( handle );
2570 // Guard against Add during callbacks
2573 mOnStageSignalled = false; // signal required next time Actor is added
2578 bool Actor::IsNodeConnected() const
2580 bool connected( false );
2585 if( mNode->IsRoot() || mNode->GetParent() )
2594 unsigned int Actor::GetDefaultPropertyCount() const
2596 return DEFAULT_PROPERTY_COUNT;
2599 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2601 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2603 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2605 indices.PushBack( i );
2609 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2611 if( index < DEFAULT_PROPERTY_COUNT )
2613 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2619 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2621 Property::Index index = Property::INVALID_INDEX;
2623 // Look for name in default properties
2624 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2626 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2627 if( 0 == name.compare( property->name ) )
2637 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2639 if( index < DEFAULT_PROPERTY_COUNT )
2641 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2647 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2649 if( index < DEFAULT_PROPERTY_COUNT )
2651 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2657 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2659 if( index < DEFAULT_PROPERTY_COUNT )
2661 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2667 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2669 if( index < DEFAULT_PROPERTY_COUNT )
2671 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2674 // index out of range...return Property::NONE
2675 return Property::NONE;
2678 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2682 case Dali::Actor::Property::PARENT_ORIGIN:
2684 SetParentOrigin( property.Get< Vector3 >() );
2688 case Dali::Actor::Property::PARENT_ORIGIN_X:
2690 SetParentOriginX( property.Get< float >() );
2694 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2696 SetParentOriginY( property.Get< float >() );
2700 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2702 SetParentOriginZ( property.Get< float >() );
2706 case Dali::Actor::Property::ANCHOR_POINT:
2708 SetAnchorPoint( property.Get< Vector3 >() );
2712 case Dali::Actor::Property::ANCHOR_POINT_X:
2714 SetAnchorPointX( property.Get< float >() );
2718 case Dali::Actor::Property::ANCHOR_POINT_Y:
2720 SetAnchorPointY( property.Get< float >() );
2724 case Dali::Actor::Property::ANCHOR_POINT_Z:
2726 SetAnchorPointZ( property.Get< float >() );
2730 case Dali::Actor::Property::SIZE:
2732 SetSize( property.Get< Vector3 >() );
2736 case Dali::Actor::Property::SIZE_WIDTH:
2738 SetWidth( property.Get< float >() );
2742 case Dali::Actor::Property::SIZE_HEIGHT:
2744 SetHeight( property.Get< float >() );
2748 case Dali::Actor::Property::SIZE_DEPTH:
2750 SetDepth( property.Get< float >() );
2754 case Dali::Actor::Property::POSITION:
2756 SetPosition( property.Get< Vector3 >() );
2760 case Dali::Actor::Property::POSITION_X:
2762 SetX( property.Get< float >() );
2766 case Dali::Actor::Property::POSITION_Y:
2768 SetY( property.Get< float >() );
2772 case Dali::Actor::Property::POSITION_Z:
2774 SetZ( property.Get< float >() );
2778 case Dali::Actor::Property::ORIENTATION:
2780 SetOrientation( property.Get< Quaternion >() );
2784 case Dali::Actor::Property::SCALE:
2786 SetScale( property.Get< Vector3 >() );
2790 case Dali::Actor::Property::SCALE_X:
2792 SetScaleX( property.Get< float >() );
2796 case Dali::Actor::Property::SCALE_Y:
2798 SetScaleY( property.Get< float >() );
2802 case Dali::Actor::Property::SCALE_Z:
2804 SetScaleZ( property.Get< float >() );
2808 case Dali::Actor::Property::VISIBLE:
2810 SetVisible( property.Get< bool >() );
2814 case Dali::Actor::Property::COLOR:
2816 SetColor( property.Get< Vector4 >() );
2820 case Dali::Actor::Property::COLOR_RED:
2822 SetColorRed( property.Get< float >() );
2826 case Dali::Actor::Property::COLOR_GREEN:
2828 SetColorGreen( property.Get< float >() );
2832 case Dali::Actor::Property::COLOR_BLUE:
2834 SetColorBlue( property.Get< float >() );
2838 case Dali::Actor::Property::COLOR_ALPHA:
2840 SetOpacity( property.Get< float >() );
2844 case Dali::Actor::Property::NAME:
2846 SetName( property.Get< std::string >() );
2850 case Dali::Actor::Property::SENSITIVE:
2852 SetSensitive( property.Get< bool >() );
2856 case Dali::Actor::Property::LEAVE_REQUIRED:
2858 SetLeaveRequired( property.Get< bool >() );
2862 case Dali::Actor::Property::INHERIT_ORIENTATION:
2864 SetInheritOrientation( property.Get< bool >() );
2868 case Dali::Actor::Property::INHERIT_SCALE:
2870 SetInheritScale( property.Get< bool >() );
2874 case Dali::Actor::Property::COLOR_MODE:
2876 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2880 case Dali::Actor::Property::POSITION_INHERITANCE:
2882 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2886 case Dali::Actor::Property::DRAW_MODE:
2888 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2892 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2894 SetSizeModeFactor( property.Get< Vector3 >() );
2898 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2900 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2904 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2906 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2910 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2912 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2916 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2918 if( property.Get< bool >() )
2920 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2925 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2927 if( property.Get< bool >() )
2929 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2934 case Dali::Actor::Property::PADDING:
2936 Vector4 padding = property.Get< Vector4 >();
2937 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2938 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2942 case Dali::Actor::Property::MINIMUM_SIZE:
2944 Vector2 size = property.Get< Vector2 >();
2945 SetMinimumSize( size.x, Dimension::WIDTH );
2946 SetMinimumSize( size.y, Dimension::HEIGHT );
2950 case Dali::Actor::Property::MAXIMUM_SIZE:
2952 Vector2 size = property.Get< Vector2 >();
2953 SetMaximumSize( size.x, Dimension::WIDTH );
2954 SetMaximumSize( size.y, Dimension::HEIGHT );
2960 // this can happen in the case of a non-animatable default property so just do nothing
2966 // TODO: This method needs to be removed
2967 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2969 switch( entry.type )
2971 case Property::BOOLEAN:
2973 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2974 DALI_ASSERT_DEBUG( NULL != property );
2976 // property is being used in a separate thread; queue a message to set the property
2977 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2982 case Property::INTEGER:
2984 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2985 DALI_ASSERT_DEBUG( NULL != property );
2987 // property is being used in a separate thread; queue a message to set the property
2988 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2993 case Property::UNSIGNED_INTEGER:
2995 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2996 DALI_ASSERT_DEBUG( NULL != property );
2998 // property is being used in a separate thread; queue a message to set the property
2999 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
3004 case Property::FLOAT:
3006 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3007 DALI_ASSERT_DEBUG( NULL != property );
3009 // property is being used in a separate thread; queue a message to set the property
3010 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3015 case Property::VECTOR2:
3017 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3018 DALI_ASSERT_DEBUG( NULL != property );
3020 // property is being used in a separate thread; queue a message to set the property
3021 if(entry.componentIndex == 0)
3023 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3025 else if(entry.componentIndex == 1)
3027 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3031 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3037 case Property::VECTOR3:
3039 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3040 DALI_ASSERT_DEBUG( NULL != property );
3042 // property is being used in a separate thread; queue a message to set the property
3043 if(entry.componentIndex == 0)
3045 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3047 else if(entry.componentIndex == 1)
3049 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3051 else if(entry.componentIndex == 2)
3053 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3057 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3063 case Property::VECTOR4:
3065 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3066 DALI_ASSERT_DEBUG( NULL != property );
3068 // property is being used in a separate thread; queue a message to set the property
3069 if(entry.componentIndex == 0)
3071 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3073 else if(entry.componentIndex == 1)
3075 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3077 else if(entry.componentIndex == 2)
3079 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3081 else if(entry.componentIndex == 3)
3083 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3087 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3093 case Property::ROTATION:
3095 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3096 DALI_ASSERT_DEBUG( NULL != property );
3098 // property is being used in a separate thread; queue a message to set the property
3099 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3104 case Property::MATRIX:
3106 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3107 DALI_ASSERT_DEBUG( NULL != property );
3109 // property is being used in a separate thread; queue a message to set the property
3110 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3115 case Property::MATRIX3:
3117 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3118 DALI_ASSERT_DEBUG( NULL != property );
3120 // property is being used in a separate thread; queue a message to set the property
3121 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3128 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3134 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3136 Property::Value value;
3140 case Dali::Actor::Property::PARENT_ORIGIN:
3142 value = GetCurrentParentOrigin();
3146 case Dali::Actor::Property::PARENT_ORIGIN_X:
3148 value = GetCurrentParentOrigin().x;
3152 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3154 value = GetCurrentParentOrigin().y;
3158 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3160 value = GetCurrentParentOrigin().z;
3164 case Dali::Actor::Property::ANCHOR_POINT:
3166 value = GetCurrentAnchorPoint();
3170 case Dali::Actor::Property::ANCHOR_POINT_X:
3172 value = GetCurrentAnchorPoint().x;
3176 case Dali::Actor::Property::ANCHOR_POINT_Y:
3178 value = GetCurrentAnchorPoint().y;
3182 case Dali::Actor::Property::ANCHOR_POINT_Z:
3184 value = GetCurrentAnchorPoint().z;
3188 case Dali::Actor::Property::SIZE:
3190 value = GetCurrentSize();
3194 case Dali::Actor::Property::SIZE_WIDTH:
3196 value = GetCurrentSize().width;
3200 case Dali::Actor::Property::SIZE_HEIGHT:
3202 value = GetCurrentSize().height;
3206 case Dali::Actor::Property::SIZE_DEPTH:
3208 value = GetCurrentSize().depth;
3212 case Dali::Actor::Property::POSITION:
3214 value = GetCurrentPosition();
3218 case Dali::Actor::Property::POSITION_X:
3220 value = GetCurrentPosition().x;
3224 case Dali::Actor::Property::POSITION_Y:
3226 value = GetCurrentPosition().y;
3230 case Dali::Actor::Property::POSITION_Z:
3232 value = GetCurrentPosition().z;
3236 case Dali::Actor::Property::WORLD_POSITION:
3238 value = GetCurrentWorldPosition();
3242 case Dali::Actor::Property::WORLD_POSITION_X:
3244 value = GetCurrentWorldPosition().x;
3248 case Dali::Actor::Property::WORLD_POSITION_Y:
3250 value = GetCurrentWorldPosition().y;
3254 case Dali::Actor::Property::WORLD_POSITION_Z:
3256 value = GetCurrentWorldPosition().z;
3260 case Dali::Actor::Property::ORIENTATION:
3262 value = GetCurrentOrientation();
3266 case Dali::Actor::Property::WORLD_ORIENTATION:
3268 value = GetCurrentWorldOrientation();
3272 case Dali::Actor::Property::SCALE:
3274 value = GetCurrentScale();
3278 case Dali::Actor::Property::SCALE_X:
3280 value = GetCurrentScale().x;
3284 case Dali::Actor::Property::SCALE_Y:
3286 value = GetCurrentScale().y;
3290 case Dali::Actor::Property::SCALE_Z:
3292 value = GetCurrentScale().z;
3296 case Dali::Actor::Property::WORLD_SCALE:
3298 value = GetCurrentWorldScale();
3302 case Dali::Actor::Property::VISIBLE:
3304 value = IsVisible();
3308 case Dali::Actor::Property::COLOR:
3310 value = GetCurrentColor();
3314 case Dali::Actor::Property::COLOR_RED:
3316 value = GetCurrentColor().r;
3320 case Dali::Actor::Property::COLOR_GREEN:
3322 value = GetCurrentColor().g;
3326 case Dali::Actor::Property::COLOR_BLUE:
3328 value = GetCurrentColor().b;
3332 case Dali::Actor::Property::COLOR_ALPHA:
3334 value = GetCurrentColor().a;
3338 case Dali::Actor::Property::WORLD_COLOR:
3340 value = GetCurrentWorldColor();
3344 case Dali::Actor::Property::WORLD_MATRIX:
3346 value = GetCurrentWorldMatrix();
3350 case Dali::Actor::Property::NAME:
3356 case Dali::Actor::Property::SENSITIVE:
3358 value = IsSensitive();
3362 case Dali::Actor::Property::LEAVE_REQUIRED:
3364 value = GetLeaveRequired();
3368 case Dali::Actor::Property::INHERIT_ORIENTATION:
3370 value = IsOrientationInherited();
3374 case Dali::Actor::Property::INHERIT_SCALE:
3376 value = IsScaleInherited();
3380 case Dali::Actor::Property::COLOR_MODE:
3382 value = Scripting::GetColorMode( GetColorMode() );
3386 case Dali::Actor::Property::POSITION_INHERITANCE:
3388 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3392 case Dali::Actor::Property::DRAW_MODE:
3394 value = Scripting::GetDrawMode( GetDrawMode() );
3398 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3400 value = GetSizeModeFactor();
3404 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3406 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3410 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3412 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3416 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3418 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3422 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3424 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3428 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3430 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3434 case Dali::Actor::Property::PADDING:
3436 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3437 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3438 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3442 case Dali::Actor::Property::MINIMUM_SIZE:
3444 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3448 case Dali::Actor::Property::MAXIMUM_SIZE:
3450 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3456 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3464 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3469 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3471 // This method should only return an object connected to the scene-graph
3472 return OnStage() ? mNode : NULL;
3475 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3477 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3479 const PropertyBase* property( NULL );
3481 // This method should only return a property of an object connected to the scene-graph
3487 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3489 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3490 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3492 property = animatable->GetSceneGraphProperty();
3494 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3496 CustomPropertyMetadata* custom = FindCustomProperty( index );
3497 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3499 property = custom->GetSceneGraphProperty();
3501 else if( NULL != mNode )
3505 case Dali::Actor::Property::SIZE:
3506 property = &mNode->mSize;
3509 case Dali::Actor::Property::SIZE_WIDTH:
3510 property = &mNode->mSize;
3513 case Dali::Actor::Property::SIZE_HEIGHT:
3514 property = &mNode->mSize;
3517 case Dali::Actor::Property::SIZE_DEPTH:
3518 property = &mNode->mSize;
3521 case Dali::Actor::Property::POSITION:
3522 property = &mNode->mPosition;
3525 case Dali::Actor::Property::POSITION_X:
3526 property = &mNode->mPosition;
3529 case Dali::Actor::Property::POSITION_Y:
3530 property = &mNode->mPosition;
3533 case Dali::Actor::Property::POSITION_Z:
3534 property = &mNode->mPosition;
3537 case Dali::Actor::Property::ORIENTATION:
3538 property = &mNode->mOrientation;
3541 case Dali::Actor::Property::SCALE:
3542 property = &mNode->mScale;
3545 case Dali::Actor::Property::SCALE_X:
3546 property = &mNode->mScale;
3549 case Dali::Actor::Property::SCALE_Y:
3550 property = &mNode->mScale;
3553 case Dali::Actor::Property::SCALE_Z:
3554 property = &mNode->mScale;
3557 case Dali::Actor::Property::VISIBLE:
3558 property = &mNode->mVisible;
3561 case Dali::Actor::Property::COLOR:
3562 property = &mNode->mColor;
3565 case Dali::Actor::Property::COLOR_RED:
3566 property = &mNode->mColor;
3569 case Dali::Actor::Property::COLOR_GREEN:
3570 property = &mNode->mColor;
3573 case Dali::Actor::Property::COLOR_BLUE:
3574 property = &mNode->mColor;
3577 case Dali::Actor::Property::COLOR_ALPHA:
3578 property = &mNode->mColor;
3589 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3591 const PropertyInputImpl* property( NULL );
3593 // This method should only return a property of an object connected to the scene-graph
3599 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3601 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3602 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3604 property = animatable->GetSceneGraphProperty();
3606 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3608 CustomPropertyMetadata* custom = FindCustomProperty( index );
3609 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3610 property = custom->GetSceneGraphProperty();
3612 else if( NULL != mNode )
3616 case Dali::Actor::Property::PARENT_ORIGIN:
3617 property = &mNode->mParentOrigin;
3620 case Dali::Actor::Property::PARENT_ORIGIN_X:
3621 property = &mNode->mParentOrigin;
3624 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3625 property = &mNode->mParentOrigin;
3628 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3629 property = &mNode->mParentOrigin;
3632 case Dali::Actor::Property::ANCHOR_POINT:
3633 property = &mNode->mAnchorPoint;
3636 case Dali::Actor::Property::ANCHOR_POINT_X:
3637 property = &mNode->mAnchorPoint;
3640 case Dali::Actor::Property::ANCHOR_POINT_Y:
3641 property = &mNode->mAnchorPoint;
3644 case Dali::Actor::Property::ANCHOR_POINT_Z:
3645 property = &mNode->mAnchorPoint;
3648 case Dali::Actor::Property::SIZE:
3649 property = &mNode->mSize;
3652 case Dali::Actor::Property::SIZE_WIDTH:
3653 property = &mNode->mSize;
3656 case Dali::Actor::Property::SIZE_HEIGHT:
3657 property = &mNode->mSize;
3660 case Dali::Actor::Property::SIZE_DEPTH:
3661 property = &mNode->mSize;
3664 case Dali::Actor::Property::POSITION:
3665 property = &mNode->mPosition;
3668 case Dali::Actor::Property::POSITION_X:
3669 property = &mNode->mPosition;
3672 case Dali::Actor::Property::POSITION_Y:
3673 property = &mNode->mPosition;
3676 case Dali::Actor::Property::POSITION_Z:
3677 property = &mNode->mPosition;
3680 case Dali::Actor::Property::WORLD_POSITION:
3681 property = &mNode->mWorldPosition;
3684 case Dali::Actor::Property::WORLD_POSITION_X:
3685 property = &mNode->mWorldPosition;
3688 case Dali::Actor::Property::WORLD_POSITION_Y:
3689 property = &mNode->mWorldPosition;
3692 case Dali::Actor::Property::WORLD_POSITION_Z:
3693 property = &mNode->mWorldPosition;
3696 case Dali::Actor::Property::ORIENTATION:
3697 property = &mNode->mOrientation;
3700 case Dali::Actor::Property::WORLD_ORIENTATION:
3701 property = &mNode->mWorldOrientation;
3704 case Dali::Actor::Property::SCALE:
3705 property = &mNode->mScale;
3708 case Dali::Actor::Property::SCALE_X:
3709 property = &mNode->mScale;
3712 case Dali::Actor::Property::SCALE_Y:
3713 property = &mNode->mScale;
3716 case Dali::Actor::Property::SCALE_Z:
3717 property = &mNode->mScale;
3720 case Dali::Actor::Property::WORLD_SCALE:
3721 property = &mNode->mWorldScale;
3724 case Dali::Actor::Property::VISIBLE:
3725 property = &mNode->mVisible;
3728 case Dali::Actor::Property::COLOR:
3729 property = &mNode->mColor;
3732 case Dali::Actor::Property::COLOR_RED:
3733 property = &mNode->mColor;
3736 case Dali::Actor::Property::COLOR_GREEN:
3737 property = &mNode->mColor;
3740 case Dali::Actor::Property::COLOR_BLUE:
3741 property = &mNode->mColor;
3744 case Dali::Actor::Property::COLOR_ALPHA:
3745 property = &mNode->mColor;
3748 case Dali::Actor::Property::WORLD_COLOR:
3749 property = &mNode->mWorldColor;
3752 case Dali::Actor::Property::WORLD_MATRIX:
3753 property = &mNode->mWorldMatrix;
3764 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3766 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3768 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3770 // check whether the animatable property is registered already, if not then register one.
3771 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3772 if( animatableProperty )
3774 componentIndex = animatableProperty->componentIndex;
3781 case Dali::Actor::Property::PARENT_ORIGIN_X:
3782 case Dali::Actor::Property::ANCHOR_POINT_X:
3783 case Dali::Actor::Property::SIZE_WIDTH:
3784 case Dali::Actor::Property::POSITION_X:
3785 case Dali::Actor::Property::WORLD_POSITION_X:
3786 case Dali::Actor::Property::SCALE_X:
3787 case Dali::Actor::Property::COLOR_RED:
3793 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3794 case Dali::Actor::Property::ANCHOR_POINT_Y:
3795 case Dali::Actor::Property::SIZE_HEIGHT:
3796 case Dali::Actor::Property::POSITION_Y:
3797 case Dali::Actor::Property::WORLD_POSITION_Y:
3798 case Dali::Actor::Property::SCALE_Y:
3799 case Dali::Actor::Property::COLOR_GREEN:
3805 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3806 case Dali::Actor::Property::ANCHOR_POINT_Z:
3807 case Dali::Actor::Property::SIZE_DEPTH:
3808 case Dali::Actor::Property::POSITION_Z:
3809 case Dali::Actor::Property::WORLD_POSITION_Z:
3810 case Dali::Actor::Property::SCALE_Z:
3811 case Dali::Actor::Property::COLOR_BLUE:
3817 case Dali::Actor::Property::COLOR_ALPHA:
3831 return componentIndex;
3834 void Actor::SetParent( Actor* parent, int index )
3838 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3842 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3845 // Instruct each actor to create a corresponding node in the scene graph
3846 ConnectToStage( index );
3849 else // parent being set to NULL
3851 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3855 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3858 DALI_ASSERT_ALWAYS( mNode != NULL );
3862 // Disconnect the Node & its children from the scene-graph.
3863 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3866 // Instruct each actor to discard pointers to the scene-graph
3867 DisconnectFromStage();
3872 SceneGraph::Node* Actor::CreateNode() const
3877 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3880 Actor* actor = dynamic_cast< Actor* >( object );
3884 if( 0 == actionName.compare( ACTION_SHOW ) )
3886 actor->SetVisible( true );
3889 else if( 0 == actionName.compare( ACTION_HIDE ) )
3891 actor->SetVisible( false );
3899 void Actor::EnsureRelayoutData() const
3901 // Assign relayout data.
3902 if( !mRelayoutData )
3904 mRelayoutData = new RelayoutData();
3908 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3910 // Check if actor is dependent on parent
3911 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3913 if( ( dimension & ( 1 << i ) ) )
3915 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3916 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3926 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3928 // Check if actor is dependent on children
3929 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3931 if( ( dimension & ( 1 << i ) ) )
3933 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3934 switch( resizePolicy )
3936 case ResizePolicy::FIT_TO_CHILDREN:
3937 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3953 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3955 return Actor::RelayoutDependentOnChildren( dimension );
3958 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3960 // Check each possible dimension and see if it is dependent on the input one
3961 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3963 if( dimension & ( 1 << i ) )
3965 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3972 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3974 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3976 if( dimension & ( 1 << i ) )
3978 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3983 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3985 // If more than one dimension is requested, just return the first one found
3986 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3988 if( ( dimension & ( 1 << i ) ) )
3990 return mRelayoutData->negotiatedDimensions[ i ];
3994 return 0.0f; // Default
3997 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3999 EnsureRelayoutData();
4001 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4003 if( dimension & ( 1 << i ) )
4005 mRelayoutData->dimensionPadding[ i ] = padding;
4010 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4012 EnsureRelayoutData();
4014 // If more than one dimension is requested, just return the first one found
4015 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4017 if( ( dimension & ( 1 << i ) ) )
4019 return mRelayoutData->dimensionPadding[ i ];
4023 return Vector2( 0.0f, 0.0f ); // Default
4026 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4028 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4030 if( dimension & ( 1 << i ) )
4032 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4037 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4039 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4041 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4050 float Actor::GetHeightForWidthBase( float width )
4052 float height = 0.0f;
4054 const Vector3 naturalSize = GetNaturalSize();
4055 if( naturalSize.width > 0.0f )
4057 height = naturalSize.height * width / naturalSize.width;
4059 else // we treat 0 as 1:1 aspect ratio
4067 float Actor::GetWidthForHeightBase( float height )
4071 const Vector3 naturalSize = GetNaturalSize();
4072 if( naturalSize.height > 0.0f )
4074 width = naturalSize.width * height / naturalSize.height;
4076 else // we treat 0 as 1:1 aspect ratio
4084 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4086 // Fill to parent, taking size mode factor into account
4087 switch( child.GetResizePolicy( dimension ) )
4089 case ResizePolicy::FILL_TO_PARENT:
4091 return GetLatestSize( dimension );
4094 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4096 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4099 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4101 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4106 return GetLatestSize( dimension );
4111 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4113 // Can be overridden in derived class
4114 return CalculateChildSizeBase( child, dimension );
4117 float Actor::GetHeightForWidth( float width )
4119 // Can be overridden in derived class
4120 return GetHeightForWidthBase( width );
4123 float Actor::GetWidthForHeight( float height )
4125 // Can be overridden in derived class
4126 return GetWidthForHeightBase( height );
4129 float Actor::GetLatestSize( Dimension::Type dimension ) const
4131 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4134 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4136 Vector2 padding = GetPadding( dimension );
4138 return GetLatestSize( dimension ) + padding.x + padding.y;
4141 float Actor::NegotiateFromParent( Dimension::Type dimension )
4143 Actor* parent = GetParent();
4146 Vector2 padding( GetPadding( dimension ) );
4147 Vector2 parentPadding( parent->GetPadding( dimension ) );
4148 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4154 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4156 float maxDimensionPoint = 0.0f;
4158 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4160 Dali::Actor child = GetChildAt( i );
4161 Actor& childImpl = GetImplementation( child );
4163 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4165 // Calculate the min and max points that the children range across
4166 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4167 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4168 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4172 return maxDimensionPoint;
4175 float Actor::GetSize( Dimension::Type dimension ) const
4177 return GetDimensionValue( GetTargetSize(), dimension );
4180 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4182 return GetDimensionValue( GetNaturalSize(), dimension );
4185 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4187 switch( GetResizePolicy( dimension ) )
4189 case ResizePolicy::USE_NATURAL_SIZE:
4191 return GetNaturalSize( dimension );
4194 case ResizePolicy::FIXED:
4196 return GetDimensionValue( GetPreferredSize(), dimension );
4199 case ResizePolicy::USE_ASSIGNED_SIZE:
4201 return GetDimensionValue( maximumSize, dimension );
4204 case ResizePolicy::FILL_TO_PARENT:
4205 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4206 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4208 return NegotiateFromParent( dimension );
4211 case ResizePolicy::FIT_TO_CHILDREN:
4213 return NegotiateFromChildren( dimension );
4216 case ResizePolicy::DIMENSION_DEPENDENCY:
4218 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4221 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4223 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4226 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4228 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4240 return 0.0f; // Default
4243 float Actor::ClampDimension( float size, Dimension::Type dimension )
4245 const float minSize = GetMinimumSize( dimension );
4246 const float maxSize = GetMaximumSize( dimension );
4248 return std::max( minSize, std::min( size, maxSize ) );
4251 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4253 // Check if it needs to be negotiated
4254 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4256 // Check that we havn't gotten into an infinite loop
4257 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4258 bool recursionFound = false;
4259 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4261 if( *it == searchActor )
4263 recursionFound = true;
4268 if( !recursionFound )
4270 // Record the path that we have taken
4271 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4273 // Dimension dependency check
4274 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4276 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4278 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4280 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4284 // Parent dependency check
4285 Actor* parent = GetParent();
4286 if( parent && RelayoutDependentOnParent( dimension ) )
4288 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4291 // Children dependency check
4292 if( RelayoutDependentOnChildren( dimension ) )
4294 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4296 Dali::Actor child = GetChildAt( i );
4297 Actor& childImpl = GetImplementation( child );
4299 // Only relayout child first if it is not dependent on this actor
4300 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4302 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4307 // For deriving classes
4308 OnCalculateRelayoutSize( dimension );
4310 // All dependencies checked, calculate the size and set negotiated flag
4311 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4313 SetNegotiatedDimension( newSize, dimension );
4314 SetLayoutNegotiated( true, dimension );
4316 // For deriving classes
4317 OnLayoutNegotiated( newSize, dimension );
4319 // This actor has been successfully processed, pop it off the recursion stack
4320 recursionStack.pop_back();
4324 // TODO: Break infinite loop
4325 SetLayoutNegotiated( true, dimension );
4330 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4332 // Negotiate all dimensions that require it
4333 ActorDimensionStack recursionStack;
4335 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4337 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4340 NegotiateDimension( dimension, allocatedSize, recursionStack );
4344 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4346 switch( mRelayoutData->sizeSetPolicy )
4348 case SizeScalePolicy::USE_SIZE_SET:
4353 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4355 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4356 const Vector3 naturalSize = GetNaturalSize();
4357 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4359 const float sizeRatio = size.width / size.height;
4360 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4362 if( naturalSizeRatio < sizeRatio )
4364 return Vector2( naturalSizeRatio * size.height, size.height );
4366 else if( naturalSizeRatio > sizeRatio )
4368 return Vector2( size.width, size.width / naturalSizeRatio );
4379 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4381 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4382 const Vector3 naturalSize = GetNaturalSize();
4383 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4385 const float sizeRatio = size.width / size.height;
4386 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4388 if( naturalSizeRatio < sizeRatio )
4390 return Vector2( size.width, size.width / naturalSizeRatio );
4392 else if( naturalSizeRatio > sizeRatio )
4394 return Vector2( naturalSizeRatio * size.height, size.height );
4412 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4414 // Do the set actor size
4415 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4417 // Adjust for size set policy
4418 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4420 // Lock the flag to stop recursive relayouts on set size
4421 mRelayoutData->insideRelayout = true;
4422 SetSize( negotiatedSize );
4423 mRelayoutData->insideRelayout = false;
4425 // Clear flags for all dimensions
4426 SetLayoutDirty( false );
4428 // Give deriving classes a chance to respond
4429 OnRelayout( negotiatedSize, container );
4431 if( !mOnRelayoutSignal.Empty() )
4433 Dali::Actor handle( this );
4434 mOnRelayoutSignal.Emit( handle );
4438 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4440 // Do the negotiation
4441 NegotiateDimensions( allocatedSize );
4443 // Set the actor size
4444 SetNegotiatedSize( container );
4446 // Negotiate down to children
4447 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4449 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4451 Dali::Actor child = GetChildAt( i );
4453 // Only relayout if required
4454 if( GetImplementation( child ).RelayoutRequired() )
4456 container.Add( child, newBounds );
4461 void Actor::RelayoutRequest( Dimension::Type dimension )
4463 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4464 if( relayoutController )
4466 Dali::Actor self( this );
4467 relayoutController->RequestRelayout( self, dimension );
4471 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4475 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4479 void Actor::SetPreferredSize( const Vector2& size )
4481 EnsureRelayoutData();
4483 if( size.width > 0.0f )
4485 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4488 if( size.height > 0.0f )
4490 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4493 mRelayoutData->preferredSize = size;
4498 Vector2 Actor::GetPreferredSize() const
4500 EnsureRelayoutData();
4502 return mRelayoutData->preferredSize;
4505 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4507 EnsureRelayoutData();
4509 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4511 if( dimension & ( 1 << i ) )
4513 mRelayoutData->minimumSize[ i ] = size;
4520 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4522 EnsureRelayoutData();
4524 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4526 if( dimension & ( 1 << i ) )
4528 return mRelayoutData->minimumSize[ i ];
4532 return 0.0f; // Default
4535 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4537 EnsureRelayoutData();
4539 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4541 if( dimension & ( 1 << i ) )
4543 mRelayoutData->maximumSize[ i ] = size;
4550 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4552 EnsureRelayoutData();
4554 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4556 if( dimension & ( 1 << i ) )
4558 return mRelayoutData->maximumSize[ i ];
4562 return 0.0f; // Default
4565 } // namespace Internal