2 * Copyright (c) 2014 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 ActorContainer Actor::GetChildren()
562 if( NULL != mChildren )
567 // return copy of mNullChildren
568 return mNullChildren;
571 const ActorContainer& Actor::GetChildren() const
573 if( NULL != mChildren )
578 // return const reference to mNullChildren
579 return mNullChildren;
582 ActorPtr Actor::FindChildByName( const std::string& actorName )
585 if( actorName == mName )
591 ActorIter end = mChildren->end();
592 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
594 child = GetImplementation( *iter ).FindChildByName( actorName );
605 ActorPtr Actor::FindChildById( const unsigned int id )
614 ActorIter end = mChildren->end();
615 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
617 child = GetImplementation( *iter ).FindChildById( id );
628 void Actor::SetParentOrigin( const Vector3& origin )
632 // mNode is being used in a separate thread; queue a message to set the value & base value
633 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
636 // Cache for event-thread access
639 // not allocated, check if different from default
640 if( ParentOrigin::DEFAULT != origin )
642 mParentOrigin = new Vector3( origin );
647 // check if different from current costs more than just set
648 *mParentOrigin = origin;
652 void Actor::SetParentOriginX( float x )
654 const Vector3& current = GetCurrentParentOrigin();
656 SetParentOrigin( Vector3( x, current.y, current.z ) );
659 void Actor::SetParentOriginY( float y )
661 const Vector3& current = GetCurrentParentOrigin();
663 SetParentOrigin( Vector3( current.x, y, current.z ) );
666 void Actor::SetParentOriginZ( float z )
668 const Vector3& current = GetCurrentParentOrigin();
670 SetParentOrigin( Vector3( current.x, current.y, z ) );
673 const Vector3& Actor::GetCurrentParentOrigin() const
675 // Cached for event-thread access
676 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
679 void Actor::SetAnchorPoint( const Vector3& anchor )
683 // mNode is being used in a separate thread; queue a message to set the value & base value
684 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
687 // Cache for event-thread access
690 // not allocated, check if different from default
691 if( AnchorPoint::DEFAULT != anchor )
693 mAnchorPoint = new Vector3( anchor );
698 // check if different from current costs more than just set
699 *mAnchorPoint = anchor;
703 void Actor::SetAnchorPointX( float x )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( x, current.y, current.z ) );
710 void Actor::SetAnchorPointY( float y )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( current.x, y, current.z ) );
717 void Actor::SetAnchorPointZ( float z )
719 const Vector3& current = GetCurrentAnchorPoint();
721 SetAnchorPoint( Vector3( current.x, current.y, z ) );
724 const Vector3& Actor::GetCurrentAnchorPoint() const
726 // Cached for event-thread access
727 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
730 void Actor::SetPosition( float x, float y )
732 SetPosition( Vector3( x, y, 0.0f ) );
735 void Actor::SetPosition( float x, float y, float z )
737 SetPosition( Vector3( x, y, z ) );
740 void Actor::SetPosition( const Vector3& position )
742 mTargetPosition = position;
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
751 void Actor::SetX( float x )
753 mTargetPosition.x = x;
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>::BakeX, x );
762 void Actor::SetY( float y )
764 mTargetPosition.y = y;
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
773 void Actor::SetZ( float z )
775 mTargetPosition.z = z;
779 // mNode is being used in a separate thread; queue a message to set the value & base value
780 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
784 void Actor::TranslateBy( const Vector3& distance )
786 mTargetPosition += distance;
790 // mNode is being used in a separate thread; queue a message to set the value & base value
791 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
795 const Vector3& Actor::GetCurrentPosition() const
799 // mNode is being used in a separate thread; copy the value from the previous update
800 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
803 return Vector3::ZERO;
806 const Vector3& Actor::GetTargetPosition() const
808 return mTargetPosition;
811 const Vector3& Actor::GetCurrentWorldPosition() const
815 // mNode is being used in a separate thread; copy the value from the previous update
816 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
819 return Vector3::ZERO;
822 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
824 // this flag is not animatable so keep the value
825 mPositionInheritanceMode = mode;
828 // mNode is being used in a separate thread; queue a message to set the value
829 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
833 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
835 // Cached for event-thread access
836 return mPositionInheritanceMode;
839 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
841 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
842 normalizedAxis.Normalize();
844 Quaternion orientation( angle, normalizedAxis );
846 SetOrientation( orientation );
849 void Actor::SetOrientation( const Quaternion& orientation )
853 // mNode is being used in a separate thread; queue a message to set the value & base value
854 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
858 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
862 // mNode is being used in a separate thread; queue a message to set the value & base value
863 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
867 void Actor::RotateBy( const Quaternion& relativeRotation )
871 // mNode is being used in a separate thread; queue a message to set the value & base value
872 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
876 const Quaternion& Actor::GetCurrentOrientation() const
880 // mNode is being used in a separate thread; copy the value from the previous update
881 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
884 return Quaternion::IDENTITY;
887 const Quaternion& Actor::GetCurrentWorldOrientation() const
891 // mNode is being used in a separate thread; copy the value from the previous update
892 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
895 return Quaternion::IDENTITY;
898 void Actor::SetScale( float scale )
900 SetScale( Vector3( scale, scale, scale ) );
903 void Actor::SetScale( float x, float y, float z )
905 SetScale( Vector3( x, y, z ) );
908 void Actor::SetScale( const Vector3& scale )
912 // mNode is being used in a separate thread; queue a message to set the value & base value
913 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
917 void Actor::SetScaleX( float x )
921 // mNode is being used in a separate thread; queue a message to set the value & base value
922 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
926 void Actor::SetScaleY( float y )
930 // mNode is being used in a separate thread; queue a message to set the value & base value
931 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
935 void Actor::SetScaleZ( float z )
939 // mNode is being used in a separate thread; queue a message to set the value & base value
940 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
944 void Actor::SetInitialVolume( const Vector3& volume )
948 // mNode is being used in a separate thread; queue a message to set the value
949 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
953 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
957 // mNode is being used in a separate thread; queue a message to set the value
958 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
962 bool Actor::GetTransmitGeometryScaling() const
966 // mNode is being used in a separate thread; copy the value from the previous update
967 return mNode->GetTransmitGeometryScaling();
973 void Actor::ScaleBy( const Vector3& relativeScale )
977 // mNode is being used in a separate thread; queue a message to set the value & base value
978 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
982 const Vector3& Actor::GetCurrentScale() const
986 // mNode is being used in a separate thread; copy the value from the previous update
987 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
993 const Vector3& Actor::GetCurrentWorldScale() const
997 // mNode is being used in a separate thread; copy the value from the previous update
998 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1001 return Vector3::ONE;
1004 void Actor::SetInheritScale( bool inherit )
1006 // non animateable so keep local copy
1007 mInheritScale = inherit;
1010 // mNode is being used in a separate thread; queue a message to set the value
1011 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1015 bool Actor::IsScaleInherited() const
1017 return mInheritScale;
1020 Matrix Actor::GetCurrentWorldMatrix() const
1024 // World matrix is no longer updated unless there is something observing the node.
1025 // Need to calculate it from node's world position, orientation and scale:
1026 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1027 Matrix worldMatrix(false);
1028 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1029 mNode->GetWorldOrientation( updateBufferIndex ),
1030 mNode->GetWorldPosition( updateBufferIndex ) );
1034 return Matrix::IDENTITY;
1037 void Actor::SetVisible( bool visible )
1041 // mNode is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1046 bool Actor::IsVisible() const
1050 // mNode is being used in a separate thread; copy the value from the previous update
1051 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1057 void Actor::SetOpacity( float opacity )
1061 // mNode is being used in a separate thread; queue a message to set the value & base value
1062 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1066 float Actor::GetCurrentOpacity() const
1070 // mNode is being used in a separate thread; copy the value from the previous update
1071 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1077 const Vector4& Actor::GetCurrentWorldColor() const
1081 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1084 return Color::WHITE;
1087 void Actor::SetColor( const Vector4& color )
1091 // mNode is being used in a separate thread; queue a message to set the value & base value
1092 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1096 void Actor::SetColorRed( float red )
1100 // mNode is being used in a separate thread; queue a message to set the value & base value
1101 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1105 void Actor::SetColorGreen( float green )
1109 // mNode is being used in a separate thread; queue a message to set the value & base value
1110 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1114 void Actor::SetColorBlue( float blue )
1118 // mNode is being used in a separate thread; queue a message to set the value & base value
1119 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1123 const Vector4& Actor::GetCurrentColor() const
1127 // mNode is being used in a separate thread; copy the value from the previous update
1128 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1131 return Color::WHITE;
1134 void Actor::SetInheritOrientation( bool inherit )
1136 // non animateable so keep local copy
1137 mInheritOrientation = inherit;
1140 // mNode is being used in a separate thread; queue a message to set the value
1141 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1145 bool Actor::IsOrientationInherited() const
1147 return mInheritOrientation;
1150 void Actor::SetSizeModeFactor( const Vector3& factor )
1152 EnsureRelayoutData();
1154 mRelayoutData->sizeModeFactor = factor;
1157 const Vector3& Actor::GetSizeModeFactor() const
1159 EnsureRelayoutData();
1161 return mRelayoutData->sizeModeFactor;
1164 void Actor::SetColorMode( ColorMode colorMode )
1166 // non animateable so keep local copy
1167 mColorMode = colorMode;
1170 // mNode is being used in a separate thread; queue a message to set the value
1171 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1175 ColorMode Actor::GetColorMode() const
1177 // we have cached copy
1181 void Actor::SetSize( float width, float height )
1183 SetSize( Vector2( width, height ) );
1186 void Actor::SetSize( float width, float height, float depth )
1188 SetSize( Vector3( width, height, depth ) );
1191 void Actor::SetSize( const Vector2& size )
1193 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1196 void Actor::SetSizeInternal( const Vector2& size )
1198 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1201 float Actor::CalculateSizeZ( const Vector2& size ) const
1203 return std::min( size.width, size.height );
1206 void Actor::SetSize( const Vector3& size )
1208 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1210 SetPreferredSize( size.GetVectorXY() );
1214 SetSizeInternal( size );
1218 void Actor::SetSizeInternal( const Vector3& size )
1224 // mNode is being used in a separate thread; queue a message to set the value & base value
1225 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1227 // Notification for derived classes
1228 OnSizeSet( mTargetSize );
1230 // Raise a relayout request if the flag is not locked
1231 if( mRelayoutData && !mRelayoutData->insideRelayout )
1238 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1240 mTargetSize = targetSize;
1242 // Notify deriving classes
1243 OnSizeAnimation( animation, targetSize );
1246 void Actor::SetWidth( float width )
1250 // mNode is being used in a separate thread; queue a message to set the value & base value
1251 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1255 void Actor::SetHeight( float height )
1259 // mNode is being used in a separate thread; queue a message to set the value & base value
1260 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1264 void Actor::SetDepth( float depth )
1268 // mNode is being used in a separate thread; queue a message to set the value & base value
1269 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1273 const Vector3& Actor::GetTargetSize() const
1278 const Vector3& Actor::GetCurrentSize() const
1282 // mNode is being used in a separate thread; copy the value from the previous update
1283 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1286 return Vector3::ZERO;
1289 Vector3 Actor::GetNaturalSize() const
1291 // It is up to deriving classes to return the appropriate natural size
1292 return Vector3( 0.0f, 0.0f, 0.0f );
1295 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1297 EnsureRelayoutData();
1299 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1301 if( dimension & ( 1 << i ) )
1303 mRelayoutData->resizePolicies[ i ] = policy;
1307 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1309 if( dimension & Dimension::WIDTH )
1311 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1314 if( dimension & Dimension::HEIGHT )
1316 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1320 // If calling SetResizePolicy, assume we want relayout enabled
1321 SetRelayoutEnabled( true );
1323 OnSetResizePolicy( policy, dimension );
1325 // Trigger relayout on this control
1329 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1331 EnsureRelayoutData();
1333 // If more than one dimension is requested, just return the first one found
1334 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1336 if( ( dimension & ( 1 << i ) ) )
1338 return mRelayoutData->resizePolicies[ i ];
1342 return ResizePolicy::FIXED; // Default
1345 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1347 EnsureRelayoutData();
1349 mRelayoutData->sizeSetPolicy = policy;
1352 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1354 EnsureRelayoutData();
1356 return mRelayoutData->sizeSetPolicy;
1359 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1361 EnsureRelayoutData();
1363 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1365 if( dimension & ( 1 << i ) )
1367 mRelayoutData->dimensionDependencies[ i ] = dependency;
1372 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1374 EnsureRelayoutData();
1376 // If more than one dimension is requested, just return the first one found
1377 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1379 if( ( dimension & ( 1 << i ) ) )
1381 return mRelayoutData->dimensionDependencies[ i ];
1385 return Dimension::ALL_DIMENSIONS; // Default
1388 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1390 // If relayout data has not been allocated yet and the client is requesting
1391 // to disable it, do nothing
1392 if( mRelayoutData || relayoutEnabled )
1394 EnsureRelayoutData();
1396 mRelayoutData->relayoutEnabled = relayoutEnabled;
1400 bool Actor::IsRelayoutEnabled() const
1402 // Assume that if relayout data has not been allocated yet then
1403 // relayout is disabled
1404 return mRelayoutData && mRelayoutData->relayoutEnabled;
1407 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1409 EnsureRelayoutData();
1411 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1413 if( dimension & ( 1 << i ) )
1415 mRelayoutData->dimensionDirty[ i ] = dirty;
1420 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1422 EnsureRelayoutData();
1424 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1426 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1435 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1437 EnsureRelayoutData();
1439 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1442 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1444 EnsureRelayoutData();
1446 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1449 #ifdef DYNAMICS_SUPPORT
1451 //--------------- Dynamics ---------------
1453 void Actor::DisableDynamics()
1455 if( NULL != mDynamicsData )
1457 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1459 // ensure dynamics object are disconnected from scene
1460 DisconnectDynamics();
1462 // delete joint owned by this actor
1463 while( !mDynamicsData->joints.empty() )
1465 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1468 // delete other joints referencing this actor
1469 while( !mDynamicsData->referencedJoints.empty() )
1471 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1472 ActorPtr jointOwner( joint->GetActor( true ) );
1475 jointOwner->RemoveDynamicsJoint( joint );
1479 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1482 // delete the DynamicsBody object
1483 mDynamicsData->body.Reset();
1485 // Discard Dynamics data structure
1486 delete mDynamicsData;
1487 mDynamicsData = NULL;
1491 DynamicsBodyPtr Actor::GetDynamicsBody() const
1493 DynamicsBodyPtr body;
1495 if( NULL != mDynamicsData )
1497 body = mDynamicsData->body;
1503 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1505 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1507 if( NULL == mDynamicsData )
1509 mDynamicsData = new DynamicsData( this );
1512 if( !mDynamicsData->body )
1514 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1518 DynamicsWorldPtr world( DynamicsWorld::Get() );
1521 if( mParent == world->GetRootActor().Get() )
1523 mDynamicsData->body->Connect( GetEventThreadServices() );
1529 return mDynamicsData->body;
1532 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1534 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1535 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1538 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1540 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1541 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1543 DynamicsJointPtr joint;
1545 DynamicsWorldPtr world( DynamicsWorld::Get() );
1549 if( NULL != mDynamicsData )
1551 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1553 if( mDynamicsData->joints.end() != it )
1555 // use existing joint
1561 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1562 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1566 bodyA = EnableDynamics( new DynamicsBodyConfig );
1571 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1574 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1575 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1577 if( OnStage() && attachedActor->OnStage() )
1579 joint->Connect( GetEventThreadServices() );
1582 attachedActor->ReferenceJoint( joint );
1584 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1585 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1592 const int Actor::GetNumberOfJoints() const
1594 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1597 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1599 DynamicsJointPtr joint;
1601 if( NULL != mDynamicsData )
1603 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1605 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1607 for( int i = 0; i < index; ++i )
1619 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1621 DynamicsJointPtr joint;
1623 if( NULL != mDynamicsData )
1625 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1627 if( mDynamicsData->joints.end() != it )
1629 // use existing joint
1637 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1639 if( NULL != mDynamicsData )
1641 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1642 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1644 for(; it != endIt; ++it )
1646 if( it->second == joint.Get() )
1648 ActorPtr attachedActor( it->first );
1650 if( OnStage() && attachedActor && attachedActor->OnStage() )
1652 joint->Disconnect( GetEventThreadServices() );
1657 attachedActor->ReleaseJoint( joint );
1658 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1659 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1662 mDynamicsData->joints.erase(it);
1669 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1671 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1673 if( NULL != mDynamicsData )
1675 mDynamicsData->referencedJoints.push_back(joint);
1679 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1681 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1683 if( NULL != mDynamicsData )
1685 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1687 if( it != mDynamicsData->referencedJoints.end() )
1689 mDynamicsData->referencedJoints.erase( it );
1694 void Actor::SetDynamicsRoot(bool flag)
1696 if( mIsDynamicsRoot != flag )
1698 mIsDynamicsRoot = flag;
1700 if( OnStage() && mChildren )
1702 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1703 ActorIter end = mChildren->end();
1704 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1706 Actor& child = GetImplementation(*iter);
1708 if( child.GetDynamicsBody() )
1710 if( mIsDynamicsRoot )
1712 child.ConnectDynamics();
1716 child.DisconnectDynamics();
1724 bool Actor::IsDynamicsRoot() const
1726 return mIsDynamicsRoot;
1729 void Actor::AttachedActorOnStage( Dali::Actor actor )
1731 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1735 ActorPtr attachedActor( &GetImplementation(actor) );
1737 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1738 if( NULL != mDynamicsData )
1740 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1741 if( mDynamicsData->joints.end() != it )
1743 DynamicsJointPtr joint( it->second );
1744 joint->Connect( GetEventThreadServices() );
1750 void Actor::AttachedActorOffStage( Dali::Actor actor )
1752 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1756 ActorPtr attachedActor( &GetImplementation(actor) );
1758 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1759 if( NULL != mDynamicsData )
1761 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1762 if( mDynamicsData->joints.end() != it )
1764 DynamicsJointPtr joint( it->second );
1765 joint->Disconnect( GetEventThreadServices() );
1771 void Actor::ConnectDynamics()
1773 if( NULL != mDynamicsData && mDynamicsData->body )
1775 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1777 mDynamicsData->body->Connect( GetEventThreadServices() );
1779 // Connect all joints where attachedActor is also on stage
1780 if( !mDynamicsData->joints.empty() )
1782 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1783 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1785 for(; it != endIt; ++it )
1787 Actor* attachedActor( it->first );
1788 if( NULL != attachedActor && attachedActor->OnStage() )
1790 DynamicsJointPtr joint( it->second );
1792 joint->Connect( GetEventThreadServices() );
1800 void Actor::DisconnectDynamics()
1802 if( NULL != mDynamicsData && mDynamicsData->body )
1806 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1808 // Disconnect all joints
1809 if( !mDynamicsData->joints.empty() )
1811 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1812 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1814 for(; it != endIt; ++it )
1816 DynamicsJointPtr joint( it->second );
1818 joint->Disconnect( GetEventThreadServices() );
1825 #endif // DYNAMICS_SUPPORT
1827 void Actor::SetOverlay( bool enable )
1829 // Setting STENCIL will override OVERLAY
1830 if( DrawMode::STENCIL != mDrawMode )
1832 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1836 bool Actor::IsOverlay() const
1838 return ( DrawMode::OVERLAY == mDrawMode );
1841 void Actor::SetDrawMode( DrawMode::Type drawMode )
1843 // this flag is not animatable so keep the value
1844 mDrawMode = drawMode;
1847 // mNode is being used in a separate thread; queue a message to set the value
1848 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1852 DrawMode::Type Actor::GetDrawMode() const
1857 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1859 // only valid when on-stage
1862 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1864 Vector2 converted( screenX, screenY );
1866 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1867 const int taskCount = taskList.GetTaskCount();
1868 for( int i = taskCount - 1; i >= 0; --i )
1870 Dali::RenderTask task = taskList.GetTask( i );
1871 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1873 // found a task where this conversion was ok so return
1881 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1883 bool retval = false;
1884 // only valid when on-stage
1887 CameraActor* camera = renderTask.GetCameraActor();
1891 renderTask.GetViewport( viewport );
1893 // need to translate coordinates to render tasks coordinate space
1894 Vector2 converted( screenX, screenY );
1895 if( renderTask.TranslateCoordinates( converted ) )
1897 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1904 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1906 // Early-out if mNode is NULL
1912 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1914 // Calculate the ModelView matrix
1915 Matrix modelView( false/*don't init*/);
1916 // need to use the components as world matrix is only updated for actors that need it
1917 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1918 Matrix::Multiply( modelView, modelView, viewMatrix );
1920 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1921 Matrix invertedMvp( false/*don't init*/);
1922 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1923 bool success = invertedMvp.Invert();
1925 // Convert to GL coordinates
1926 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1931 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1938 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1944 if( XyPlaneIntersect( nearPos, farPos, local ) )
1946 Vector3 size = GetCurrentSize();
1947 localX = local.x + size.x * 0.5f;
1948 localY = local.y + size.y * 0.5f;
1959 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1962 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1964 Mathematical Formulation
1966 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1968 ( p - c ) dot ( p - c ) = r^2
1970 Given a ray with a point of origin 'o', and a direction vector 'd':
1972 ray(t) = o + td, t >= 0
1974 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1976 (o + td - c ) dot ( o + td - c ) = r^2
1978 To solve for t we first expand the above into a more recognisable quadratic equation form
1980 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1989 B = 2( o - c ) dot d
1990 C = ( o - c ) dot ( o - c ) - r^2
1992 which can be solved using a standard quadratic formula.
1994 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1996 Practical Simplification
1998 In a renderer, we often differentiate between world space and object space. In the object space
1999 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
2000 into object space, the mathematical solution presented above can be simplified significantly.
2002 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2006 and we can find the t at which the (transformed) ray intersects the sphere by
2008 ( o + td ) dot ( o + td ) = r^2
2010 According to the reasoning above, we expand the above quadratic equation into the general form
2014 which now has coefficients:
2021 // Early out if mNode is NULL
2027 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2029 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2030 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2031 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2033 // Compute the radius is not needed, square radius it's enough.
2034 const Vector3& size( mNode->GetSize( bufferIndex ) );
2036 // Scale the sphere.
2037 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2039 const float width = size.width * scale.width;
2040 const float height = size.height * scale.height;
2042 float squareSphereRadius = 0.5f * ( width * width + height * height );
2044 float a = rayDir.Dot( rayDir ); // a
2045 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2046 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2048 return ( b2 * b2 - a * c ) >= 0.f;
2051 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2058 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2060 // Transforms the ray to the local reference system.
2062 // Calculate the inverse of Model matrix
2063 Matrix invModelMatrix( false/*don't init*/);
2064 // need to use the components as world matrix is only updated for actors that need it
2065 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2067 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2068 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2070 // Test with the actor's XY plane (Normal = 0 0 1 1).
2072 float a = -rayOriginLocal.z;
2073 float b = rayDirLocal.z;
2075 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2077 // Ray travels distance * rayDirLocal to intersect with plane.
2080 const Vector3& size = mNode->GetSize( bufferIndex );
2082 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2083 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2085 // Test with the actor's geometry.
2086 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2093 void Actor::SetLeaveRequired( bool required )
2095 mLeaveRequired = required;
2098 bool Actor::GetLeaveRequired() const
2100 return mLeaveRequired;
2103 void Actor::SetKeyboardFocusable( bool focusable )
2105 mKeyboardFocusable = focusable;
2108 bool Actor::IsKeyboardFocusable() const
2110 return mKeyboardFocusable;
2113 bool Actor::GetTouchRequired() const
2115 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2118 bool Actor::GetHoverRequired() const
2120 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2123 bool Actor::GetMouseWheelEventRequired() const
2125 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2128 bool Actor::IsHittable() const
2130 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2133 ActorGestureData& Actor::GetGestureData()
2135 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2136 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2137 if( NULL == mGestureData )
2139 mGestureData = new ActorGestureData;
2141 return *mGestureData;
2144 bool Actor::IsGestureRequred( Gesture::Type type ) const
2146 return mGestureData && mGestureData->IsGestureRequred( type );
2149 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2151 bool consumed = false;
2153 if( !mTouchedSignal.Empty() )
2155 Dali::Actor handle( this );
2156 consumed = mTouchedSignal.Emit( handle, event );
2161 // Notification for derived classes
2162 consumed = OnTouchEvent( event );
2168 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2170 bool consumed = false;
2172 if( !mHoveredSignal.Empty() )
2174 Dali::Actor handle( this );
2175 consumed = mHoveredSignal.Emit( handle, event );
2180 // Notification for derived classes
2181 consumed = OnHoverEvent( event );
2187 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2189 bool consumed = false;
2191 if( !mMouseWheelEventSignal.Empty() )
2193 Dali::Actor handle( this );
2194 consumed = mMouseWheelEventSignal.Emit( handle, event );
2199 // Notification for derived classes
2200 consumed = OnMouseWheelEvent( event );
2206 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2208 return mTouchedSignal;
2211 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2213 return mHoveredSignal;
2216 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2218 return mMouseWheelEventSignal;
2221 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2223 return mOnStageSignal;
2226 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2228 return mOffStageSignal;
2231 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2233 return mOnRelayoutSignal;
2236 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2238 bool connected( true );
2239 Actor* actor = dynamic_cast< Actor* >( object );
2241 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2243 actor->TouchedSignal().Connect( tracker, functor );
2245 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2247 actor->HoveredSignal().Connect( tracker, functor );
2249 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2251 actor->MouseWheelEventSignal().Connect( tracker, functor );
2253 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2255 actor->OnStageSignal().Connect( tracker, functor );
2257 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2259 actor->OffStageSignal().Connect( tracker, functor );
2263 // signalName does not match any signal
2270 Actor::Actor( DerivedType derivedType )
2274 mParentOrigin( NULL ),
2275 mAnchorPoint( NULL ),
2276 mRelayoutData( NULL ),
2277 #ifdef DYNAMICS_SUPPORT
2278 mDynamicsData( NULL ),
2280 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
2281 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 )
2285 void Actor::Initialize()
2288 SceneGraph::Node* node = CreateNode();
2290 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2291 mNode = node; // Keep raw-pointer to Node
2295 GetEventThreadServices().RegisterObject( this );
2300 // Remove mParent pointers from children even if we're destroying core,
2301 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2304 ActorConstIter endIter = mChildren->end();
2305 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2307 Actor& actor = GetImplementation( *iter );
2308 actor.SetParent( NULL );
2313 // Guard to allow handle destruction after Core has been destroyed
2314 if( EventThreadServices::IsCoreRunning() )
2318 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2319 mNode = NULL; // Node is about to be destroyed
2322 GetEventThreadServices().UnregisterObject( this );
2325 #ifdef DYNAMICS_SUPPORT
2327 delete mDynamicsData;
2330 // Cleanup optional gesture data
2331 delete mGestureData;
2333 // Cleanup optional parent origin and anchor
2334 delete mParentOrigin;
2335 delete mAnchorPoint;
2337 // Delete optional relayout data
2340 delete mRelayoutData;
2344 void Actor::ConnectToStage( int index )
2346 // This container is used instead of walking the Actor hierachy.
2347 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2348 ActorContainer connectionList;
2350 // This stage is atomic i.e. not interrupted by user callbacks
2351 RecursiveConnectToStage( connectionList, index );
2353 // Notify applications about the newly connected actors.
2354 const ActorIter endIter = connectionList.end();
2355 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2357 Actor& actor = GetImplementation( *iter );
2358 actor.NotifyStageConnection();
2364 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2366 DALI_ASSERT_ALWAYS( !OnStage() );
2370 ConnectToSceneGraph( index );
2372 // Notification for internal derived classes
2373 OnStageConnectionInternal();
2375 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2376 connectionList.push_back( Dali::Actor( this ) );
2378 // Recursively connect children
2381 ActorConstIter endIter = mChildren->end();
2382 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2384 Actor& actor = GetImplementation( *iter );
2385 actor.RecursiveConnectToStage( connectionList );
2391 * This method is called when the Actor is connected to the Stage.
2392 * The parent must have added its Node to the scene-graph.
2393 * The child must connect its Node to the parent's Node.
2394 * This is resursive; the child calls ConnectToStage() for its children.
2396 void Actor::ConnectToSceneGraph( int index )
2398 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2402 // Reparent Node in next Update
2403 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2406 // Notify attachment
2409 mAttachment->Connect();
2412 #ifdef DYNAMICS_SUPPORT
2414 if( NULL != mDynamicsData )
2420 // Request relayout on all actors that are added to the scenegraph
2423 // Notification for Object::Observers
2427 void Actor::NotifyStageConnection()
2429 // Actors can be removed (in a callback), before the on-stage stage is reported.
2430 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2431 if( OnStage() && !mOnStageSignalled )
2433 // Notification for external (CustomActor) derived classes
2434 OnStageConnectionExternal();
2436 if( !mOnStageSignal.Empty() )
2438 Dali::Actor handle( this );
2439 mOnStageSignal.Emit( handle );
2442 // Guard against Remove during callbacks
2445 mOnStageSignalled = true; // signal required next time Actor is removed
2450 void Actor::DisconnectFromStage()
2452 // This container is used instead of walking the Actor hierachy.
2453 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2454 ActorContainer disconnectionList;
2456 // This stage is atomic i.e. not interrupted by user callbacks
2457 RecursiveDisconnectFromStage( disconnectionList );
2459 // Notify applications about the newly disconnected actors.
2460 const ActorIter endIter = disconnectionList.end();
2461 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2463 Actor& actor = GetImplementation( *iter );
2464 actor.NotifyStageDisconnection();
2468 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2470 DALI_ASSERT_ALWAYS( OnStage() );
2472 // Recursively disconnect children
2475 ActorConstIter endIter = mChildren->end();
2476 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2478 Actor& actor = GetImplementation( *iter );
2479 actor.RecursiveDisconnectFromStage( disconnectionList );
2483 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2484 disconnectionList.push_back( Dali::Actor( this ) );
2486 // Notification for internal derived classes
2487 OnStageDisconnectionInternal();
2489 DisconnectFromSceneGraph();
2495 * This method is called by an actor or its parent, before a node removal message is sent.
2496 * This is recursive; the child calls DisconnectFromStage() for its children.
2498 void Actor::DisconnectFromSceneGraph()
2500 // Notification for Object::Observers
2501 OnSceneObjectRemove();
2503 // Notify attachment
2506 mAttachment->Disconnect();
2509 #ifdef DYNAMICS_SUPPORT
2511 if( NULL != mDynamicsData )
2513 DisconnectDynamics();
2518 void Actor::NotifyStageDisconnection()
2520 // Actors can be added (in a callback), before the off-stage state is reported.
2521 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2522 // only do this step if there is a stage, i.e. Core is not being shut down
2523 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2525 // Notification for external (CustomeActor) derived classes
2526 OnStageDisconnectionExternal();
2528 if( !mOffStageSignal.Empty() )
2530 Dali::Actor handle( this );
2531 mOffStageSignal.Emit( handle );
2534 // Guard against Add during callbacks
2537 mOnStageSignalled = false; // signal required next time Actor is added
2542 bool Actor::IsNodeConnected() const
2544 bool connected( false );
2549 if( mNode->IsRoot() || mNode->GetParent() )
2558 unsigned int Actor::GetDefaultPropertyCount() const
2560 return DEFAULT_PROPERTY_COUNT;
2563 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2565 indices.reserve( DEFAULT_PROPERTY_COUNT );
2567 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2569 indices.push_back( i );
2573 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2575 if( index < DEFAULT_PROPERTY_COUNT )
2577 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2583 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2585 Property::Index index = Property::INVALID_INDEX;
2587 // Look for name in default properties
2588 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2590 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2591 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2601 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2603 if( index < DEFAULT_PROPERTY_COUNT )
2605 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2611 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2613 if( index < DEFAULT_PROPERTY_COUNT )
2615 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2621 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2623 if( index < DEFAULT_PROPERTY_COUNT )
2625 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2631 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2633 if( index < DEFAULT_PROPERTY_COUNT )
2635 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2638 // index out of range...return Property::NONE
2639 return Property::NONE;
2642 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2646 case Dali::Actor::Property::PARENT_ORIGIN:
2648 SetParentOrigin( property.Get< Vector3 >() );
2652 case Dali::Actor::Property::PARENT_ORIGIN_X:
2654 SetParentOriginX( property.Get< float >() );
2658 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2660 SetParentOriginY( property.Get< float >() );
2664 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2666 SetParentOriginZ( property.Get< float >() );
2670 case Dali::Actor::Property::ANCHOR_POINT:
2672 SetAnchorPoint( property.Get< Vector3 >() );
2676 case Dali::Actor::Property::ANCHOR_POINT_X:
2678 SetAnchorPointX( property.Get< float >() );
2682 case Dali::Actor::Property::ANCHOR_POINT_Y:
2684 SetAnchorPointY( property.Get< float >() );
2688 case Dali::Actor::Property::ANCHOR_POINT_Z:
2690 SetAnchorPointZ( property.Get< float >() );
2694 case Dali::Actor::Property::SIZE:
2696 SetSize( property.Get< Vector3 >() );
2700 case Dali::Actor::Property::SIZE_WIDTH:
2702 SetWidth( property.Get< float >() );
2706 case Dali::Actor::Property::SIZE_HEIGHT:
2708 SetHeight( property.Get< float >() );
2712 case Dali::Actor::Property::SIZE_DEPTH:
2714 SetDepth( property.Get< float >() );
2718 case Dali::Actor::Property::POSITION:
2720 SetPosition( property.Get< Vector3 >() );
2724 case Dali::Actor::Property::POSITION_X:
2726 SetX( property.Get< float >() );
2730 case Dali::Actor::Property::POSITION_Y:
2732 SetY( property.Get< float >() );
2736 case Dali::Actor::Property::POSITION_Z:
2738 SetZ( property.Get< float >() );
2742 case Dali::Actor::Property::ORIENTATION:
2744 SetOrientation( property.Get< Quaternion >() );
2748 case Dali::Actor::Property::SCALE:
2750 SetScale( property.Get< Vector3 >() );
2754 case Dali::Actor::Property::SCALE_X:
2756 SetScaleX( property.Get< float >() );
2760 case Dali::Actor::Property::SCALE_Y:
2762 SetScaleY( property.Get< float >() );
2766 case Dali::Actor::Property::SCALE_Z:
2768 SetScaleZ( property.Get< float >() );
2772 case Dali::Actor::Property::VISIBLE:
2774 SetVisible( property.Get< bool >() );
2778 case Dali::Actor::Property::COLOR:
2780 SetColor( property.Get< Vector4 >() );
2784 case Dali::Actor::Property::COLOR_RED:
2786 SetColorRed( property.Get< float >() );
2790 case Dali::Actor::Property::COLOR_GREEN:
2792 SetColorGreen( property.Get< float >() );
2796 case Dali::Actor::Property::COLOR_BLUE:
2798 SetColorBlue( property.Get< float >() );
2802 case Dali::Actor::Property::COLOR_ALPHA:
2804 SetOpacity( property.Get< float >() );
2808 case Dali::Actor::Property::NAME:
2810 SetName( property.Get< std::string >() );
2814 case Dali::Actor::Property::SENSITIVE:
2816 SetSensitive( property.Get< bool >() );
2820 case Dali::Actor::Property::LEAVE_REQUIRED:
2822 SetLeaveRequired( property.Get< bool >() );
2826 case Dali::Actor::Property::INHERIT_ORIENTATION:
2828 SetInheritOrientation( property.Get< bool >() );
2832 case Dali::Actor::Property::INHERIT_SCALE:
2834 SetInheritScale( property.Get< bool >() );
2838 case Dali::Actor::Property::COLOR_MODE:
2840 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2844 case Dali::Actor::Property::POSITION_INHERITANCE:
2846 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2850 case Dali::Actor::Property::DRAW_MODE:
2852 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2856 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2858 SetSizeModeFactor( property.Get< Vector3 >() );
2862 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2864 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2868 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2870 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2874 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2876 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2880 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2882 if( property.Get< bool >() )
2884 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2889 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2891 if( property.Get< bool >() )
2893 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2898 case Dali::Actor::Property::PADDING:
2900 Vector4 padding = property.Get< Vector4 >();
2901 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2902 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2906 case Dali::Actor::Property::MINIMUM_SIZE:
2908 Vector2 size = property.Get< Vector2 >();
2909 SetMinimumSize( size.x, Dimension::WIDTH );
2910 SetMinimumSize( size.y, Dimension::HEIGHT );
2914 case Dali::Actor::Property::MAXIMUM_SIZE:
2916 Vector2 size = property.Get< Vector2 >();
2917 SetMaximumSize( size.x, Dimension::WIDTH );
2918 SetMaximumSize( size.y, Dimension::HEIGHT );
2924 // this can happen in the case of a non-animatable default property so just do nothing
2930 // TODO: This method needs to be removed
2931 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2933 switch( entry.type )
2935 case Property::BOOLEAN:
2937 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( 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<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2946 case Property::INTEGER:
2948 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( 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<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2957 case Property::UNSIGNED_INTEGER:
2959 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( 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 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2968 case Property::FLOAT:
2970 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2971 DALI_ASSERT_DEBUG( NULL != property );
2973 // property is being used in a separate thread; queue a message to set the property
2974 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2979 case Property::VECTOR2:
2981 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( 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 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2990 case Property::VECTOR3:
2992 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2993 DALI_ASSERT_DEBUG( NULL != property );
2995 // property is being used in a separate thread; queue a message to set the property
2996 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3001 case Property::VECTOR4:
3003 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3004 DALI_ASSERT_DEBUG( NULL != property );
3006 // property is being used in a separate thread; queue a message to set the property
3007 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3012 case Property::ROTATION:
3014 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3015 DALI_ASSERT_DEBUG( NULL != property );
3017 // property is being used in a separate thread; queue a message to set the property
3018 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3023 case Property::MATRIX:
3025 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3026 DALI_ASSERT_DEBUG( NULL != property );
3028 // property is being used in a separate thread; queue a message to set the property
3029 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3034 case Property::MATRIX3:
3036 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3037 DALI_ASSERT_DEBUG( NULL != property );
3039 // property is being used in a separate thread; queue a message to set the property
3040 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3047 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3053 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3055 Property::Value value;
3059 case Dali::Actor::Property::PARENT_ORIGIN:
3061 value = GetCurrentParentOrigin();
3065 case Dali::Actor::Property::PARENT_ORIGIN_X:
3067 value = GetCurrentParentOrigin().x;
3071 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3073 value = GetCurrentParentOrigin().y;
3077 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3079 value = GetCurrentParentOrigin().z;
3083 case Dali::Actor::Property::ANCHOR_POINT:
3085 value = GetCurrentAnchorPoint();
3089 case Dali::Actor::Property::ANCHOR_POINT_X:
3091 value = GetCurrentAnchorPoint().x;
3095 case Dali::Actor::Property::ANCHOR_POINT_Y:
3097 value = GetCurrentAnchorPoint().y;
3101 case Dali::Actor::Property::ANCHOR_POINT_Z:
3103 value = GetCurrentAnchorPoint().z;
3107 case Dali::Actor::Property::SIZE:
3109 value = GetCurrentSize();
3113 case Dali::Actor::Property::SIZE_WIDTH:
3115 value = GetCurrentSize().width;
3119 case Dali::Actor::Property::SIZE_HEIGHT:
3121 value = GetCurrentSize().height;
3125 case Dali::Actor::Property::SIZE_DEPTH:
3127 value = GetCurrentSize().depth;
3131 case Dali::Actor::Property::POSITION:
3133 value = GetCurrentPosition();
3137 case Dali::Actor::Property::POSITION_X:
3139 value = GetCurrentPosition().x;
3143 case Dali::Actor::Property::POSITION_Y:
3145 value = GetCurrentPosition().y;
3149 case Dali::Actor::Property::POSITION_Z:
3151 value = GetCurrentPosition().z;
3155 case Dali::Actor::Property::WORLD_POSITION:
3157 value = GetCurrentWorldPosition();
3161 case Dali::Actor::Property::WORLD_POSITION_X:
3163 value = GetCurrentWorldPosition().x;
3167 case Dali::Actor::Property::WORLD_POSITION_Y:
3169 value = GetCurrentWorldPosition().y;
3173 case Dali::Actor::Property::WORLD_POSITION_Z:
3175 value = GetCurrentWorldPosition().z;
3179 case Dali::Actor::Property::ORIENTATION:
3181 value = GetCurrentOrientation();
3185 case Dali::Actor::Property::WORLD_ORIENTATION:
3187 value = GetCurrentWorldOrientation();
3191 case Dali::Actor::Property::SCALE:
3193 value = GetCurrentScale();
3197 case Dali::Actor::Property::SCALE_X:
3199 value = GetCurrentScale().x;
3203 case Dali::Actor::Property::SCALE_Y:
3205 value = GetCurrentScale().y;
3209 case Dali::Actor::Property::SCALE_Z:
3211 value = GetCurrentScale().z;
3215 case Dali::Actor::Property::WORLD_SCALE:
3217 value = GetCurrentWorldScale();
3221 case Dali::Actor::Property::VISIBLE:
3223 value = IsVisible();
3227 case Dali::Actor::Property::COLOR:
3229 value = GetCurrentColor();
3233 case Dali::Actor::Property::COLOR_RED:
3235 value = GetCurrentColor().r;
3239 case Dali::Actor::Property::COLOR_GREEN:
3241 value = GetCurrentColor().g;
3245 case Dali::Actor::Property::COLOR_BLUE:
3247 value = GetCurrentColor().b;
3251 case Dali::Actor::Property::COLOR_ALPHA:
3253 value = GetCurrentColor().a;
3257 case Dali::Actor::Property::WORLD_COLOR:
3259 value = GetCurrentWorldColor();
3263 case Dali::Actor::Property::WORLD_MATRIX:
3265 value = GetCurrentWorldMatrix();
3269 case Dali::Actor::Property::NAME:
3275 case Dali::Actor::Property::SENSITIVE:
3277 value = IsSensitive();
3281 case Dali::Actor::Property::LEAVE_REQUIRED:
3283 value = GetLeaveRequired();
3287 case Dali::Actor::Property::INHERIT_ORIENTATION:
3289 value = IsOrientationInherited();
3293 case Dali::Actor::Property::INHERIT_SCALE:
3295 value = IsScaleInherited();
3299 case Dali::Actor::Property::COLOR_MODE:
3301 value = Scripting::GetColorMode( GetColorMode() );
3305 case Dali::Actor::Property::POSITION_INHERITANCE:
3307 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3311 case Dali::Actor::Property::DRAW_MODE:
3313 value = Scripting::GetDrawMode( GetDrawMode() );
3317 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3319 value = GetSizeModeFactor();
3323 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3325 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3329 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3331 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3335 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3337 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3341 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3343 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3347 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3349 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3353 case Dali::Actor::Property::PADDING:
3355 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3356 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3357 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3361 case Dali::Actor::Property::MINIMUM_SIZE:
3363 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3367 case Dali::Actor::Property::MAXIMUM_SIZE:
3369 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3375 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3383 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3388 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3390 // This method should only return an object connected to the scene-graph
3391 return OnStage() ? mNode : NULL;
3394 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3396 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3398 const PropertyBase* property( NULL );
3400 // This method should only return a property of an object connected to the scene-graph
3406 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3408 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3411 const TypeInfo* typeInfo( GetTypeInfo() );
3414 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3416 animatable = FindAnimatableProperty( index );
3420 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3422 property = animatable->GetSceneGraphProperty();
3424 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3426 CustomPropertyMetadata* custom = FindCustomProperty( index );
3427 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3429 property = custom->GetSceneGraphProperty();
3431 else if( NULL != mNode )
3435 case Dali::Actor::Property::SIZE:
3436 property = &mNode->mSize;
3439 case Dali::Actor::Property::SIZE_WIDTH:
3440 property = &mNode->mSize;
3443 case Dali::Actor::Property::SIZE_HEIGHT:
3444 property = &mNode->mSize;
3447 case Dali::Actor::Property::SIZE_DEPTH:
3448 property = &mNode->mSize;
3451 case Dali::Actor::Property::POSITION:
3452 property = &mNode->mPosition;
3455 case Dali::Actor::Property::POSITION_X:
3456 property = &mNode->mPosition;
3459 case Dali::Actor::Property::POSITION_Y:
3460 property = &mNode->mPosition;
3463 case Dali::Actor::Property::POSITION_Z:
3464 property = &mNode->mPosition;
3467 case Dali::Actor::Property::ORIENTATION:
3468 property = &mNode->mOrientation;
3471 case Dali::Actor::Property::SCALE:
3472 property = &mNode->mScale;
3475 case Dali::Actor::Property::SCALE_X:
3476 property = &mNode->mScale;
3479 case Dali::Actor::Property::SCALE_Y:
3480 property = &mNode->mScale;
3483 case Dali::Actor::Property::SCALE_Z:
3484 property = &mNode->mScale;
3487 case Dali::Actor::Property::VISIBLE:
3488 property = &mNode->mVisible;
3491 case Dali::Actor::Property::COLOR:
3492 property = &mNode->mColor;
3495 case Dali::Actor::Property::COLOR_RED:
3496 property = &mNode->mColor;
3499 case Dali::Actor::Property::COLOR_GREEN:
3500 property = &mNode->mColor;
3503 case Dali::Actor::Property::COLOR_BLUE:
3504 property = &mNode->mColor;
3507 case Dali::Actor::Property::COLOR_ALPHA:
3508 property = &mNode->mColor;
3519 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3521 const PropertyInputImpl* property( NULL );
3523 // This method should only return a property of an object connected to the scene-graph
3529 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3531 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3534 const TypeInfo* typeInfo( GetTypeInfo() );
3537 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3539 animatable = FindAnimatableProperty( index );
3543 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3545 property = animatable->GetSceneGraphProperty();
3547 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3549 CustomPropertyMetadata* custom = FindCustomProperty( index );
3550 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3551 property = custom->GetSceneGraphProperty();
3553 else if( NULL != mNode )
3557 case Dali::Actor::Property::PARENT_ORIGIN:
3558 property = &mNode->mParentOrigin;
3561 case Dali::Actor::Property::PARENT_ORIGIN_X:
3562 property = &mNode->mParentOrigin;
3565 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3566 property = &mNode->mParentOrigin;
3569 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3570 property = &mNode->mParentOrigin;
3573 case Dali::Actor::Property::ANCHOR_POINT:
3574 property = &mNode->mAnchorPoint;
3577 case Dali::Actor::Property::ANCHOR_POINT_X:
3578 property = &mNode->mAnchorPoint;
3581 case Dali::Actor::Property::ANCHOR_POINT_Y:
3582 property = &mNode->mAnchorPoint;
3585 case Dali::Actor::Property::ANCHOR_POINT_Z:
3586 property = &mNode->mAnchorPoint;
3589 case Dali::Actor::Property::SIZE:
3590 property = &mNode->mSize;
3593 case Dali::Actor::Property::SIZE_WIDTH:
3594 property = &mNode->mSize;
3597 case Dali::Actor::Property::SIZE_HEIGHT:
3598 property = &mNode->mSize;
3601 case Dali::Actor::Property::SIZE_DEPTH:
3602 property = &mNode->mSize;
3605 case Dali::Actor::Property::POSITION:
3606 property = &mNode->mPosition;
3609 case Dali::Actor::Property::POSITION_X:
3610 property = &mNode->mPosition;
3613 case Dali::Actor::Property::POSITION_Y:
3614 property = &mNode->mPosition;
3617 case Dali::Actor::Property::POSITION_Z:
3618 property = &mNode->mPosition;
3621 case Dali::Actor::Property::WORLD_POSITION:
3622 property = &mNode->mWorldPosition;
3625 case Dali::Actor::Property::WORLD_POSITION_X:
3626 property = &mNode->mWorldPosition;
3629 case Dali::Actor::Property::WORLD_POSITION_Y:
3630 property = &mNode->mWorldPosition;
3633 case Dali::Actor::Property::WORLD_POSITION_Z:
3634 property = &mNode->mWorldPosition;
3637 case Dali::Actor::Property::ORIENTATION:
3638 property = &mNode->mOrientation;
3641 case Dali::Actor::Property::WORLD_ORIENTATION:
3642 property = &mNode->mWorldOrientation;
3645 case Dali::Actor::Property::SCALE:
3646 property = &mNode->mScale;
3649 case Dali::Actor::Property::SCALE_X:
3650 property = &mNode->mScale;
3653 case Dali::Actor::Property::SCALE_Y:
3654 property = &mNode->mScale;
3657 case Dali::Actor::Property::SCALE_Z:
3658 property = &mNode->mScale;
3661 case Dali::Actor::Property::WORLD_SCALE:
3662 property = &mNode->mWorldScale;
3665 case Dali::Actor::Property::VISIBLE:
3666 property = &mNode->mVisible;
3669 case Dali::Actor::Property::COLOR:
3670 property = &mNode->mColor;
3673 case Dali::Actor::Property::COLOR_RED:
3674 property = &mNode->mColor;
3677 case Dali::Actor::Property::COLOR_GREEN:
3678 property = &mNode->mColor;
3681 case Dali::Actor::Property::COLOR_BLUE:
3682 property = &mNode->mColor;
3685 case Dali::Actor::Property::COLOR_ALPHA:
3686 property = &mNode->mColor;
3689 case Dali::Actor::Property::WORLD_COLOR:
3690 property = &mNode->mWorldColor;
3693 case Dali::Actor::Property::WORLD_MATRIX:
3694 property = &mNode->mWorldMatrix;
3705 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3707 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3711 case Dali::Actor::Property::PARENT_ORIGIN_X:
3712 case Dali::Actor::Property::ANCHOR_POINT_X:
3713 case Dali::Actor::Property::SIZE_WIDTH:
3714 case Dali::Actor::Property::POSITION_X:
3715 case Dali::Actor::Property::WORLD_POSITION_X:
3716 case Dali::Actor::Property::SCALE_X:
3717 case Dali::Actor::Property::COLOR_RED:
3723 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3724 case Dali::Actor::Property::ANCHOR_POINT_Y:
3725 case Dali::Actor::Property::SIZE_HEIGHT:
3726 case Dali::Actor::Property::POSITION_Y:
3727 case Dali::Actor::Property::WORLD_POSITION_Y:
3728 case Dali::Actor::Property::SCALE_Y:
3729 case Dali::Actor::Property::COLOR_GREEN:
3735 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3736 case Dali::Actor::Property::ANCHOR_POINT_Z:
3737 case Dali::Actor::Property::SIZE_DEPTH:
3738 case Dali::Actor::Property::POSITION_Z:
3739 case Dali::Actor::Property::WORLD_POSITION_Z:
3740 case Dali::Actor::Property::SCALE_Z:
3741 case Dali::Actor::Property::COLOR_BLUE:
3747 case Dali::Actor::Property::COLOR_ALPHA:
3760 return componentIndex;
3763 void Actor::SetParent( Actor* parent, int index )
3767 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3771 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3774 // Instruct each actor to create a corresponding node in the scene graph
3775 ConnectToStage( index );
3778 else // parent being set to NULL
3780 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3784 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3787 DALI_ASSERT_ALWAYS( mNode != NULL );
3791 // Disconnect the Node & its children from the scene-graph.
3792 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3795 // Instruct each actor to discard pointers to the scene-graph
3796 DisconnectFromStage();
3801 SceneGraph::Node* Actor::CreateNode() const
3806 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3809 Actor* actor = dynamic_cast< Actor* >( object );
3813 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3815 actor->SetVisible( true );
3818 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3820 actor->SetVisible( false );
3828 void Actor::EnsureRelayoutData() const
3830 // Assign relayout data.
3831 if( !mRelayoutData )
3833 mRelayoutData = new RelayoutData();
3837 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3839 // Check if actor is dependent on parent
3840 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3842 if( ( dimension & ( 1 << i ) ) )
3844 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3845 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3855 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3857 // Check if actor is dependent on children
3858 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3860 if( ( dimension & ( 1 << i ) ) )
3862 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3863 switch( resizePolicy )
3865 case ResizePolicy::FIT_TO_CHILDREN:
3866 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3882 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3884 return Actor::RelayoutDependentOnChildren( dimension );
3887 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3889 // Check each possible dimension and see if it is dependent on the input one
3890 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3892 if( dimension & ( 1 << i ) )
3894 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3901 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3903 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3905 if( dimension & ( 1 << i ) )
3907 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3912 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3914 // If more than one dimension is requested, just return the first one found
3915 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3917 if( ( dimension & ( 1 << i ) ) )
3919 return mRelayoutData->negotiatedDimensions[ i ];
3923 return 0.0f; // Default
3926 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3928 EnsureRelayoutData();
3930 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3932 if( dimension & ( 1 << i ) )
3934 mRelayoutData->dimensionPadding[ i ] = padding;
3939 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3941 EnsureRelayoutData();
3943 // If more than one dimension is requested, just return the first one found
3944 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3946 if( ( dimension & ( 1 << i ) ) )
3948 return mRelayoutData->dimensionPadding[ i ];
3952 return Vector2( 0.0f, 0.0f ); // Default
3955 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3957 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3959 if( dimension & ( 1 << i ) )
3961 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3966 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3968 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3970 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3979 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3981 // Could be overridden in derived classes.
3982 return CalculateChildSizeBase( child, dimension );
3985 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3987 // Fill to parent, taking size mode factor into account
3988 switch( child.GetResizePolicy( dimension ) )
3990 case ResizePolicy::FILL_TO_PARENT:
3992 return GetLatestSize( dimension );
3995 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3997 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4000 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4002 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4007 return GetLatestSize( dimension );
4012 float Actor::GetHeightForWidth( float width )
4014 // Could be overridden in derived classes.
4015 float height = 0.0f;
4017 const Vector3 naturalSize = GetNaturalSize();
4018 if( naturalSize.width > 0.0f )
4020 height = naturalSize.height * width / naturalSize.width;
4026 float Actor::GetWidthForHeight( float height )
4028 // Could be overridden in derived classes.
4031 const Vector3 naturalSize = GetNaturalSize();
4032 if( naturalSize.height > 0.0f )
4034 width = naturalSize.width * height / naturalSize.height;
4040 float Actor::GetLatestSize( Dimension::Type dimension ) const
4042 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4045 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4047 Vector2 padding = GetPadding( dimension );
4049 return GetLatestSize( dimension ) + padding.x + padding.y;
4052 float Actor::NegotiateFromParent( Dimension::Type dimension )
4054 Actor* parent = GetParent();
4057 Vector2 padding( GetPadding( dimension ) );
4058 Vector2 parentPadding( parent->GetPadding( dimension ) );
4059 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4065 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4067 float maxDimensionPoint = 0.0f;
4069 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4071 Dali::Actor child = GetChildAt( i );
4072 Actor& childImpl = GetImplementation( child );
4074 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4076 // Calculate the min and max points that the children range across
4077 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4078 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4079 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4083 return maxDimensionPoint;
4086 float Actor::GetSize( Dimension::Type dimension ) const
4088 return GetDimensionValue( GetTargetSize(), dimension );
4091 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4093 return GetDimensionValue( GetNaturalSize(), dimension );
4096 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4098 switch( GetResizePolicy( dimension ) )
4100 case ResizePolicy::USE_NATURAL_SIZE:
4102 return GetNaturalSize( dimension );
4105 case ResizePolicy::FIXED:
4107 return GetDimensionValue( GetPreferredSize(), dimension );
4110 case ResizePolicy::USE_ASSIGNED_SIZE:
4112 return GetDimensionValue( maximumSize, dimension );
4115 case ResizePolicy::FILL_TO_PARENT:
4116 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4117 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4119 return NegotiateFromParent( dimension );
4122 case ResizePolicy::FIT_TO_CHILDREN:
4124 return NegotiateFromChildren( dimension );
4127 case ResizePolicy::DIMENSION_DEPENDENCY:
4129 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4132 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4134 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4137 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4139 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4151 return 0.0f; // Default
4154 float Actor::ClampDimension( float size, Dimension::Type dimension )
4156 const float minSize = GetMinimumSize( dimension );
4157 const float maxSize = GetMaximumSize( dimension );
4159 return std::max( minSize, std::min( size, maxSize ) );
4162 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4164 // Check if it needs to be negotiated
4165 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4167 // Check that we havn't gotten into an infinite loop
4168 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4169 bool recursionFound = false;
4170 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4172 if( *it == searchActor )
4174 recursionFound = true;
4179 if( !recursionFound )
4181 // Record the path that we have taken
4182 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4184 // Dimension dependency check
4185 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4187 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4189 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4191 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4195 // Parent dependency check
4196 Actor* parent = GetParent();
4197 if( parent && RelayoutDependentOnParent( dimension ) )
4199 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4202 // Children dependency check
4203 if( RelayoutDependentOnChildren( dimension ) )
4205 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4207 Dali::Actor child = GetChildAt( i );
4208 Actor& childImpl = GetImplementation( child );
4210 // Only relayout child first if it is not dependent on this actor
4211 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4213 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4218 // For deriving classes
4219 OnCalculateRelayoutSize( dimension );
4221 // All dependencies checked, calculate the size and set negotiated flag
4222 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4224 SetNegotiatedDimension( newSize, dimension );
4225 SetLayoutNegotiated( true, dimension );
4227 // For deriving classes
4228 OnLayoutNegotiated( newSize, dimension );
4230 // This actor has been successfully processed, pop it off the recursion stack
4231 recursionStack.pop_back();
4235 // TODO: Break infinite loop
4236 SetLayoutNegotiated( true, dimension );
4241 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4243 // Negotiate all dimensions that require it
4244 ActorDimensionStack recursionStack;
4246 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4248 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4251 NegotiateDimension( dimension, allocatedSize, recursionStack );
4255 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4257 switch( mRelayoutData->sizeSetPolicy )
4259 case SizeScalePolicy::USE_SIZE_SET:
4264 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4266 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4267 const Vector3 naturalSize = GetNaturalSize();
4268 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4270 const float sizeRatio = size.width / size.height;
4271 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4273 if( naturalSizeRatio < sizeRatio )
4275 return Vector2( naturalSizeRatio * size.height, size.height );
4277 else if( naturalSizeRatio > sizeRatio )
4279 return Vector2( size.width, size.width / naturalSizeRatio );
4290 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4292 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4293 const Vector3 naturalSize = GetNaturalSize();
4294 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4296 const float sizeRatio = size.width / size.height;
4297 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4299 if( naturalSizeRatio < sizeRatio )
4301 return Vector2( size.width, size.width / naturalSizeRatio );
4303 else if( naturalSizeRatio > sizeRatio )
4305 return Vector2( naturalSizeRatio * size.height, size.height );
4323 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4325 // Do the set actor size
4326 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4328 // Adjust for size set policy
4329 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4331 // Lock the flag to stop recursive relayouts on set size
4332 mRelayoutData->insideRelayout = true;
4333 SetSize( negotiatedSize );
4334 mRelayoutData->insideRelayout = false;
4336 // Clear flags for all dimensions
4337 SetLayoutDirty( false );
4339 // Give deriving classes a chance to respond
4340 OnRelayout( negotiatedSize, container );
4342 if( !mOnRelayoutSignal.Empty() )
4344 Dali::Actor handle( this );
4345 mOnRelayoutSignal.Emit( handle );
4349 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4351 // Do the negotiation
4352 NegotiateDimensions( allocatedSize );
4354 // Set the actor size
4355 SetNegotiatedSize( container );
4357 // Negotiate down to children
4358 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4360 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4362 Dali::Actor child = GetChildAt( i );
4364 // Only relayout if required
4365 if( GetImplementation( child ).RelayoutRequired() )
4367 container.Add( child, newBounds );
4372 void Actor::RelayoutRequest( Dimension::Type dimension )
4374 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4375 if( relayoutController )
4377 Dali::Actor self( this );
4378 relayoutController->RequestRelayout( self, dimension );
4382 void Actor::PropagateRelayoutFlags()
4384 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4385 if( relayoutController )
4387 Dali::Actor self( this );
4388 relayoutController->PropagateFlags( self );
4392 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4396 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4400 void Actor::SetPreferredSize( const Vector2& size )
4402 EnsureRelayoutData();
4404 if( size.width > 0.0f )
4406 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4409 if( size.height > 0.0f )
4411 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4414 mRelayoutData->preferredSize = size;
4419 Vector2 Actor::GetPreferredSize() const
4421 EnsureRelayoutData();
4423 return mRelayoutData->preferredSize;
4426 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4428 EnsureRelayoutData();
4430 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4432 if( dimension & ( 1 << i ) )
4434 mRelayoutData->minimumSize[ i ] = size;
4441 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4443 EnsureRelayoutData();
4445 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4447 if( dimension & ( 1 << i ) )
4449 return mRelayoutData->minimumSize[ i ];
4453 return 0.0f; // Default
4456 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4458 EnsureRelayoutData();
4460 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4462 if( dimension & ( 1 << i ) )
4464 mRelayoutData->maximumSize[ i ] = size;
4471 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4473 EnsureRelayoutData();
4475 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4477 if( dimension & ( 1 << i ) )
4479 return mRelayoutData->maximumSize[ i ];
4483 return 0.0f; // Default
4486 } // namespace Internal