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>
25 #include <cstring> // for strcmp
29 #include <dali/public-api/common/dali-common.h>
30 #include <dali/public-api/common/constants.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/public-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/actor-attachments/actor-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 )DALI_ENUM_TO_STRING( FIXED )
76 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
77 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
80 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
81 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
82 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
83 DALI_ENUM_TO_STRING_TABLE_END( Type )
85 } // unnamed namespace
88 namespace SizeScalePolicy
92 // Enumeration to / from string conversion tables
93 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
94 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
95 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING_TABLE_END( Type )
97 } // unnamed namespace
103 unsigned int Actor::mActorCounter = 0;
104 ActorContainer Actor::mNullChildren;
107 * Struct to collect relayout variables
109 struct Actor::RelayoutData
112 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
114 // Set size negotiation defaults
115 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
117 resizePolicies[ i ] = ResizePolicy::FIXED;
118 negotiatedDimensions[ i ] = 0.0f;
119 dimensionNegotiated[ i ] = false;
120 dimensionDirty[ i ] = false;
121 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
122 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
123 minimumSize[ i ] = 0.0f;
124 maximumSize[ i ] = FLT_MAX;
128 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
130 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
132 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
134 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
136 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
137 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
139 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
140 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
142 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
144 Vector2 preferredSize; ///< The preferred size of the actor
146 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
148 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
149 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
152 #ifdef DYNAMICS_SUPPORT
154 // Encapsulate actor related dynamics data
157 DynamicsData( Actor* slotOwner )
158 : slotDelegate( slotOwner )
162 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
163 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
165 DynamicsBodyPtr body;
166 JointContainer joints;
167 ReferencedJointContainer referencedJoints;
169 SlotDelegate< Actor > slotDelegate;
172 #endif // DYNAMICS_SUPPORT
174 namespace // unnamed namespace
180 * We want to discourage the use of property strings (minimize string comparisons),
181 * particularly for the default properties.
182 * Name Type writable animatable constraint-input enum for index-checking
184 DALI_PROPERTY_TABLE_BEGIN
185 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
186 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
187 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
188 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
189 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
190 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
191 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
192 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
193 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
194 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
195 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
196 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
197 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
198 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
199 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
200 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
201 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
202 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
203 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
204 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
205 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
206 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
207 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
208 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
209 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
210 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
211 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
212 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
213 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
214 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
215 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
216 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
217 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
218 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
219 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
220 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
221 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
222 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
223 DALI_PROPERTY( "inherit-orientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
224 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
225 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
226 DALI_PROPERTY( "position-inheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
227 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
228 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
229 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
230 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
231 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
232 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
233 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
234 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
235 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
236 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
237 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
241 const char* const SIGNAL_TOUCHED = "touched";
242 const char* const SIGNAL_HOVERED = "hovered";
243 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
244 const char* const SIGNAL_ON_STAGE = "on-stage";
245 const char* const SIGNAL_OFF_STAGE = "off-stage";
249 const char* const ACTION_SHOW = "show";
250 const char* const ACTION_HIDE = "hide";
252 BaseHandle CreateActor()
254 return Dali::Actor::New();
257 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
259 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
264 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
265 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
268 * @brief Extract a given dimension from a Vector2
270 * @param[in] values The values to extract from
271 * @param[in] dimension The dimension to extract
272 * @return Return the value for the dimension
274 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
278 case Dimension::WIDTH:
283 case Dimension::HEIGHT:
285 return values.height;
298 * @brief Extract a given dimension from a Vector3
300 * @param[in] values The values to extract from
301 * @param[in] dimension The dimension to extract
302 * @return Return the value for the dimension
304 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
306 return GetDimensionValue( values.GetVectorXY(), dimension );
309 } // unnamed namespace
311 ActorPtr Actor::New()
313 ActorPtr actor( new Actor( BASIC ) );
315 // Second-phase construction
321 const std::string& Actor::GetName() const
326 void Actor::SetName( const std::string& name )
332 // ATTENTION: string for debug purposes is not thread safe.
333 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
337 unsigned int Actor::GetId() const
342 void Actor::Attach( ActorAttachment& attachment )
344 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
348 attachment.Connect();
351 mAttachment = ActorAttachmentPtr( &attachment );
354 ActorAttachmentPtr Actor::GetAttachment()
359 bool Actor::OnStage() const
364 Dali::Layer Actor::GetLayer()
368 // Short-circuit for Layer derived actors
371 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
374 // Find the immediate Layer parent
375 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
377 if( parent->IsLayer() )
379 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
386 void Actor::Add( Actor& child )
388 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
389 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
393 mChildren = new ActorContainer;
396 Actor* const oldParent( child.mParent );
398 // child might already be ours
399 if( this != oldParent )
401 // if we already have parent, unparent us first
404 oldParent->Remove( child ); // This causes OnChildRemove callback
406 // Old parent may need to readjust to missing child
407 if( oldParent->RelayoutDependentOnChildren() )
409 oldParent->RelayoutRequest();
413 // Guard against Add() during previous OnChildRemove callback
416 // Do this first, since user callbacks from within SetParent() may need to remove child
417 mChildren->push_back( Dali::Actor( &child ) );
419 // SetParent asserts that child can be added
420 child.SetParent( this );
422 // Notification for derived classes
425 // Only put in a relayout request if there is a suitable dependency
426 if( RelayoutDependentOnChildren() )
434 void Actor::Insert( unsigned int index, Actor& child )
436 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
437 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
441 mChildren = new ActorContainer;
444 Actor* const oldParent( child.mParent );
446 // since an explicit position has been given, always insert, even if already a child
449 oldParent->Remove( child ); // This causes OnChildRemove callback
451 // Old parent may need to readjust to missing child
452 if( oldParent->RelayoutDependentOnChildren() )
454 oldParent->RelayoutRequest();
458 // Guard against Add() during previous OnChildRemove callback
461 // Do this first, since user callbacks from within SetParent() may need to remove child
462 if( index < GetChildCount() )
464 ActorIter it = mChildren->begin();
465 std::advance( it, index );
466 mChildren->insert( it, Dali::Actor( &child ) );
470 mChildren->push_back( Dali::Actor( &child ) );
472 // SetParent asserts that child can be added
473 child.SetParent( this, index );
475 // Notification for derived classes
478 // Only put in a relayout request if there is a suitable dependency
479 if( RelayoutDependentOnChildren() )
484 if( child.RelayoutDependentOnParent() )
486 child.RelayoutRequest();
491 void Actor::Remove( Actor& child )
493 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
503 // Find the child in mChildren, and unparent it
504 ActorIter end = mChildren->end();
505 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
507 Actor& actor = GetImplementation( *iter );
509 if( &actor == &child )
511 // Keep handle for OnChildRemove notification
512 removed = Dali::Actor( &actor );
514 // Do this first, since user callbacks from within SetParent() may need to add the child
515 mChildren->erase( iter );
517 DALI_ASSERT_DEBUG( actor.GetParent() == this );
518 actor.SetParent( NULL );
526 // Notification for derived classes
527 OnChildRemove( GetImplementation( removed ) );
529 // Only put in a relayout request if there is a suitable dependency
530 if( RelayoutDependentOnChildren() )
537 void Actor::Unparent()
541 // Remove this actor from the parent. The remove will put a relayout request in for
542 // the parent if required
543 mParent->Remove( *this );
544 // mParent is now NULL!
548 unsigned int Actor::GetChildCount() const
550 return ( NULL != mChildren ) ? mChildren->size() : 0;
553 Dali::Actor Actor::GetChildAt( unsigned int index ) const
555 DALI_ASSERT_ALWAYS( index < GetChildCount() );
557 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
560 ActorPtr Actor::FindChildByName( const std::string& actorName )
563 if( actorName == mName )
569 ActorIter end = mChildren->end();
570 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
572 child = GetImplementation( *iter ).FindChildByName( actorName );
583 ActorPtr Actor::FindChildById( const unsigned int id )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = GetImplementation( *iter ).FindChildById( id );
606 void Actor::SetParentOrigin( const Vector3& origin )
610 // mNode is being used in a separate thread; queue a message to set the value & base value
611 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
614 // Cache for event-thread access
617 // not allocated, check if different from default
618 if( ParentOrigin::DEFAULT != origin )
620 mParentOrigin = new Vector3( origin );
625 // check if different from current costs more than just set
626 *mParentOrigin = origin;
630 void Actor::SetParentOriginX( float x )
632 const Vector3& current = GetCurrentParentOrigin();
634 SetParentOrigin( Vector3( x, current.y, current.z ) );
637 void Actor::SetParentOriginY( float y )
639 const Vector3& current = GetCurrentParentOrigin();
641 SetParentOrigin( Vector3( current.x, y, current.z ) );
644 void Actor::SetParentOriginZ( float z )
646 const Vector3& current = GetCurrentParentOrigin();
648 SetParentOrigin( Vector3( current.x, current.y, z ) );
651 const Vector3& Actor::GetCurrentParentOrigin() const
653 // Cached for event-thread access
654 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
657 void Actor::SetAnchorPoint( const Vector3& anchor )
661 // mNode is being used in a separate thread; queue a message to set the value & base value
662 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
665 // Cache for event-thread access
668 // not allocated, check if different from default
669 if( AnchorPoint::DEFAULT != anchor )
671 mAnchorPoint = new Vector3( anchor );
676 // check if different from current costs more than just set
677 *mAnchorPoint = anchor;
681 void Actor::SetAnchorPointX( float x )
683 const Vector3& current = GetCurrentAnchorPoint();
685 SetAnchorPoint( Vector3( x, current.y, current.z ) );
688 void Actor::SetAnchorPointY( float y )
690 const Vector3& current = GetCurrentAnchorPoint();
692 SetAnchorPoint( Vector3( current.x, y, current.z ) );
695 void Actor::SetAnchorPointZ( float z )
697 const Vector3& current = GetCurrentAnchorPoint();
699 SetAnchorPoint( Vector3( current.x, current.y, z ) );
702 const Vector3& Actor::GetCurrentAnchorPoint() const
704 // Cached for event-thread access
705 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
708 void Actor::SetPosition( float x, float y )
710 SetPosition( Vector3( x, y, 0.0f ) );
713 void Actor::SetPosition( float x, float y, float z )
715 SetPosition( Vector3( x, y, z ) );
718 void Actor::SetPosition( const Vector3& position )
720 mTargetPosition = position;
724 // mNode is being used in a separate thread; queue a message to set the value & base value
725 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
729 void Actor::SetX( float x )
731 mTargetPosition.x = x;
735 // mNode is being used in a separate thread; queue a message to set the value & base value
736 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
740 void Actor::SetY( float y )
742 mTargetPosition.y = y;
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
751 void Actor::SetZ( float z )
753 mTargetPosition.z = z;
757 // mNode is being used in a separate thread; queue a message to set the value & base value
758 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
762 void Actor::TranslateBy( const Vector3& distance )
764 mTargetPosition += distance;
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
773 const Vector3& Actor::GetCurrentPosition() const
777 // mNode is being used in a separate thread; copy the value from the previous update
778 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
781 return Vector3::ZERO;
784 const Vector3& Actor::GetTargetPosition() const
786 return mTargetPosition;
789 const Vector3& Actor::GetCurrentWorldPosition() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 return Vector3::ZERO;
800 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
802 // this flag is not animatable so keep the value
803 mPositionInheritanceMode = mode;
806 // mNode is being used in a separate thread; queue a message to set the value
807 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
811 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
813 // Cached for event-thread access
814 return mPositionInheritanceMode;
817 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
819 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
820 normalizedAxis.Normalize();
822 Quaternion orientation( angle, normalizedAxis );
824 SetOrientation( orientation );
827 void Actor::SetOrientation( const Quaternion& orientation )
831 // mNode is being used in a separate thread; queue a message to set the value & base value
832 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
836 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
840 // mNode is being used in a separate thread; queue a message to set the value & base value
841 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
845 void Actor::RotateBy( const Quaternion& relativeRotation )
849 // mNode is being used in a separate thread; queue a message to set the value & base value
850 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
854 const Quaternion& Actor::GetCurrentOrientation() const
858 // mNode is being used in a separate thread; copy the value from the previous update
859 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
862 return Quaternion::IDENTITY;
865 const Quaternion& Actor::GetCurrentWorldOrientation() const
869 // mNode is being used in a separate thread; copy the value from the previous update
870 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
873 return Quaternion::IDENTITY;
876 void Actor::SetScale( float scale )
878 SetScale( Vector3( scale, scale, scale ) );
881 void Actor::SetScale( float x, float y, float z )
883 SetScale( Vector3( x, y, z ) );
886 void Actor::SetScale( const Vector3& scale )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
895 void Actor::SetScaleX( float x )
899 // mNode is being used in a separate thread; queue a message to set the value & base value
900 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
904 void Actor::SetScaleY( float y )
908 // mNode is being used in a separate thread; queue a message to set the value & base value
909 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
913 void Actor::SetScaleZ( float z )
917 // mNode is being used in a separate thread; queue a message to set the value & base value
918 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
922 void Actor::SetInitialVolume( const Vector3& volume )
926 // mNode is being used in a separate thread; queue a message to set the value
927 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
931 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
935 // mNode is being used in a separate thread; queue a message to set the value
936 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
940 bool Actor::GetTransmitGeometryScaling() const
944 // mNode is being used in a separate thread; copy the value from the previous update
945 return mNode->GetTransmitGeometryScaling();
951 void Actor::ScaleBy( const Vector3& relativeScale )
955 // mNode is being used in a separate thread; queue a message to set the value & base value
956 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
960 const Vector3& Actor::GetCurrentScale() const
964 // mNode is being used in a separate thread; copy the value from the previous update
965 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
971 const Vector3& Actor::GetCurrentWorldScale() const
975 // mNode is being used in a separate thread; copy the value from the previous update
976 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
982 void Actor::SetInheritScale( bool inherit )
984 // non animateable so keep local copy
985 mInheritScale = inherit;
988 // mNode is being used in a separate thread; queue a message to set the value
989 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
993 bool Actor::IsScaleInherited() const
995 return mInheritScale;
998 Matrix Actor::GetCurrentWorldMatrix() const
1002 // World matrix is no longer updated unless there is something observing the node.
1003 // Need to calculate it from node's world position, orientation and scale:
1004 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1005 Matrix worldMatrix(false);
1006 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1007 mNode->GetWorldOrientation( updateBufferIndex ),
1008 mNode->GetWorldPosition( updateBufferIndex ) );
1012 return Matrix::IDENTITY;
1015 void Actor::SetVisible( bool visible )
1019 // mNode is being used in a separate thread; queue a message to set the value & base value
1020 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1024 bool Actor::IsVisible() const
1028 // mNode is being used in a separate thread; copy the value from the previous update
1029 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1035 void Actor::SetOpacity( float opacity )
1039 // mNode is being used in a separate thread; queue a message to set the value & base value
1040 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1044 float Actor::GetCurrentOpacity() const
1048 // mNode is being used in a separate thread; copy the value from the previous update
1049 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1055 const Vector4& Actor::GetCurrentWorldColor() const
1059 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1062 return Color::WHITE;
1065 void Actor::SetColor( const Vector4& color )
1069 // mNode is being used in a separate thread; queue a message to set the value & base value
1070 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1074 void Actor::SetColorRed( float red )
1078 // mNode is being used in a separate thread; queue a message to set the value & base value
1079 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1083 void Actor::SetColorGreen( float green )
1087 // mNode is being used in a separate thread; queue a message to set the value & base value
1088 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1092 void Actor::SetColorBlue( float blue )
1096 // mNode is being used in a separate thread; queue a message to set the value & base value
1097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1101 const Vector4& Actor::GetCurrentColor() const
1105 // mNode is being used in a separate thread; copy the value from the previous update
1106 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1109 return Color::WHITE;
1112 void Actor::SetInheritOrientation( bool inherit )
1114 // non animateable so keep local copy
1115 mInheritOrientation = inherit;
1118 // mNode is being used in a separate thread; queue a message to set the value
1119 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1123 bool Actor::IsOrientationInherited() const
1125 return mInheritOrientation;
1128 void Actor::SetSizeModeFactor( const Vector3& factor )
1130 EnsureRelayoutData();
1132 mRelayoutData->sizeModeFactor = factor;
1135 const Vector3& Actor::GetSizeModeFactor() const
1137 EnsureRelayoutData();
1139 return mRelayoutData->sizeModeFactor;
1142 void Actor::SetColorMode( ColorMode colorMode )
1144 // non animateable so keep local copy
1145 mColorMode = colorMode;
1148 // mNode is being used in a separate thread; queue a message to set the value
1149 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1153 ColorMode Actor::GetColorMode() const
1155 // we have cached copy
1159 void Actor::SetSize( float width, float height )
1161 SetSize( Vector2( width, height ) );
1164 void Actor::SetSize( float width, float height, float depth )
1166 SetSize( Vector3( width, height, depth ) );
1169 void Actor::SetSize( const Vector2& size )
1171 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1174 void Actor::SetSizeInternal( const Vector2& size )
1176 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1179 float Actor::CalculateSizeZ( const Vector2& size ) const
1181 return std::min( size.width, size.height );
1184 void Actor::SetSize( const Vector3& size )
1186 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1188 SetPreferredSize( size.GetVectorXY() );
1192 SetSizeInternal( size );
1196 void Actor::SetSizeInternal( const Vector3& size )
1202 // mNode is being used in a separate thread; queue a message to set the value & base value
1203 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1205 // Notification for derived classes
1206 OnSizeSet( mTargetSize );
1208 // Raise a relayout request if the flag is not locked
1209 if( mRelayoutData && !mRelayoutData->insideRelayout )
1216 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1218 mTargetSize = targetSize;
1220 // Notify deriving classes
1221 OnSizeAnimation( animation, targetSize );
1224 void Actor::SetWidth( float width )
1228 // mNode is being used in a separate thread; queue a message to set the value & base value
1229 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1233 void Actor::SetHeight( float height )
1237 // mNode is being used in a separate thread; queue a message to set the value & base value
1238 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1242 void Actor::SetDepth( float depth )
1246 // mNode is being used in a separate thread; queue a message to set the value & base value
1247 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1251 const Vector3& Actor::GetTargetSize() const
1256 const Vector3& Actor::GetCurrentSize() const
1260 // mNode is being used in a separate thread; copy the value from the previous update
1261 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1264 return Vector3::ZERO;
1267 Vector3 Actor::GetNaturalSize() const
1269 // It is up to deriving classes to return the appropriate natural size
1270 return Vector3( 0.0f, 0.0f, 0.0f );
1273 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1275 EnsureRelayoutData();
1277 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1279 if( dimension & ( 1 << i ) )
1281 mRelayoutData->resizePolicies[ i ] = policy;
1285 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1287 if( dimension & Dimension::WIDTH )
1289 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1292 if( dimension & Dimension::HEIGHT )
1294 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1298 // If calling SetResizePolicy, assume we want relayout enabled
1299 SetRelayoutEnabled( true );
1301 OnSetResizePolicy( policy, dimension );
1303 // Trigger relayout on this control
1307 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1309 EnsureRelayoutData();
1311 // If more than one dimension is requested, just return the first one found
1312 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1314 if( ( dimension & ( 1 << i ) ) )
1316 return mRelayoutData->resizePolicies[ i ];
1320 return ResizePolicy::FIXED; // Default
1323 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1325 EnsureRelayoutData();
1327 mRelayoutData->sizeSetPolicy = policy;
1330 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1332 EnsureRelayoutData();
1334 return mRelayoutData->sizeSetPolicy;
1337 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1339 EnsureRelayoutData();
1341 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1343 if( dimension & ( 1 << i ) )
1345 mRelayoutData->dimensionDependencies[ i ] = dependency;
1350 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1352 EnsureRelayoutData();
1354 // If more than one dimension is requested, just return the first one found
1355 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1357 if( ( dimension & ( 1 << i ) ) )
1359 return mRelayoutData->dimensionDependencies[ i ];
1363 return Dimension::ALL_DIMENSIONS; // Default
1366 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1368 // If relayout data has not been allocated yet and the client is requesting
1369 // to disable it, do nothing
1370 if( mRelayoutData || relayoutEnabled )
1372 EnsureRelayoutData();
1374 mRelayoutData->relayoutEnabled = relayoutEnabled;
1378 bool Actor::IsRelayoutEnabled() const
1380 // Assume that if relayout data has not been allocated yet then
1381 // relayout is disabled
1382 return mRelayoutData && mRelayoutData->relayoutEnabled;
1385 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1387 EnsureRelayoutData();
1389 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1391 if( dimension & ( 1 << i ) )
1393 mRelayoutData->dimensionDirty[ i ] = dirty;
1398 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1400 EnsureRelayoutData();
1402 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1404 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1413 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1415 EnsureRelayoutData();
1417 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1420 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1422 EnsureRelayoutData();
1424 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1427 #ifdef DYNAMICS_SUPPORT
1429 //--------------- Dynamics ---------------
1431 void Actor::DisableDynamics()
1433 if( NULL != mDynamicsData )
1435 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1437 // ensure dynamics object are disconnected from scene
1438 DisconnectDynamics();
1440 // delete joint owned by this actor
1441 while( !mDynamicsData->joints.empty() )
1443 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1446 // delete other joints referencing this actor
1447 while( !mDynamicsData->referencedJoints.empty() )
1449 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1450 ActorPtr jointOwner( joint->GetActor( true ) );
1453 jointOwner->RemoveDynamicsJoint( joint );
1457 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1460 // delete the DynamicsBody object
1461 mDynamicsData->body.Reset();
1463 // Discard Dynamics data structure
1464 delete mDynamicsData;
1465 mDynamicsData = NULL;
1469 DynamicsBodyPtr Actor::GetDynamicsBody() const
1471 DynamicsBodyPtr body;
1473 if( NULL != mDynamicsData )
1475 body = mDynamicsData->body;
1481 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1483 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1485 if( NULL == mDynamicsData )
1487 mDynamicsData = new DynamicsData( this );
1490 if( !mDynamicsData->body )
1492 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1496 DynamicsWorldPtr world( DynamicsWorld::Get() );
1499 if( mParent == world->GetRootActor().Get() )
1501 mDynamicsData->body->Connect( GetEventThreadServices() );
1507 return mDynamicsData->body;
1510 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1512 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1513 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1516 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1518 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1519 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1521 DynamicsJointPtr joint;
1523 DynamicsWorldPtr world( DynamicsWorld::Get() );
1527 if( NULL != mDynamicsData )
1529 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1531 if( mDynamicsData->joints.end() != it )
1533 // use existing joint
1539 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1540 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1544 bodyA = EnableDynamics( new DynamicsBodyConfig );
1549 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1552 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1553 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1555 if( OnStage() && attachedActor->OnStage() )
1557 joint->Connect( GetEventThreadServices() );
1560 attachedActor->ReferenceJoint( joint );
1562 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1563 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1570 const int Actor::GetNumberOfJoints() const
1572 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1575 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1577 DynamicsJointPtr joint;
1579 if( NULL != mDynamicsData )
1581 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1583 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1585 for( int i = 0; i < index; ++i )
1597 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1599 DynamicsJointPtr joint;
1601 if( NULL != mDynamicsData )
1603 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1605 if( mDynamicsData->joints.end() != it )
1607 // use existing joint
1615 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1617 if( NULL != mDynamicsData )
1619 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1620 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1622 for(; it != endIt; ++it )
1624 if( it->second == joint.Get() )
1626 ActorPtr attachedActor( it->first );
1628 if( OnStage() && attachedActor && attachedActor->OnStage() )
1630 joint->Disconnect( GetEventThreadServices() );
1635 attachedActor->ReleaseJoint( joint );
1636 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1637 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1640 mDynamicsData->joints.erase(it);
1647 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1649 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1651 if( NULL != mDynamicsData )
1653 mDynamicsData->referencedJoints.push_back(joint);
1657 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1659 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1661 if( NULL != mDynamicsData )
1663 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1665 if( it != mDynamicsData->referencedJoints.end() )
1667 mDynamicsData->referencedJoints.erase( it );
1672 void Actor::SetDynamicsRoot(bool flag)
1674 if( mIsDynamicsRoot != flag )
1676 mIsDynamicsRoot = flag;
1678 if( OnStage() && mChildren )
1680 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1681 ActorIter end = mChildren->end();
1682 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1684 Actor& child = GetImplementation(*iter);
1686 if( child.GetDynamicsBody() )
1688 if( mIsDynamicsRoot )
1690 child.ConnectDynamics();
1694 child.DisconnectDynamics();
1702 bool Actor::IsDynamicsRoot() const
1704 return mIsDynamicsRoot;
1707 void Actor::AttachedActorOnStage( Dali::Actor actor )
1709 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1713 ActorPtr attachedActor( &GetImplementation(actor) );
1715 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1716 if( NULL != mDynamicsData )
1718 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1719 if( mDynamicsData->joints.end() != it )
1721 DynamicsJointPtr joint( it->second );
1722 joint->Connect( GetEventThreadServices() );
1728 void Actor::AttachedActorOffStage( Dali::Actor actor )
1730 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1734 ActorPtr attachedActor( &GetImplementation(actor) );
1736 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1737 if( NULL != mDynamicsData )
1739 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1740 if( mDynamicsData->joints.end() != it )
1742 DynamicsJointPtr joint( it->second );
1743 joint->Disconnect( GetEventThreadServices() );
1749 void Actor::ConnectDynamics()
1751 if( NULL != mDynamicsData && mDynamicsData->body )
1753 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1755 mDynamicsData->body->Connect( GetEventThreadServices() );
1757 // Connect all joints where attachedActor is also on stage
1758 if( !mDynamicsData->joints.empty() )
1760 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1761 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1763 for(; it != endIt; ++it )
1765 Actor* attachedActor( it->first );
1766 if( NULL != attachedActor && attachedActor->OnStage() )
1768 DynamicsJointPtr joint( it->second );
1770 joint->Connect( GetEventThreadServices() );
1778 void Actor::DisconnectDynamics()
1780 if( NULL != mDynamicsData && mDynamicsData->body )
1784 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1786 // Disconnect all joints
1787 if( !mDynamicsData->joints.empty() )
1789 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1790 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1792 for(; it != endIt; ++it )
1794 DynamicsJointPtr joint( it->second );
1796 joint->Disconnect( GetEventThreadServices() );
1803 #endif // DYNAMICS_SUPPORT
1805 void Actor::SetOverlay( bool enable )
1807 // Setting STENCIL will override OVERLAY
1808 if( DrawMode::STENCIL != mDrawMode )
1810 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1814 bool Actor::IsOverlay() const
1816 return ( DrawMode::OVERLAY == mDrawMode );
1819 void Actor::SetDrawMode( DrawMode::Type drawMode )
1821 // this flag is not animatable so keep the value
1822 mDrawMode = drawMode;
1825 // mNode is being used in a separate thread; queue a message to set the value
1826 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1830 DrawMode::Type Actor::GetDrawMode() const
1835 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1837 // only valid when on-stage
1840 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1842 Vector2 converted( screenX, screenY );
1844 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1845 const int taskCount = taskList.GetTaskCount();
1846 for( int i = taskCount - 1; i >= 0; --i )
1848 Dali::RenderTask task = taskList.GetTask( i );
1849 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1851 // found a task where this conversion was ok so return
1859 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1861 bool retval = false;
1862 // only valid when on-stage
1865 CameraActor* camera = renderTask.GetCameraActor();
1869 renderTask.GetViewport( viewport );
1871 // need to translate coordinates to render tasks coordinate space
1872 Vector2 converted( screenX, screenY );
1873 if( renderTask.TranslateCoordinates( converted ) )
1875 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1882 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1884 // Early-out if mNode is NULL
1890 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1892 // Calculate the ModelView matrix
1893 Matrix modelView( false/*don't init*/);
1894 // need to use the components as world matrix is only updated for actors that need it
1895 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1896 Matrix::Multiply( modelView, modelView, viewMatrix );
1898 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1899 Matrix invertedMvp( false/*don't init*/);
1900 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1901 bool success = invertedMvp.Invert();
1903 // Convert to GL coordinates
1904 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1909 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1916 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1922 if( XyPlaneIntersect( nearPos, farPos, local ) )
1924 Vector3 size = GetCurrentSize();
1925 localX = local.x + size.x * 0.5f;
1926 localY = local.y + size.y * 0.5f;
1937 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1940 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1942 Mathematical Formulation
1944 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1946 ( p - c ) dot ( p - c ) = r^2
1948 Given a ray with a point of origin 'o', and a direction vector 'd':
1950 ray(t) = o + td, t >= 0
1952 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1954 (o + td - c ) dot ( o + td - c ) = r^2
1956 To solve for t we first expand the above into a more recognisable quadratic equation form
1958 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1967 B = 2( o - c ) dot d
1968 C = ( o - c ) dot ( o - c ) - r^2
1970 which can be solved using a standard quadratic formula.
1972 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1974 Practical Simplification
1976 In a renderer, we often differentiate between world space and object space. In the object space
1977 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1978 into object space, the mathematical solution presented above can be simplified significantly.
1980 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1984 and we can find the t at which the (transformed) ray intersects the sphere by
1986 ( o + td ) dot ( o + td ) = r^2
1988 According to the reasoning above, we expand the above quadratic equation into the general form
1992 which now has coefficients:
1999 // Early out if mNode is NULL
2005 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2007 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2008 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2009 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2011 // Compute the radius is not needed, square radius it's enough.
2012 const Vector3& size( mNode->GetSize( bufferIndex ) );
2014 // Scale the sphere.
2015 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2017 const float width = size.width * scale.width;
2018 const float height = size.height * scale.height;
2020 float squareSphereRadius = 0.5f * ( width * width + height * height );
2022 float a = rayDir.Dot( rayDir ); // a
2023 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2024 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2026 return ( b2 * b2 - a * c ) >= 0.f;
2029 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2036 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2038 // Transforms the ray to the local reference system.
2040 // Calculate the inverse of Model matrix
2041 Matrix invModelMatrix( false/*don't init*/);
2042 // need to use the components as world matrix is only updated for actors that need it
2043 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2045 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2046 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2048 // Test with the actor's XY plane (Normal = 0 0 1 1).
2050 float a = -rayOriginLocal.z;
2051 float b = rayDirLocal.z;
2053 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2055 // Ray travels distance * rayDirLocal to intersect with plane.
2058 const Vector3& size = mNode->GetSize( bufferIndex );
2060 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2061 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2063 // Test with the actor's geometry.
2064 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2071 void Actor::SetLeaveRequired( bool required )
2073 mLeaveRequired = required;
2076 bool Actor::GetLeaveRequired() const
2078 return mLeaveRequired;
2081 void Actor::SetKeyboardFocusable( bool focusable )
2083 mKeyboardFocusable = focusable;
2086 bool Actor::IsKeyboardFocusable() const
2088 return mKeyboardFocusable;
2091 bool Actor::GetTouchRequired() const
2093 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2096 bool Actor::GetHoverRequired() const
2098 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2101 bool Actor::GetMouseWheelEventRequired() const
2103 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2106 bool Actor::IsHittable() const
2108 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2111 ActorGestureData& Actor::GetGestureData()
2113 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2114 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2115 if( NULL == mGestureData )
2117 mGestureData = new ActorGestureData;
2119 return *mGestureData;
2122 bool Actor::IsGestureRequred( Gesture::Type type ) const
2124 return mGestureData && mGestureData->IsGestureRequred( type );
2127 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2129 bool consumed = false;
2131 if( !mTouchedSignal.Empty() )
2133 Dali::Actor handle( this );
2134 consumed = mTouchedSignal.Emit( handle, event );
2139 // Notification for derived classes
2140 consumed = OnTouchEvent( event );
2146 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2148 bool consumed = false;
2150 if( !mHoveredSignal.Empty() )
2152 Dali::Actor handle( this );
2153 consumed = mHoveredSignal.Emit( handle, event );
2158 // Notification for derived classes
2159 consumed = OnHoverEvent( event );
2165 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2167 bool consumed = false;
2169 if( !mMouseWheelEventSignal.Empty() )
2171 Dali::Actor handle( this );
2172 consumed = mMouseWheelEventSignal.Emit( handle, event );
2177 // Notification for derived classes
2178 consumed = OnMouseWheelEvent( event );
2184 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2186 return mTouchedSignal;
2189 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2191 return mHoveredSignal;
2194 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2196 return mMouseWheelEventSignal;
2199 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2201 return mOnStageSignal;
2204 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2206 return mOffStageSignal;
2209 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2211 return mOnRelayoutSignal;
2214 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2216 bool connected( true );
2217 Actor* actor = dynamic_cast< Actor* >( object );
2219 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2221 actor->TouchedSignal().Connect( tracker, functor );
2223 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2225 actor->HoveredSignal().Connect( tracker, functor );
2227 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2229 actor->MouseWheelEventSignal().Connect( tracker, functor );
2231 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2233 actor->OnStageSignal().Connect( tracker, functor );
2235 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2237 actor->OffStageSignal().Connect( tracker, functor );
2241 // signalName does not match any signal
2248 Actor::Actor( DerivedType derivedType )
2252 mParentOrigin( NULL ),
2253 mAnchorPoint( NULL ),
2254 mRelayoutData( NULL ),
2255 #ifdef DYNAMICS_SUPPORT
2256 mDynamicsData( NULL ),
2258 mGestureData( NULL ), mAttachment(), mTargetSize( 0.0f, 0.0f, 0.0f ), mName(), mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2259 mIsRoot( ROOT_LAYER == derivedType ), mIsRenderable( RENDERABLE == derivedType ), mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ), mIsOnStage( false ), mIsDynamicsRoot( false ), mSensitive( true ), mLeaveRequired( false ), mKeyboardFocusable( false ), mDerivedRequiresTouch( false ), mDerivedRequiresHover( false ), mDerivedRequiresMouseWheelEvent( false ), mOnStageSignalled( false ), mInheritOrientation( true ), mInheritScale( true ), mDrawMode( DrawMode::NORMAL ), mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), mColorMode( Node::DEFAULT_COLOR_MODE )
2263 void Actor::Initialize()
2266 SceneGraph::Node* node = CreateNode();
2268 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2269 mNode = node; // Keep raw-pointer to Node
2273 GetEventThreadServices().RegisterObject( this );
2278 // Remove mParent pointers from children even if we're destroying core,
2279 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2282 ActorConstIter endIter = mChildren->end();
2283 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2285 Actor& actor = GetImplementation( *iter );
2286 actor.SetParent( NULL );
2291 // Guard to allow handle destruction after Core has been destroyed
2292 if( EventThreadServices::IsCoreRunning() )
2296 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2297 mNode = NULL; // Node is about to be destroyed
2300 GetEventThreadServices().UnregisterObject( this );
2303 #ifdef DYNAMICS_SUPPORT
2305 delete mDynamicsData;
2308 // Cleanup optional gesture data
2309 delete mGestureData;
2311 // Cleanup optional parent origin and anchor
2312 delete mParentOrigin;
2313 delete mAnchorPoint;
2315 // Delete optional relayout data
2318 delete mRelayoutData;
2322 void Actor::ConnectToStage( int index )
2324 // This container is used instead of walking the Actor hierachy.
2325 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2326 ActorContainer connectionList;
2328 // This stage is atomic i.e. not interrupted by user callbacks
2329 RecursiveConnectToStage( connectionList, index );
2331 // Notify applications about the newly connected actors.
2332 const ActorIter endIter = connectionList.end();
2333 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2335 Actor& actor = GetImplementation( *iter );
2336 actor.NotifyStageConnection();
2342 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2344 DALI_ASSERT_ALWAYS( !OnStage() );
2348 ConnectToSceneGraph( index );
2350 // Notification for internal derived classes
2351 OnStageConnectionInternal();
2353 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2354 connectionList.push_back( Dali::Actor( this ) );
2356 // Recursively connect children
2359 ActorConstIter endIter = mChildren->end();
2360 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2362 Actor& actor = GetImplementation( *iter );
2363 actor.RecursiveConnectToStage( connectionList );
2369 * This method is called when the Actor is connected to the Stage.
2370 * The parent must have added its Node to the scene-graph.
2371 * The child must connect its Node to the parent's Node.
2372 * This is resursive; the child calls ConnectToStage() for its children.
2374 void Actor::ConnectToSceneGraph( int index )
2376 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2380 // Reparent Node in next Update
2381 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2384 // Notify attachment
2387 mAttachment->Connect();
2390 #ifdef DYNAMICS_SUPPORT
2392 if( NULL != mDynamicsData )
2398 // Request relayout on all actors that are added to the scenegraph
2401 // Notification for Object::Observers
2405 void Actor::NotifyStageConnection()
2407 // Actors can be removed (in a callback), before the on-stage stage is reported.
2408 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2409 if( OnStage() && !mOnStageSignalled )
2411 // Notification for external (CustomActor) derived classes
2412 OnStageConnectionExternal();
2414 if( !mOnStageSignal.Empty() )
2416 Dali::Actor handle( this );
2417 mOnStageSignal.Emit( handle );
2420 // Guard against Remove during callbacks
2423 mOnStageSignalled = true; // signal required next time Actor is removed
2428 void Actor::DisconnectFromStage()
2430 // This container is used instead of walking the Actor hierachy.
2431 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2432 ActorContainer disconnectionList;
2434 // This stage is atomic i.e. not interrupted by user callbacks
2435 RecursiveDisconnectFromStage( disconnectionList );
2437 // Notify applications about the newly disconnected actors.
2438 const ActorIter endIter = disconnectionList.end();
2439 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2441 Actor& actor = GetImplementation( *iter );
2442 actor.NotifyStageDisconnection();
2446 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2448 DALI_ASSERT_ALWAYS( OnStage() );
2450 // Recursively disconnect children
2453 ActorConstIter endIter = mChildren->end();
2454 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2456 Actor& actor = GetImplementation( *iter );
2457 actor.RecursiveDisconnectFromStage( disconnectionList );
2461 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2462 disconnectionList.push_back( Dali::Actor( this ) );
2464 // Notification for internal derived classes
2465 OnStageDisconnectionInternal();
2467 DisconnectFromSceneGraph();
2473 * This method is called by an actor or its parent, before a node removal message is sent.
2474 * This is recursive; the child calls DisconnectFromStage() for its children.
2476 void Actor::DisconnectFromSceneGraph()
2478 // Notification for Object::Observers
2479 OnSceneObjectRemove();
2481 // Notify attachment
2484 mAttachment->Disconnect();
2487 #ifdef DYNAMICS_SUPPORT
2489 if( NULL != mDynamicsData )
2491 DisconnectDynamics();
2496 void Actor::NotifyStageDisconnection()
2498 // Actors can be added (in a callback), before the off-stage state is reported.
2499 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2500 // only do this step if there is a stage, i.e. Core is not being shut down
2501 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2503 // Notification for external (CustomeActor) derived classes
2504 OnStageDisconnectionExternal();
2506 if( !mOffStageSignal.Empty() )
2508 Dali::Actor handle( this );
2509 mOffStageSignal.Emit( handle );
2512 // Guard against Add during callbacks
2515 mOnStageSignalled = false; // signal required next time Actor is added
2520 bool Actor::IsNodeConnected() const
2522 bool connected( false );
2527 if( mNode->IsRoot() || mNode->GetParent() )
2536 unsigned int Actor::GetDefaultPropertyCount() const
2538 return DEFAULT_PROPERTY_COUNT;
2541 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2543 indices.reserve( DEFAULT_PROPERTY_COUNT );
2545 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2547 indices.push_back( i );
2551 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2553 if( index < DEFAULT_PROPERTY_COUNT )
2555 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2561 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2563 Property::Index index = Property::INVALID_INDEX;
2565 // Look for name in default properties
2566 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2568 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2569 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2579 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2581 if( index < DEFAULT_PROPERTY_COUNT )
2583 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2589 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2591 if( index < DEFAULT_PROPERTY_COUNT )
2593 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2599 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2601 if( index < DEFAULT_PROPERTY_COUNT )
2603 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2609 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2611 if( index < DEFAULT_PROPERTY_COUNT )
2613 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2616 // index out of range...return Property::NONE
2617 return Property::NONE;
2620 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2624 case Dali::Actor::Property::PARENT_ORIGIN:
2626 SetParentOrigin( property.Get< Vector3 >() );
2630 case Dali::Actor::Property::PARENT_ORIGIN_X:
2632 SetParentOriginX( property.Get< float >() );
2636 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2638 SetParentOriginY( property.Get< float >() );
2642 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2644 SetParentOriginZ( property.Get< float >() );
2648 case Dali::Actor::Property::ANCHOR_POINT:
2650 SetAnchorPoint( property.Get< Vector3 >() );
2654 case Dali::Actor::Property::ANCHOR_POINT_X:
2656 SetAnchorPointX( property.Get< float >() );
2660 case Dali::Actor::Property::ANCHOR_POINT_Y:
2662 SetAnchorPointY( property.Get< float >() );
2666 case Dali::Actor::Property::ANCHOR_POINT_Z:
2668 SetAnchorPointZ( property.Get< float >() );
2672 case Dali::Actor::Property::SIZE:
2674 SetSize( property.Get< Vector3 >() );
2678 case Dali::Actor::Property::SIZE_WIDTH:
2680 SetWidth( property.Get< float >() );
2684 case Dali::Actor::Property::SIZE_HEIGHT:
2686 SetHeight( property.Get< float >() );
2690 case Dali::Actor::Property::SIZE_DEPTH:
2692 SetDepth( property.Get< float >() );
2696 case Dali::Actor::Property::POSITION:
2698 SetPosition( property.Get< Vector3 >() );
2702 case Dali::Actor::Property::POSITION_X:
2704 SetX( property.Get< float >() );
2708 case Dali::Actor::Property::POSITION_Y:
2710 SetY( property.Get< float >() );
2714 case Dali::Actor::Property::POSITION_Z:
2716 SetZ( property.Get< float >() );
2720 case Dali::Actor::Property::ORIENTATION:
2722 SetOrientation( property.Get< Quaternion >() );
2726 case Dali::Actor::Property::SCALE:
2728 SetScale( property.Get< Vector3 >() );
2732 case Dali::Actor::Property::SCALE_X:
2734 SetScaleX( property.Get< float >() );
2738 case Dali::Actor::Property::SCALE_Y:
2740 SetScaleY( property.Get< float >() );
2744 case Dali::Actor::Property::SCALE_Z:
2746 SetScaleZ( property.Get< float >() );
2750 case Dali::Actor::Property::VISIBLE:
2752 SetVisible( property.Get< bool >() );
2756 case Dali::Actor::Property::COLOR:
2758 SetColor( property.Get< Vector4 >() );
2762 case Dali::Actor::Property::COLOR_RED:
2764 SetColorRed( property.Get< float >() );
2768 case Dali::Actor::Property::COLOR_GREEN:
2770 SetColorGreen( property.Get< float >() );
2774 case Dali::Actor::Property::COLOR_BLUE:
2776 SetColorBlue( property.Get< float >() );
2780 case Dali::Actor::Property::COLOR_ALPHA:
2782 SetOpacity( property.Get< float >() );
2786 case Dali::Actor::Property::NAME:
2788 SetName( property.Get< std::string >() );
2792 case Dali::Actor::Property::SENSITIVE:
2794 SetSensitive( property.Get< bool >() );
2798 case Dali::Actor::Property::LEAVE_REQUIRED:
2800 SetLeaveRequired( property.Get< bool >() );
2804 case Dali::Actor::Property::INHERIT_ORIENTATION:
2806 SetInheritOrientation( property.Get< bool >() );
2810 case Dali::Actor::Property::INHERIT_SCALE:
2812 SetInheritScale( property.Get< bool >() );
2816 case Dali::Actor::Property::COLOR_MODE:
2818 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2822 case Dali::Actor::Property::POSITION_INHERITANCE:
2824 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2828 case Dali::Actor::Property::DRAW_MODE:
2830 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2834 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2836 SetSizeModeFactor( property.Get< Vector3 >() );
2840 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2842 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2846 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2848 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2852 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2854 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2858 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2860 if( property.Get< bool >() )
2862 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2867 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2869 if( property.Get< bool >() )
2871 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2876 case Dali::Actor::Property::PADDING:
2878 Vector4 padding = property.Get< Vector4 >();
2879 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2880 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2884 case Dali::Actor::Property::MINIMUM_SIZE:
2886 Vector2 size = property.Get< Vector2 >();
2887 SetMinimumSize( size.x, Dimension::WIDTH );
2888 SetMinimumSize( size.y, Dimension::HEIGHT );
2892 case Dali::Actor::Property::MAXIMUM_SIZE:
2894 Vector2 size = property.Get< Vector2 >();
2895 SetMaximumSize( size.x, Dimension::WIDTH );
2896 SetMaximumSize( size.y, Dimension::HEIGHT );
2902 // this can happen in the case of a non-animatable default property so just do nothing
2908 // TODO: This method needs to be removed
2909 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2911 switch( entry.type )
2913 case Property::BOOLEAN:
2915 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2916 DALI_ASSERT_DEBUG( NULL != property );
2918 // property is being used in a separate thread; queue a message to set the property
2919 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2924 case Property::INTEGER:
2926 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2927 DALI_ASSERT_DEBUG( NULL != property );
2929 // property is being used in a separate thread; queue a message to set the property
2930 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2935 case Property::UNSIGNED_INTEGER:
2937 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2938 DALI_ASSERT_DEBUG( NULL != property );
2940 // property is being used in a separate thread; queue a message to set the property
2941 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2946 case Property::FLOAT:
2948 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2949 DALI_ASSERT_DEBUG( NULL != property );
2951 // property is being used in a separate thread; queue a message to set the property
2952 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2957 case Property::VECTOR2:
2959 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2960 DALI_ASSERT_DEBUG( NULL != property );
2962 // property is being used in a separate thread; queue a message to set the property
2963 if(entry.componentIndex == 0)
2965 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2967 else if(entry.componentIndex == 1)
2969 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2973 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2979 case Property::VECTOR3:
2981 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2982 DALI_ASSERT_DEBUG( NULL != property );
2984 // property is being used in a separate thread; queue a message to set the property
2985 if(entry.componentIndex == 0)
2987 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2989 else if(entry.componentIndex == 1)
2991 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2993 else if(entry.componentIndex == 2)
2995 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2999 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3005 case Property::VECTOR4:
3007 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3008 DALI_ASSERT_DEBUG( NULL != property );
3010 // property is being used in a separate thread; queue a message to set the property
3011 if(entry.componentIndex == 0)
3013 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3015 else if(entry.componentIndex == 1)
3017 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3019 else if(entry.componentIndex == 2)
3021 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3023 else if(entry.componentIndex == 3)
3025 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3029 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3035 case Property::ROTATION:
3037 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3038 DALI_ASSERT_DEBUG( NULL != property );
3040 // property is being used in a separate thread; queue a message to set the property
3041 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3046 case Property::MATRIX:
3048 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3049 DALI_ASSERT_DEBUG( NULL != property );
3051 // property is being used in a separate thread; queue a message to set the property
3052 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3057 case Property::MATRIX3:
3059 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3060 DALI_ASSERT_DEBUG( NULL != property );
3062 // property is being used in a separate thread; queue a message to set the property
3063 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3070 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3076 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3078 Property::Value value;
3082 case Dali::Actor::Property::PARENT_ORIGIN:
3084 value = GetCurrentParentOrigin();
3088 case Dali::Actor::Property::PARENT_ORIGIN_X:
3090 value = GetCurrentParentOrigin().x;
3094 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3096 value = GetCurrentParentOrigin().y;
3100 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3102 value = GetCurrentParentOrigin().z;
3106 case Dali::Actor::Property::ANCHOR_POINT:
3108 value = GetCurrentAnchorPoint();
3112 case Dali::Actor::Property::ANCHOR_POINT_X:
3114 value = GetCurrentAnchorPoint().x;
3118 case Dali::Actor::Property::ANCHOR_POINT_Y:
3120 value = GetCurrentAnchorPoint().y;
3124 case Dali::Actor::Property::ANCHOR_POINT_Z:
3126 value = GetCurrentAnchorPoint().z;
3130 case Dali::Actor::Property::SIZE:
3132 value = GetCurrentSize();
3136 case Dali::Actor::Property::SIZE_WIDTH:
3138 value = GetCurrentSize().width;
3142 case Dali::Actor::Property::SIZE_HEIGHT:
3144 value = GetCurrentSize().height;
3148 case Dali::Actor::Property::SIZE_DEPTH:
3150 value = GetCurrentSize().depth;
3154 case Dali::Actor::Property::POSITION:
3156 value = GetCurrentPosition();
3160 case Dali::Actor::Property::POSITION_X:
3162 value = GetCurrentPosition().x;
3166 case Dali::Actor::Property::POSITION_Y:
3168 value = GetCurrentPosition().y;
3172 case Dali::Actor::Property::POSITION_Z:
3174 value = GetCurrentPosition().z;
3178 case Dali::Actor::Property::WORLD_POSITION:
3180 value = GetCurrentWorldPosition();
3184 case Dali::Actor::Property::WORLD_POSITION_X:
3186 value = GetCurrentWorldPosition().x;
3190 case Dali::Actor::Property::WORLD_POSITION_Y:
3192 value = GetCurrentWorldPosition().y;
3196 case Dali::Actor::Property::WORLD_POSITION_Z:
3198 value = GetCurrentWorldPosition().z;
3202 case Dali::Actor::Property::ORIENTATION:
3204 value = GetCurrentOrientation();
3208 case Dali::Actor::Property::WORLD_ORIENTATION:
3210 value = GetCurrentWorldOrientation();
3214 case Dali::Actor::Property::SCALE:
3216 value = GetCurrentScale();
3220 case Dali::Actor::Property::SCALE_X:
3222 value = GetCurrentScale().x;
3226 case Dali::Actor::Property::SCALE_Y:
3228 value = GetCurrentScale().y;
3232 case Dali::Actor::Property::SCALE_Z:
3234 value = GetCurrentScale().z;
3238 case Dali::Actor::Property::WORLD_SCALE:
3240 value = GetCurrentWorldScale();
3244 case Dali::Actor::Property::VISIBLE:
3246 value = IsVisible();
3250 case Dali::Actor::Property::COLOR:
3252 value = GetCurrentColor();
3256 case Dali::Actor::Property::COLOR_RED:
3258 value = GetCurrentColor().r;
3262 case Dali::Actor::Property::COLOR_GREEN:
3264 value = GetCurrentColor().g;
3268 case Dali::Actor::Property::COLOR_BLUE:
3270 value = GetCurrentColor().b;
3274 case Dali::Actor::Property::COLOR_ALPHA:
3276 value = GetCurrentColor().a;
3280 case Dali::Actor::Property::WORLD_COLOR:
3282 value = GetCurrentWorldColor();
3286 case Dali::Actor::Property::WORLD_MATRIX:
3288 value = GetCurrentWorldMatrix();
3292 case Dali::Actor::Property::NAME:
3298 case Dali::Actor::Property::SENSITIVE:
3300 value = IsSensitive();
3304 case Dali::Actor::Property::LEAVE_REQUIRED:
3306 value = GetLeaveRequired();
3310 case Dali::Actor::Property::INHERIT_ORIENTATION:
3312 value = IsOrientationInherited();
3316 case Dali::Actor::Property::INHERIT_SCALE:
3318 value = IsScaleInherited();
3322 case Dali::Actor::Property::COLOR_MODE:
3324 value = Scripting::GetColorMode( GetColorMode() );
3328 case Dali::Actor::Property::POSITION_INHERITANCE:
3330 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3334 case Dali::Actor::Property::DRAW_MODE:
3336 value = Scripting::GetDrawMode( GetDrawMode() );
3340 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3342 value = GetSizeModeFactor();
3346 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3348 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3352 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3354 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3358 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3360 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3364 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3366 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3370 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3372 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3376 case Dali::Actor::Property::PADDING:
3378 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3379 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3380 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3384 case Dali::Actor::Property::MINIMUM_SIZE:
3386 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3390 case Dali::Actor::Property::MAXIMUM_SIZE:
3392 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3398 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3406 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3411 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3413 // This method should only return an object connected to the scene-graph
3414 return OnStage() ? mNode : NULL;
3417 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3419 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3421 const PropertyBase* property( NULL );
3423 // This method should only return a property of an object connected to the scene-graph
3429 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3431 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3432 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3434 property = animatable->GetSceneGraphProperty();
3436 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3438 CustomPropertyMetadata* custom = FindCustomProperty( index );
3439 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3441 property = custom->GetSceneGraphProperty();
3443 else if( NULL != mNode )
3447 case Dali::Actor::Property::SIZE:
3448 property = &mNode->mSize;
3451 case Dali::Actor::Property::SIZE_WIDTH:
3452 property = &mNode->mSize;
3455 case Dali::Actor::Property::SIZE_HEIGHT:
3456 property = &mNode->mSize;
3459 case Dali::Actor::Property::SIZE_DEPTH:
3460 property = &mNode->mSize;
3463 case Dali::Actor::Property::POSITION:
3464 property = &mNode->mPosition;
3467 case Dali::Actor::Property::POSITION_X:
3468 property = &mNode->mPosition;
3471 case Dali::Actor::Property::POSITION_Y:
3472 property = &mNode->mPosition;
3475 case Dali::Actor::Property::POSITION_Z:
3476 property = &mNode->mPosition;
3479 case Dali::Actor::Property::ORIENTATION:
3480 property = &mNode->mOrientation;
3483 case Dali::Actor::Property::SCALE:
3484 property = &mNode->mScale;
3487 case Dali::Actor::Property::SCALE_X:
3488 property = &mNode->mScale;
3491 case Dali::Actor::Property::SCALE_Y:
3492 property = &mNode->mScale;
3495 case Dali::Actor::Property::SCALE_Z:
3496 property = &mNode->mScale;
3499 case Dali::Actor::Property::VISIBLE:
3500 property = &mNode->mVisible;
3503 case Dali::Actor::Property::COLOR:
3504 property = &mNode->mColor;
3507 case Dali::Actor::Property::COLOR_RED:
3508 property = &mNode->mColor;
3511 case Dali::Actor::Property::COLOR_GREEN:
3512 property = &mNode->mColor;
3515 case Dali::Actor::Property::COLOR_BLUE:
3516 property = &mNode->mColor;
3519 case Dali::Actor::Property::COLOR_ALPHA:
3520 property = &mNode->mColor;
3531 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3533 const PropertyInputImpl* property( NULL );
3535 // This method should only return a property of an object connected to the scene-graph
3541 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3543 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3544 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3546 property = animatable->GetSceneGraphProperty();
3548 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3550 CustomPropertyMetadata* custom = FindCustomProperty( index );
3551 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3552 property = custom->GetSceneGraphProperty();
3554 else if( NULL != mNode )
3558 case Dali::Actor::Property::PARENT_ORIGIN:
3559 property = &mNode->mParentOrigin;
3562 case Dali::Actor::Property::PARENT_ORIGIN_X:
3563 property = &mNode->mParentOrigin;
3566 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3567 property = &mNode->mParentOrigin;
3570 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3571 property = &mNode->mParentOrigin;
3574 case Dali::Actor::Property::ANCHOR_POINT:
3575 property = &mNode->mAnchorPoint;
3578 case Dali::Actor::Property::ANCHOR_POINT_X:
3579 property = &mNode->mAnchorPoint;
3582 case Dali::Actor::Property::ANCHOR_POINT_Y:
3583 property = &mNode->mAnchorPoint;
3586 case Dali::Actor::Property::ANCHOR_POINT_Z:
3587 property = &mNode->mAnchorPoint;
3590 case Dali::Actor::Property::SIZE:
3591 property = &mNode->mSize;
3594 case Dali::Actor::Property::SIZE_WIDTH:
3595 property = &mNode->mSize;
3598 case Dali::Actor::Property::SIZE_HEIGHT:
3599 property = &mNode->mSize;
3602 case Dali::Actor::Property::SIZE_DEPTH:
3603 property = &mNode->mSize;
3606 case Dali::Actor::Property::POSITION:
3607 property = &mNode->mPosition;
3610 case Dali::Actor::Property::POSITION_X:
3611 property = &mNode->mPosition;
3614 case Dali::Actor::Property::POSITION_Y:
3615 property = &mNode->mPosition;
3618 case Dali::Actor::Property::POSITION_Z:
3619 property = &mNode->mPosition;
3622 case Dali::Actor::Property::WORLD_POSITION:
3623 property = &mNode->mWorldPosition;
3626 case Dali::Actor::Property::WORLD_POSITION_X:
3627 property = &mNode->mWorldPosition;
3630 case Dali::Actor::Property::WORLD_POSITION_Y:
3631 property = &mNode->mWorldPosition;
3634 case Dali::Actor::Property::WORLD_POSITION_Z:
3635 property = &mNode->mWorldPosition;
3638 case Dali::Actor::Property::ORIENTATION:
3639 property = &mNode->mOrientation;
3642 case Dali::Actor::Property::WORLD_ORIENTATION:
3643 property = &mNode->mWorldOrientation;
3646 case Dali::Actor::Property::SCALE:
3647 property = &mNode->mScale;
3650 case Dali::Actor::Property::SCALE_X:
3651 property = &mNode->mScale;
3654 case Dali::Actor::Property::SCALE_Y:
3655 property = &mNode->mScale;
3658 case Dali::Actor::Property::SCALE_Z:
3659 property = &mNode->mScale;
3662 case Dali::Actor::Property::WORLD_SCALE:
3663 property = &mNode->mWorldScale;
3666 case Dali::Actor::Property::VISIBLE:
3667 property = &mNode->mVisible;
3670 case Dali::Actor::Property::COLOR:
3671 property = &mNode->mColor;
3674 case Dali::Actor::Property::COLOR_RED:
3675 property = &mNode->mColor;
3678 case Dali::Actor::Property::COLOR_GREEN:
3679 property = &mNode->mColor;
3682 case Dali::Actor::Property::COLOR_BLUE:
3683 property = &mNode->mColor;
3686 case Dali::Actor::Property::COLOR_ALPHA:
3687 property = &mNode->mColor;
3690 case Dali::Actor::Property::WORLD_COLOR:
3691 property = &mNode->mWorldColor;
3694 case Dali::Actor::Property::WORLD_MATRIX:
3695 property = &mNode->mWorldMatrix;
3706 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3708 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3710 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3712 // check whether the animatable property is registered already, if not then register one.
3713 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3714 if( animatableProperty )
3716 componentIndex = animatableProperty->componentIndex;
3723 case Dali::Actor::Property::PARENT_ORIGIN_X:
3724 case Dali::Actor::Property::ANCHOR_POINT_X:
3725 case Dali::Actor::Property::SIZE_WIDTH:
3726 case Dali::Actor::Property::POSITION_X:
3727 case Dali::Actor::Property::WORLD_POSITION_X:
3728 case Dali::Actor::Property::SCALE_X:
3729 case Dali::Actor::Property::COLOR_RED:
3735 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3736 case Dali::Actor::Property::ANCHOR_POINT_Y:
3737 case Dali::Actor::Property::SIZE_HEIGHT:
3738 case Dali::Actor::Property::POSITION_Y:
3739 case Dali::Actor::Property::WORLD_POSITION_Y:
3740 case Dali::Actor::Property::SCALE_Y:
3741 case Dali::Actor::Property::COLOR_GREEN:
3747 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3748 case Dali::Actor::Property::ANCHOR_POINT_Z:
3749 case Dali::Actor::Property::SIZE_DEPTH:
3750 case Dali::Actor::Property::POSITION_Z:
3751 case Dali::Actor::Property::WORLD_POSITION_Z:
3752 case Dali::Actor::Property::SCALE_Z:
3753 case Dali::Actor::Property::COLOR_BLUE:
3759 case Dali::Actor::Property::COLOR_ALPHA:
3773 return componentIndex;
3776 void Actor::SetParent( Actor* parent, int index )
3780 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3784 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3787 // Instruct each actor to create a corresponding node in the scene graph
3788 ConnectToStage( index );
3791 else // parent being set to NULL
3793 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3797 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3800 DALI_ASSERT_ALWAYS( mNode != NULL );
3804 // Disconnect the Node & its children from the scene-graph.
3805 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3808 // Instruct each actor to discard pointers to the scene-graph
3809 DisconnectFromStage();
3814 SceneGraph::Node* Actor::CreateNode() const
3819 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3822 Actor* actor = dynamic_cast< Actor* >( object );
3826 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3828 actor->SetVisible( true );
3831 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3833 actor->SetVisible( false );
3841 void Actor::EnsureRelayoutData() const
3843 // Assign relayout data.
3844 if( !mRelayoutData )
3846 mRelayoutData = new RelayoutData();
3850 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3852 // Check if actor is dependent on parent
3853 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3855 if( ( dimension & ( 1 << i ) ) )
3857 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3858 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3868 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3870 // Check if actor is dependent on children
3871 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3873 if( ( dimension & ( 1 << i ) ) )
3875 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3876 switch( resizePolicy )
3878 case ResizePolicy::FIT_TO_CHILDREN:
3879 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3895 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3897 return Actor::RelayoutDependentOnChildren( dimension );
3900 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3902 // Check each possible dimension and see if it is dependent on the input one
3903 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3905 if( dimension & ( 1 << i ) )
3907 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3914 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3916 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3918 if( dimension & ( 1 << i ) )
3920 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3925 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3927 // If more than one dimension is requested, just return the first one found
3928 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3930 if( ( dimension & ( 1 << i ) ) )
3932 return mRelayoutData->negotiatedDimensions[ i ];
3936 return 0.0f; // Default
3939 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3941 EnsureRelayoutData();
3943 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3945 if( dimension & ( 1 << i ) )
3947 mRelayoutData->dimensionPadding[ i ] = padding;
3952 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3954 EnsureRelayoutData();
3956 // If more than one dimension is requested, just return the first one found
3957 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3959 if( ( dimension & ( 1 << i ) ) )
3961 return mRelayoutData->dimensionPadding[ i ];
3965 return Vector2( 0.0f, 0.0f ); // Default
3968 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3970 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3972 if( dimension & ( 1 << i ) )
3974 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3979 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3981 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3983 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3992 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3994 // Could be overridden in derived classes.
3995 return CalculateChildSizeBase( child, dimension );
3998 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4000 // Fill to parent, taking size mode factor into account
4001 switch( child.GetResizePolicy( dimension ) )
4003 case ResizePolicy::FILL_TO_PARENT:
4005 return GetLatestSize( dimension );
4008 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4010 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4013 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4015 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4020 return GetLatestSize( dimension );
4025 float Actor::GetHeightForWidth( float width )
4027 // Could be overridden in derived classes.
4028 float height = 0.0f;
4030 const Vector3 naturalSize = GetNaturalSize();
4031 if( naturalSize.width > 0.0f )
4033 height = naturalSize.height * width / naturalSize.width;
4039 float Actor::GetWidthForHeight( float height )
4041 // Could be overridden in derived classes.
4044 const Vector3 naturalSize = GetNaturalSize();
4045 if( naturalSize.height > 0.0f )
4047 width = naturalSize.width * height / naturalSize.height;
4053 float Actor::GetLatestSize( Dimension::Type dimension ) const
4055 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4058 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4060 Vector2 padding = GetPadding( dimension );
4062 return GetLatestSize( dimension ) + padding.x + padding.y;
4065 float Actor::NegotiateFromParent( Dimension::Type dimension )
4067 Actor* parent = GetParent();
4070 Vector2 padding( GetPadding( dimension ) );
4071 Vector2 parentPadding( parent->GetPadding( dimension ) );
4072 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4078 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4080 float maxDimensionPoint = 0.0f;
4082 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4084 Dali::Actor child = GetChildAt( i );
4085 Actor& childImpl = GetImplementation( child );
4087 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4089 // Calculate the min and max points that the children range across
4090 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4091 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4092 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4096 return maxDimensionPoint;
4099 float Actor::GetSize( Dimension::Type dimension ) const
4101 return GetDimensionValue( GetTargetSize(), dimension );
4104 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4106 return GetDimensionValue( GetNaturalSize(), dimension );
4109 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4111 switch( GetResizePolicy( dimension ) )
4113 case ResizePolicy::USE_NATURAL_SIZE:
4115 return GetNaturalSize( dimension );
4118 case ResizePolicy::FIXED:
4120 return GetDimensionValue( GetPreferredSize(), dimension );
4123 case ResizePolicy::USE_ASSIGNED_SIZE:
4125 return GetDimensionValue( maximumSize, dimension );
4128 case ResizePolicy::FILL_TO_PARENT:
4129 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4130 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4132 return NegotiateFromParent( dimension );
4135 case ResizePolicy::FIT_TO_CHILDREN:
4137 return NegotiateFromChildren( dimension );
4140 case ResizePolicy::DIMENSION_DEPENDENCY:
4142 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4145 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4147 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4150 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4152 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4164 return 0.0f; // Default
4167 float Actor::ClampDimension( float size, Dimension::Type dimension )
4169 const float minSize = GetMinimumSize( dimension );
4170 const float maxSize = GetMaximumSize( dimension );
4172 return std::max( minSize, std::min( size, maxSize ) );
4175 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4177 // Check if it needs to be negotiated
4178 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4180 // Check that we havn't gotten into an infinite loop
4181 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4182 bool recursionFound = false;
4183 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4185 if( *it == searchActor )
4187 recursionFound = true;
4192 if( !recursionFound )
4194 // Record the path that we have taken
4195 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4197 // Dimension dependency check
4198 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4200 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4202 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4204 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4208 // Parent dependency check
4209 Actor* parent = GetParent();
4210 if( parent && RelayoutDependentOnParent( dimension ) )
4212 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4215 // Children dependency check
4216 if( RelayoutDependentOnChildren( dimension ) )
4218 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4220 Dali::Actor child = GetChildAt( i );
4221 Actor& childImpl = GetImplementation( child );
4223 // Only relayout child first if it is not dependent on this actor
4224 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4226 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4231 // For deriving classes
4232 OnCalculateRelayoutSize( dimension );
4234 // All dependencies checked, calculate the size and set negotiated flag
4235 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4237 SetNegotiatedDimension( newSize, dimension );
4238 SetLayoutNegotiated( true, dimension );
4240 // For deriving classes
4241 OnLayoutNegotiated( newSize, dimension );
4243 // This actor has been successfully processed, pop it off the recursion stack
4244 recursionStack.pop_back();
4248 // TODO: Break infinite loop
4249 SetLayoutNegotiated( true, dimension );
4254 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4256 // Negotiate all dimensions that require it
4257 ActorDimensionStack recursionStack;
4259 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4261 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4264 NegotiateDimension( dimension, allocatedSize, recursionStack );
4268 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4270 switch( mRelayoutData->sizeSetPolicy )
4272 case SizeScalePolicy::USE_SIZE_SET:
4277 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4279 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4280 const Vector3 naturalSize = GetNaturalSize();
4281 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4283 const float sizeRatio = size.width / size.height;
4284 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4286 if( naturalSizeRatio < sizeRatio )
4288 return Vector2( naturalSizeRatio * size.height, size.height );
4290 else if( naturalSizeRatio > sizeRatio )
4292 return Vector2( size.width, size.width / naturalSizeRatio );
4303 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4305 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4306 const Vector3 naturalSize = GetNaturalSize();
4307 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4309 const float sizeRatio = size.width / size.height;
4310 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4312 if( naturalSizeRatio < sizeRatio )
4314 return Vector2( size.width, size.width / naturalSizeRatio );
4316 else if( naturalSizeRatio > sizeRatio )
4318 return Vector2( naturalSizeRatio * size.height, size.height );
4336 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4338 // Do the set actor size
4339 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4341 // Adjust for size set policy
4342 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4344 // Lock the flag to stop recursive relayouts on set size
4345 mRelayoutData->insideRelayout = true;
4346 SetSize( negotiatedSize );
4347 mRelayoutData->insideRelayout = false;
4349 // Clear flags for all dimensions
4350 SetLayoutDirty( false );
4352 // Give deriving classes a chance to respond
4353 OnRelayout( negotiatedSize, container );
4355 if( !mOnRelayoutSignal.Empty() )
4357 Dali::Actor handle( this );
4358 mOnRelayoutSignal.Emit( handle );
4362 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4364 // Do the negotiation
4365 NegotiateDimensions( allocatedSize );
4367 // Set the actor size
4368 SetNegotiatedSize( container );
4370 // Negotiate down to children
4371 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4373 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4375 Dali::Actor child = GetChildAt( i );
4377 // Only relayout if required
4378 if( GetImplementation( child ).RelayoutRequired() )
4380 container.Add( child, newBounds );
4385 void Actor::RelayoutRequest( Dimension::Type dimension )
4387 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4388 if( relayoutController )
4390 Dali::Actor self( this );
4391 relayoutController->RequestRelayout( self, dimension );
4395 void Actor::PropagateRelayoutFlags()
4397 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4398 if( relayoutController )
4400 Dali::Actor self( this );
4401 relayoutController->PropagateFlags( self );
4405 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4409 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4413 void Actor::SetPreferredSize( const Vector2& size )
4415 EnsureRelayoutData();
4417 if( size.width > 0.0f )
4419 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4422 if( size.height > 0.0f )
4424 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4427 mRelayoutData->preferredSize = size;
4432 Vector2 Actor::GetPreferredSize() const
4434 EnsureRelayoutData();
4436 return mRelayoutData->preferredSize;
4439 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4441 EnsureRelayoutData();
4443 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4445 if( dimension & ( 1 << i ) )
4447 mRelayoutData->minimumSize[ i ] = size;
4454 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4456 EnsureRelayoutData();
4458 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4460 if( dimension & ( 1 << i ) )
4462 return mRelayoutData->minimumSize[ i ];
4466 return 0.0f; // Default
4469 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4471 EnsureRelayoutData();
4473 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4475 if( dimension & ( 1 << i ) )
4477 mRelayoutData->maximumSize[ i ] = size;
4484 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4486 EnsureRelayoutData();
4488 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4490 if( dimension & ( 1 << i ) )
4492 return mRelayoutData->maximumSize[ i ];
4496 return 0.0f; // Default
4499 } // namespace Internal