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 OnPropertySet( index, value );
2935 switch( entry.type )
2937 case Property::BOOLEAN:
2939 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2940 DALI_ASSERT_DEBUG( NULL != property );
2942 // property is being used in a separate thread; queue a message to set the property
2943 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2948 case Property::INTEGER:
2950 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2951 DALI_ASSERT_DEBUG( NULL != property );
2953 // property is being used in a separate thread; queue a message to set the property
2954 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2959 case Property::UNSIGNED_INTEGER:
2961 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2962 DALI_ASSERT_DEBUG( NULL != property );
2964 // property is being used in a separate thread; queue a message to set the property
2965 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2970 case Property::FLOAT:
2972 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2973 DALI_ASSERT_DEBUG( NULL != property );
2975 // property is being used in a separate thread; queue a message to set the property
2976 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2981 case Property::VECTOR2:
2983 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2984 DALI_ASSERT_DEBUG( NULL != property );
2986 // property is being used in a separate thread; queue a message to set the property
2987 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2992 case Property::VECTOR3:
2994 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2995 DALI_ASSERT_DEBUG( NULL != property );
2997 // property is being used in a separate thread; queue a message to set the property
2998 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3003 case Property::VECTOR4:
3005 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3006 DALI_ASSERT_DEBUG( NULL != property );
3008 // property is being used in a separate thread; queue a message to set the property
3009 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3014 case Property::ROTATION:
3016 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3017 DALI_ASSERT_DEBUG( NULL != property );
3019 // property is being used in a separate thread; queue a message to set the property
3020 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3025 case Property::MATRIX:
3027 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3028 DALI_ASSERT_DEBUG( NULL != property );
3030 // property is being used in a separate thread; queue a message to set the property
3031 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3036 case Property::MATRIX3:
3038 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3039 DALI_ASSERT_DEBUG( NULL != property );
3041 // property is being used in a separate thread; queue a message to set the property
3042 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3049 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3055 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3057 Property::Value value;
3061 case Dali::Actor::Property::PARENT_ORIGIN:
3063 value = GetCurrentParentOrigin();
3067 case Dali::Actor::Property::PARENT_ORIGIN_X:
3069 value = GetCurrentParentOrigin().x;
3073 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3075 value = GetCurrentParentOrigin().y;
3079 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3081 value = GetCurrentParentOrigin().z;
3085 case Dali::Actor::Property::ANCHOR_POINT:
3087 value = GetCurrentAnchorPoint();
3091 case Dali::Actor::Property::ANCHOR_POINT_X:
3093 value = GetCurrentAnchorPoint().x;
3097 case Dali::Actor::Property::ANCHOR_POINT_Y:
3099 value = GetCurrentAnchorPoint().y;
3103 case Dali::Actor::Property::ANCHOR_POINT_Z:
3105 value = GetCurrentAnchorPoint().z;
3109 case Dali::Actor::Property::SIZE:
3111 value = GetCurrentSize();
3115 case Dali::Actor::Property::SIZE_WIDTH:
3117 value = GetCurrentSize().width;
3121 case Dali::Actor::Property::SIZE_HEIGHT:
3123 value = GetCurrentSize().height;
3127 case Dali::Actor::Property::SIZE_DEPTH:
3129 value = GetCurrentSize().depth;
3133 case Dali::Actor::Property::POSITION:
3135 value = GetCurrentPosition();
3139 case Dali::Actor::Property::POSITION_X:
3141 value = GetCurrentPosition().x;
3145 case Dali::Actor::Property::POSITION_Y:
3147 value = GetCurrentPosition().y;
3151 case Dali::Actor::Property::POSITION_Z:
3153 value = GetCurrentPosition().z;
3157 case Dali::Actor::Property::WORLD_POSITION:
3159 value = GetCurrentWorldPosition();
3163 case Dali::Actor::Property::WORLD_POSITION_X:
3165 value = GetCurrentWorldPosition().x;
3169 case Dali::Actor::Property::WORLD_POSITION_Y:
3171 value = GetCurrentWorldPosition().y;
3175 case Dali::Actor::Property::WORLD_POSITION_Z:
3177 value = GetCurrentWorldPosition().z;
3181 case Dali::Actor::Property::ORIENTATION:
3183 value = GetCurrentOrientation();
3187 case Dali::Actor::Property::WORLD_ORIENTATION:
3189 value = GetCurrentWorldOrientation();
3193 case Dali::Actor::Property::SCALE:
3195 value = GetCurrentScale();
3199 case Dali::Actor::Property::SCALE_X:
3201 value = GetCurrentScale().x;
3205 case Dali::Actor::Property::SCALE_Y:
3207 value = GetCurrentScale().y;
3211 case Dali::Actor::Property::SCALE_Z:
3213 value = GetCurrentScale().z;
3217 case Dali::Actor::Property::WORLD_SCALE:
3219 value = GetCurrentWorldScale();
3223 case Dali::Actor::Property::VISIBLE:
3225 value = IsVisible();
3229 case Dali::Actor::Property::COLOR:
3231 value = GetCurrentColor();
3235 case Dali::Actor::Property::COLOR_RED:
3237 value = GetCurrentColor().r;
3241 case Dali::Actor::Property::COLOR_GREEN:
3243 value = GetCurrentColor().g;
3247 case Dali::Actor::Property::COLOR_BLUE:
3249 value = GetCurrentColor().b;
3253 case Dali::Actor::Property::COLOR_ALPHA:
3255 value = GetCurrentColor().a;
3259 case Dali::Actor::Property::WORLD_COLOR:
3261 value = GetCurrentWorldColor();
3265 case Dali::Actor::Property::WORLD_MATRIX:
3267 value = GetCurrentWorldMatrix();
3271 case Dali::Actor::Property::NAME:
3277 case Dali::Actor::Property::SENSITIVE:
3279 value = IsSensitive();
3283 case Dali::Actor::Property::LEAVE_REQUIRED:
3285 value = GetLeaveRequired();
3289 case Dali::Actor::Property::INHERIT_ORIENTATION:
3291 value = IsOrientationInherited();
3295 case Dali::Actor::Property::INHERIT_SCALE:
3297 value = IsScaleInherited();
3301 case Dali::Actor::Property::COLOR_MODE:
3303 value = Scripting::GetColorMode( GetColorMode() );
3307 case Dali::Actor::Property::POSITION_INHERITANCE:
3309 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3313 case Dali::Actor::Property::DRAW_MODE:
3315 value = Scripting::GetDrawMode( GetDrawMode() );
3319 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3321 value = GetSizeModeFactor();
3325 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3327 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3331 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3333 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3337 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3339 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3343 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3345 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3349 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3351 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3355 case Dali::Actor::Property::PADDING:
3357 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3358 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3359 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3363 case Dali::Actor::Property::MINIMUM_SIZE:
3365 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3369 case Dali::Actor::Property::MAXIMUM_SIZE:
3371 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3377 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3385 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3390 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3392 // This method should only return an object connected to the scene-graph
3393 return OnStage() ? mNode : NULL;
3396 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3398 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3400 const PropertyBase* property( NULL );
3402 // This method should only return a property of an object connected to the scene-graph
3408 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3410 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3413 const TypeInfo* typeInfo( GetTypeInfo() );
3416 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3418 animatable = FindAnimatableProperty( index );
3422 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3424 property = animatable->GetSceneGraphProperty();
3426 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3428 CustomPropertyMetadata* custom = FindCustomProperty( index );
3429 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3431 property = custom->GetSceneGraphProperty();
3433 else if( NULL != mNode )
3437 case Dali::Actor::Property::SIZE:
3438 property = &mNode->mSize;
3441 case Dali::Actor::Property::SIZE_WIDTH:
3442 property = &mNode->mSize;
3445 case Dali::Actor::Property::SIZE_HEIGHT:
3446 property = &mNode->mSize;
3449 case Dali::Actor::Property::SIZE_DEPTH:
3450 property = &mNode->mSize;
3453 case Dali::Actor::Property::POSITION:
3454 property = &mNode->mPosition;
3457 case Dali::Actor::Property::POSITION_X:
3458 property = &mNode->mPosition;
3461 case Dali::Actor::Property::POSITION_Y:
3462 property = &mNode->mPosition;
3465 case Dali::Actor::Property::POSITION_Z:
3466 property = &mNode->mPosition;
3469 case Dali::Actor::Property::ORIENTATION:
3470 property = &mNode->mOrientation;
3473 case Dali::Actor::Property::SCALE:
3474 property = &mNode->mScale;
3477 case Dali::Actor::Property::SCALE_X:
3478 property = &mNode->mScale;
3481 case Dali::Actor::Property::SCALE_Y:
3482 property = &mNode->mScale;
3485 case Dali::Actor::Property::SCALE_Z:
3486 property = &mNode->mScale;
3489 case Dali::Actor::Property::VISIBLE:
3490 property = &mNode->mVisible;
3493 case Dali::Actor::Property::COLOR:
3494 property = &mNode->mColor;
3497 case Dali::Actor::Property::COLOR_RED:
3498 property = &mNode->mColor;
3501 case Dali::Actor::Property::COLOR_GREEN:
3502 property = &mNode->mColor;
3505 case Dali::Actor::Property::COLOR_BLUE:
3506 property = &mNode->mColor;
3509 case Dali::Actor::Property::COLOR_ALPHA:
3510 property = &mNode->mColor;
3521 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3523 const PropertyInputImpl* property( NULL );
3525 // This method should only return a property of an object connected to the scene-graph
3531 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3533 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3536 const TypeInfo* typeInfo( GetTypeInfo() );
3539 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3541 animatable = FindAnimatableProperty( index );
3545 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3547 property = animatable->GetSceneGraphProperty();
3549 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3551 CustomPropertyMetadata* custom = FindCustomProperty( index );
3552 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3553 property = custom->GetSceneGraphProperty();
3555 else if( NULL != mNode )
3559 case Dali::Actor::Property::PARENT_ORIGIN:
3560 property = &mNode->mParentOrigin;
3563 case Dali::Actor::Property::PARENT_ORIGIN_X:
3564 property = &mNode->mParentOrigin;
3567 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3568 property = &mNode->mParentOrigin;
3571 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3572 property = &mNode->mParentOrigin;
3575 case Dali::Actor::Property::ANCHOR_POINT:
3576 property = &mNode->mAnchorPoint;
3579 case Dali::Actor::Property::ANCHOR_POINT_X:
3580 property = &mNode->mAnchorPoint;
3583 case Dali::Actor::Property::ANCHOR_POINT_Y:
3584 property = &mNode->mAnchorPoint;
3587 case Dali::Actor::Property::ANCHOR_POINT_Z:
3588 property = &mNode->mAnchorPoint;
3591 case Dali::Actor::Property::SIZE:
3592 property = &mNode->mSize;
3595 case Dali::Actor::Property::SIZE_WIDTH:
3596 property = &mNode->mSize;
3599 case Dali::Actor::Property::SIZE_HEIGHT:
3600 property = &mNode->mSize;
3603 case Dali::Actor::Property::SIZE_DEPTH:
3604 property = &mNode->mSize;
3607 case Dali::Actor::Property::POSITION:
3608 property = &mNode->mPosition;
3611 case Dali::Actor::Property::POSITION_X:
3612 property = &mNode->mPosition;
3615 case Dali::Actor::Property::POSITION_Y:
3616 property = &mNode->mPosition;
3619 case Dali::Actor::Property::POSITION_Z:
3620 property = &mNode->mPosition;
3623 case Dali::Actor::Property::WORLD_POSITION:
3624 property = &mNode->mWorldPosition;
3627 case Dali::Actor::Property::WORLD_POSITION_X:
3628 property = &mNode->mWorldPosition;
3631 case Dali::Actor::Property::WORLD_POSITION_Y:
3632 property = &mNode->mWorldPosition;
3635 case Dali::Actor::Property::WORLD_POSITION_Z:
3636 property = &mNode->mWorldPosition;
3639 case Dali::Actor::Property::ORIENTATION:
3640 property = &mNode->mOrientation;
3643 case Dali::Actor::Property::WORLD_ORIENTATION:
3644 property = &mNode->mWorldOrientation;
3647 case Dali::Actor::Property::SCALE:
3648 property = &mNode->mScale;
3651 case Dali::Actor::Property::SCALE_X:
3652 property = &mNode->mScale;
3655 case Dali::Actor::Property::SCALE_Y:
3656 property = &mNode->mScale;
3659 case Dali::Actor::Property::SCALE_Z:
3660 property = &mNode->mScale;
3663 case Dali::Actor::Property::WORLD_SCALE:
3664 property = &mNode->mWorldScale;
3667 case Dali::Actor::Property::VISIBLE:
3668 property = &mNode->mVisible;
3671 case Dali::Actor::Property::COLOR:
3672 property = &mNode->mColor;
3675 case Dali::Actor::Property::COLOR_RED:
3676 property = &mNode->mColor;
3679 case Dali::Actor::Property::COLOR_GREEN:
3680 property = &mNode->mColor;
3683 case Dali::Actor::Property::COLOR_BLUE:
3684 property = &mNode->mColor;
3687 case Dali::Actor::Property::COLOR_ALPHA:
3688 property = &mNode->mColor;
3691 case Dali::Actor::Property::WORLD_COLOR:
3692 property = &mNode->mWorldColor;
3695 case Dali::Actor::Property::WORLD_MATRIX:
3696 property = &mNode->mWorldMatrix;
3707 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3709 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3713 case Dali::Actor::Property::PARENT_ORIGIN_X:
3714 case Dali::Actor::Property::ANCHOR_POINT_X:
3715 case Dali::Actor::Property::SIZE_WIDTH:
3716 case Dali::Actor::Property::POSITION_X:
3717 case Dali::Actor::Property::WORLD_POSITION_X:
3718 case Dali::Actor::Property::SCALE_X:
3719 case Dali::Actor::Property::COLOR_RED:
3725 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3726 case Dali::Actor::Property::ANCHOR_POINT_Y:
3727 case Dali::Actor::Property::SIZE_HEIGHT:
3728 case Dali::Actor::Property::POSITION_Y:
3729 case Dali::Actor::Property::WORLD_POSITION_Y:
3730 case Dali::Actor::Property::SCALE_Y:
3731 case Dali::Actor::Property::COLOR_GREEN:
3737 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3738 case Dali::Actor::Property::ANCHOR_POINT_Z:
3739 case Dali::Actor::Property::SIZE_DEPTH:
3740 case Dali::Actor::Property::POSITION_Z:
3741 case Dali::Actor::Property::WORLD_POSITION_Z:
3742 case Dali::Actor::Property::SCALE_Z:
3743 case Dali::Actor::Property::COLOR_BLUE:
3749 case Dali::Actor::Property::COLOR_ALPHA:
3762 return componentIndex;
3765 void Actor::SetParent( Actor* parent, int index )
3769 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3773 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3776 // Instruct each actor to create a corresponding node in the scene graph
3777 ConnectToStage( index );
3780 else // parent being set to NULL
3782 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3786 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3789 DALI_ASSERT_ALWAYS( mNode != NULL );
3793 // Disconnect the Node & its children from the scene-graph.
3794 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3797 // Instruct each actor to discard pointers to the scene-graph
3798 DisconnectFromStage();
3803 SceneGraph::Node* Actor::CreateNode() const
3808 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3811 Actor* actor = dynamic_cast< Actor* >( object );
3815 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3817 actor->SetVisible( true );
3820 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3822 actor->SetVisible( false );
3830 void Actor::EnsureRelayoutData() const
3832 // Assign relayout data.
3833 if( !mRelayoutData )
3835 mRelayoutData = new RelayoutData();
3839 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3841 // Check if actor is dependent on parent
3842 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3844 if( ( dimension & ( 1 << i ) ) )
3846 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3847 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3857 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3859 // Check if actor is dependent on children
3860 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3862 if( ( dimension & ( 1 << i ) ) )
3864 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3865 switch( resizePolicy )
3867 case ResizePolicy::FIT_TO_CHILDREN:
3868 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3884 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3886 return Actor::RelayoutDependentOnChildren( dimension );
3889 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3891 // Check each possible dimension and see if it is dependent on the input one
3892 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3894 if( dimension & ( 1 << i ) )
3896 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3903 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3905 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3907 if( dimension & ( 1 << i ) )
3909 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3914 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3916 // If more than one dimension is requested, just return the first one found
3917 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3919 if( ( dimension & ( 1 << i ) ) )
3921 return mRelayoutData->negotiatedDimensions[ i ];
3925 return 0.0f; // Default
3928 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3930 EnsureRelayoutData();
3932 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3934 if( dimension & ( 1 << i ) )
3936 mRelayoutData->dimensionPadding[ i ] = padding;
3941 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3943 EnsureRelayoutData();
3945 // If more than one dimension is requested, just return the first one found
3946 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3948 if( ( dimension & ( 1 << i ) ) )
3950 return mRelayoutData->dimensionPadding[ i ];
3954 return Vector2( 0.0f, 0.0f ); // Default
3957 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3959 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3961 if( dimension & ( 1 << i ) )
3963 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3968 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3970 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3972 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3981 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3983 // Could be overridden in derived classes.
3984 return CalculateChildSizeBase( child, dimension );
3987 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3989 // Fill to parent, taking size mode factor into account
3990 switch( child.GetResizePolicy( dimension ) )
3992 case ResizePolicy::FILL_TO_PARENT:
3994 return GetLatestSize( dimension );
3997 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3999 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4002 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4004 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4009 return GetLatestSize( dimension );
4014 float Actor::GetHeightForWidth( float width )
4016 // Could be overridden in derived classes.
4017 float height = 0.0f;
4019 const Vector3 naturalSize = GetNaturalSize();
4020 if( naturalSize.width > 0.0f )
4022 height = naturalSize.height * width / naturalSize.width;
4028 float Actor::GetWidthForHeight( float height )
4030 // Could be overridden in derived classes.
4033 const Vector3 naturalSize = GetNaturalSize();
4034 if( naturalSize.height > 0.0f )
4036 width = naturalSize.width * height / naturalSize.height;
4042 float Actor::GetLatestSize( Dimension::Type dimension ) const
4044 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4047 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4049 Vector2 padding = GetPadding( dimension );
4051 return GetLatestSize( dimension ) + padding.x + padding.y;
4054 float Actor::NegotiateFromParent( Dimension::Type dimension )
4056 Actor* parent = GetParent();
4059 Vector2 padding( GetPadding( dimension ) );
4060 Vector2 parentPadding( parent->GetPadding( dimension ) );
4061 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4067 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4069 float maxDimensionPoint = 0.0f;
4071 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4073 Dali::Actor child = GetChildAt( i );
4074 Actor& childImpl = GetImplementation( child );
4076 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4078 // Calculate the min and max points that the children range across
4079 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4080 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4081 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4085 return maxDimensionPoint;
4088 float Actor::GetSize( Dimension::Type dimension ) const
4090 return GetDimensionValue( GetTargetSize(), dimension );
4093 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4095 return GetDimensionValue( GetNaturalSize(), dimension );
4098 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4100 switch( GetResizePolicy( dimension ) )
4102 case ResizePolicy::USE_NATURAL_SIZE:
4104 return GetNaturalSize( dimension );
4107 case ResizePolicy::FIXED:
4109 return GetDimensionValue( GetPreferredSize(), dimension );
4112 case ResizePolicy::USE_ASSIGNED_SIZE:
4114 return GetDimensionValue( maximumSize, dimension );
4117 case ResizePolicy::FILL_TO_PARENT:
4118 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4119 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4121 return NegotiateFromParent( dimension );
4124 case ResizePolicy::FIT_TO_CHILDREN:
4126 return NegotiateFromChildren( dimension );
4129 case ResizePolicy::DIMENSION_DEPENDENCY:
4131 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4134 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4136 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4139 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4141 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4153 return 0.0f; // Default
4156 float Actor::ClampDimension( float size, Dimension::Type dimension )
4158 const float minSize = GetMinimumSize( dimension );
4159 const float maxSize = GetMaximumSize( dimension );
4161 return std::max( minSize, std::min( size, maxSize ) );
4164 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4166 // Check if it needs to be negotiated
4167 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4169 // Check that we havn't gotten into an infinite loop
4170 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4171 bool recursionFound = false;
4172 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4174 if( *it == searchActor )
4176 recursionFound = true;
4181 if( !recursionFound )
4183 // Record the path that we have taken
4184 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4186 // Dimension dependency check
4187 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4189 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4191 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4193 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4197 // Parent dependency check
4198 Actor* parent = GetParent();
4199 if( parent && RelayoutDependentOnParent( dimension ) )
4201 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4204 // Children dependency check
4205 if( RelayoutDependentOnChildren( dimension ) )
4207 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4209 Dali::Actor child = GetChildAt( i );
4210 Actor& childImpl = GetImplementation( child );
4212 // Only relayout child first if it is not dependent on this actor
4213 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4215 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4220 // For deriving classes
4221 OnCalculateRelayoutSize( dimension );
4223 // All dependencies checked, calculate the size and set negotiated flag
4224 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4226 SetNegotiatedDimension( newSize, dimension );
4227 SetLayoutNegotiated( true, dimension );
4229 // For deriving classes
4230 OnLayoutNegotiated( newSize, dimension );
4232 // This actor has been successfully processed, pop it off the recursion stack
4233 recursionStack.pop_back();
4237 // TODO: Break infinite loop
4238 SetLayoutNegotiated( true, dimension );
4243 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4245 // Negotiate all dimensions that require it
4246 ActorDimensionStack recursionStack;
4248 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4250 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4253 NegotiateDimension( dimension, allocatedSize, recursionStack );
4257 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4259 switch( mRelayoutData->sizeSetPolicy )
4261 case SizeScalePolicy::USE_SIZE_SET:
4266 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4268 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4269 const Vector3 naturalSize = GetNaturalSize();
4270 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4272 const float sizeRatio = size.width / size.height;
4273 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4275 if( naturalSizeRatio < sizeRatio )
4277 return Vector2( naturalSizeRatio * size.height, size.height );
4279 else if( naturalSizeRatio > sizeRatio )
4281 return Vector2( size.width, size.width / naturalSizeRatio );
4292 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4294 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4295 const Vector3 naturalSize = GetNaturalSize();
4296 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4298 const float sizeRatio = size.width / size.height;
4299 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4301 if( naturalSizeRatio < sizeRatio )
4303 return Vector2( size.width, size.width / naturalSizeRatio );
4305 else if( naturalSizeRatio > sizeRatio )
4307 return Vector2( naturalSizeRatio * size.height, size.height );
4325 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4327 // Do the set actor size
4328 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4330 // Adjust for size set policy
4331 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4333 // Lock the flag to stop recursive relayouts on set size
4334 mRelayoutData->insideRelayout = true;
4335 SetSize( negotiatedSize );
4336 mRelayoutData->insideRelayout = false;
4338 // Clear flags for all dimensions
4339 SetLayoutDirty( false );
4341 // Give deriving classes a chance to respond
4342 OnRelayout( negotiatedSize, container );
4344 if( !mOnRelayoutSignal.Empty() )
4346 Dali::Actor handle( this );
4347 mOnRelayoutSignal.Emit( handle );
4351 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4353 // Do the negotiation
4354 NegotiateDimensions( allocatedSize );
4356 // Set the actor size
4357 SetNegotiatedSize( container );
4359 // Negotiate down to children
4360 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4362 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4364 Dali::Actor child = GetChildAt( i );
4366 // Only relayout if required
4367 if( GetImplementation( child ).RelayoutRequired() )
4369 container.Add( child, newBounds );
4374 void Actor::RelayoutRequest( Dimension::Type dimension )
4376 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4377 if( relayoutController )
4379 Dali::Actor self( this );
4380 relayoutController->RequestRelayout( self, dimension );
4384 void Actor::PropagateRelayoutFlags()
4386 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4387 if( relayoutController )
4389 Dali::Actor self( this );
4390 relayoutController->PropagateFlags( self );
4394 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4398 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4402 void Actor::SetPreferredSize( const Vector2& size )
4404 EnsureRelayoutData();
4406 if( size.width > 0.0f )
4408 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4411 if( size.height > 0.0f )
4413 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4416 mRelayoutData->preferredSize = size;
4421 Vector2 Actor::GetPreferredSize() const
4423 EnsureRelayoutData();
4425 return mRelayoutData->preferredSize;
4428 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4430 EnsureRelayoutData();
4432 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4434 if( dimension & ( 1 << i ) )
4436 mRelayoutData->minimumSize[ i ] = size;
4443 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4445 EnsureRelayoutData();
4447 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4449 if( dimension & ( 1 << i ) )
4451 return mRelayoutData->minimumSize[ i ];
4455 return 0.0f; // Default
4458 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4460 EnsureRelayoutData();
4462 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4464 if( dimension & ( 1 << i ) )
4466 mRelayoutData->maximumSize[ i ] = size;
4473 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4475 EnsureRelayoutData();
4477 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4479 if( dimension & ( 1 << i ) )
4481 return mRelayoutData->maximumSize[ i ];
4485 return 0.0f; // Default
4488 } // namespace Internal