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::FLOAT:
2950 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2959 case Property::INTEGER:
2961 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< 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<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2970 case Property::VECTOR2:
2972 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( 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<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2981 case Property::VECTOR3:
2983 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( 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<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2992 case Property::VECTOR4:
2994 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( 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<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3003 case Property::ROTATION:
3005 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( 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<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3014 case Property::MATRIX:
3016 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( 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<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3025 case Property::MATRIX3:
3027 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( 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<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3038 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3044 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3046 Property::Value value;
3050 case Dali::Actor::Property::PARENT_ORIGIN:
3052 value = GetCurrentParentOrigin();
3056 case Dali::Actor::Property::PARENT_ORIGIN_X:
3058 value = GetCurrentParentOrigin().x;
3062 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3064 value = GetCurrentParentOrigin().y;
3068 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3070 value = GetCurrentParentOrigin().z;
3074 case Dali::Actor::Property::ANCHOR_POINT:
3076 value = GetCurrentAnchorPoint();
3080 case Dali::Actor::Property::ANCHOR_POINT_X:
3082 value = GetCurrentAnchorPoint().x;
3086 case Dali::Actor::Property::ANCHOR_POINT_Y:
3088 value = GetCurrentAnchorPoint().y;
3092 case Dali::Actor::Property::ANCHOR_POINT_Z:
3094 value = GetCurrentAnchorPoint().z;
3098 case Dali::Actor::Property::SIZE:
3100 value = GetCurrentSize();
3104 case Dali::Actor::Property::SIZE_WIDTH:
3106 value = GetCurrentSize().width;
3110 case Dali::Actor::Property::SIZE_HEIGHT:
3112 value = GetCurrentSize().height;
3116 case Dali::Actor::Property::SIZE_DEPTH:
3118 value = GetCurrentSize().depth;
3122 case Dali::Actor::Property::POSITION:
3124 value = GetCurrentPosition();
3128 case Dali::Actor::Property::POSITION_X:
3130 value = GetCurrentPosition().x;
3134 case Dali::Actor::Property::POSITION_Y:
3136 value = GetCurrentPosition().y;
3140 case Dali::Actor::Property::POSITION_Z:
3142 value = GetCurrentPosition().z;
3146 case Dali::Actor::Property::WORLD_POSITION:
3148 value = GetCurrentWorldPosition();
3152 case Dali::Actor::Property::WORLD_POSITION_X:
3154 value = GetCurrentWorldPosition().x;
3158 case Dali::Actor::Property::WORLD_POSITION_Y:
3160 value = GetCurrentWorldPosition().y;
3164 case Dali::Actor::Property::WORLD_POSITION_Z:
3166 value = GetCurrentWorldPosition().z;
3170 case Dali::Actor::Property::ORIENTATION:
3172 value = GetCurrentOrientation();
3176 case Dali::Actor::Property::WORLD_ORIENTATION:
3178 value = GetCurrentWorldOrientation();
3182 case Dali::Actor::Property::SCALE:
3184 value = GetCurrentScale();
3188 case Dali::Actor::Property::SCALE_X:
3190 value = GetCurrentScale().x;
3194 case Dali::Actor::Property::SCALE_Y:
3196 value = GetCurrentScale().y;
3200 case Dali::Actor::Property::SCALE_Z:
3202 value = GetCurrentScale().z;
3206 case Dali::Actor::Property::WORLD_SCALE:
3208 value = GetCurrentWorldScale();
3212 case Dali::Actor::Property::VISIBLE:
3214 value = IsVisible();
3218 case Dali::Actor::Property::COLOR:
3220 value = GetCurrentColor();
3224 case Dali::Actor::Property::COLOR_RED:
3226 value = GetCurrentColor().r;
3230 case Dali::Actor::Property::COLOR_GREEN:
3232 value = GetCurrentColor().g;
3236 case Dali::Actor::Property::COLOR_BLUE:
3238 value = GetCurrentColor().b;
3242 case Dali::Actor::Property::COLOR_ALPHA:
3244 value = GetCurrentColor().a;
3248 case Dali::Actor::Property::WORLD_COLOR:
3250 value = GetCurrentWorldColor();
3254 case Dali::Actor::Property::WORLD_MATRIX:
3256 value = GetCurrentWorldMatrix();
3260 case Dali::Actor::Property::NAME:
3266 case Dali::Actor::Property::SENSITIVE:
3268 value = IsSensitive();
3272 case Dali::Actor::Property::LEAVE_REQUIRED:
3274 value = GetLeaveRequired();
3278 case Dali::Actor::Property::INHERIT_ORIENTATION:
3280 value = IsOrientationInherited();
3284 case Dali::Actor::Property::INHERIT_SCALE:
3286 value = IsScaleInherited();
3290 case Dali::Actor::Property::COLOR_MODE:
3292 value = Scripting::GetColorMode( GetColorMode() );
3296 case Dali::Actor::Property::POSITION_INHERITANCE:
3298 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3302 case Dali::Actor::Property::DRAW_MODE:
3304 value = Scripting::GetDrawMode( GetDrawMode() );
3308 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3310 value = GetSizeModeFactor();
3314 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3316 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3320 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3322 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3326 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3328 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3332 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3334 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3338 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3340 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3344 case Dali::Actor::Property::PADDING:
3346 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3347 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3348 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3352 case Dali::Actor::Property::MINIMUM_SIZE:
3354 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3358 case Dali::Actor::Property::MAXIMUM_SIZE:
3360 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3366 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3374 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3379 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3381 // This method should only return an object connected to the scene-graph
3382 return OnStage() ? mNode : NULL;
3385 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3387 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3389 const PropertyBase* property( NULL );
3391 // This method should only return a property of an object connected to the scene-graph
3397 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3399 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3402 const TypeInfo* typeInfo( GetTypeInfo() );
3405 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3407 animatable = FindAnimatableProperty( index );
3411 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3413 property = animatable->GetSceneGraphProperty();
3415 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3417 CustomPropertyMetadata* custom = FindCustomProperty( index );
3418 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3420 property = custom->GetSceneGraphProperty();
3422 else if( NULL != mNode )
3426 case Dali::Actor::Property::SIZE:
3427 property = &mNode->mSize;
3430 case Dali::Actor::Property::SIZE_WIDTH:
3431 property = &mNode->mSize;
3434 case Dali::Actor::Property::SIZE_HEIGHT:
3435 property = &mNode->mSize;
3438 case Dali::Actor::Property::SIZE_DEPTH:
3439 property = &mNode->mSize;
3442 case Dali::Actor::Property::POSITION:
3443 property = &mNode->mPosition;
3446 case Dali::Actor::Property::POSITION_X:
3447 property = &mNode->mPosition;
3450 case Dali::Actor::Property::POSITION_Y:
3451 property = &mNode->mPosition;
3454 case Dali::Actor::Property::POSITION_Z:
3455 property = &mNode->mPosition;
3458 case Dali::Actor::Property::ORIENTATION:
3459 property = &mNode->mOrientation;
3462 case Dali::Actor::Property::SCALE:
3463 property = &mNode->mScale;
3466 case Dali::Actor::Property::SCALE_X:
3467 property = &mNode->mScale;
3470 case Dali::Actor::Property::SCALE_Y:
3471 property = &mNode->mScale;
3474 case Dali::Actor::Property::SCALE_Z:
3475 property = &mNode->mScale;
3478 case Dali::Actor::Property::VISIBLE:
3479 property = &mNode->mVisible;
3482 case Dali::Actor::Property::COLOR:
3483 property = &mNode->mColor;
3486 case Dali::Actor::Property::COLOR_RED:
3487 property = &mNode->mColor;
3490 case Dali::Actor::Property::COLOR_GREEN:
3491 property = &mNode->mColor;
3494 case Dali::Actor::Property::COLOR_BLUE:
3495 property = &mNode->mColor;
3498 case Dali::Actor::Property::COLOR_ALPHA:
3499 property = &mNode->mColor;
3510 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3512 const PropertyInputImpl* property( NULL );
3514 // This method should only return a property of an object connected to the scene-graph
3520 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3522 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3525 const TypeInfo* typeInfo( GetTypeInfo() );
3528 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3530 animatable = FindAnimatableProperty( index );
3534 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3536 property = animatable->GetSceneGraphProperty();
3538 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3540 CustomPropertyMetadata* custom = FindCustomProperty( index );
3541 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3542 property = custom->GetSceneGraphProperty();
3544 else if( NULL != mNode )
3548 case Dali::Actor::Property::PARENT_ORIGIN:
3549 property = &mNode->mParentOrigin;
3552 case Dali::Actor::Property::PARENT_ORIGIN_X:
3553 property = &mNode->mParentOrigin;
3556 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3557 property = &mNode->mParentOrigin;
3560 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3561 property = &mNode->mParentOrigin;
3564 case Dali::Actor::Property::ANCHOR_POINT:
3565 property = &mNode->mAnchorPoint;
3568 case Dali::Actor::Property::ANCHOR_POINT_X:
3569 property = &mNode->mAnchorPoint;
3572 case Dali::Actor::Property::ANCHOR_POINT_Y:
3573 property = &mNode->mAnchorPoint;
3576 case Dali::Actor::Property::ANCHOR_POINT_Z:
3577 property = &mNode->mAnchorPoint;
3580 case Dali::Actor::Property::SIZE:
3581 property = &mNode->mSize;
3584 case Dali::Actor::Property::SIZE_WIDTH:
3585 property = &mNode->mSize;
3588 case Dali::Actor::Property::SIZE_HEIGHT:
3589 property = &mNode->mSize;
3592 case Dali::Actor::Property::SIZE_DEPTH:
3593 property = &mNode->mSize;
3596 case Dali::Actor::Property::POSITION:
3597 property = &mNode->mPosition;
3600 case Dali::Actor::Property::POSITION_X:
3601 property = &mNode->mPosition;
3604 case Dali::Actor::Property::POSITION_Y:
3605 property = &mNode->mPosition;
3608 case Dali::Actor::Property::POSITION_Z:
3609 property = &mNode->mPosition;
3612 case Dali::Actor::Property::WORLD_POSITION:
3613 property = &mNode->mWorldPosition;
3616 case Dali::Actor::Property::WORLD_POSITION_X:
3617 property = &mNode->mWorldPosition;
3620 case Dali::Actor::Property::WORLD_POSITION_Y:
3621 property = &mNode->mWorldPosition;
3624 case Dali::Actor::Property::WORLD_POSITION_Z:
3625 property = &mNode->mWorldPosition;
3628 case Dali::Actor::Property::ORIENTATION:
3629 property = &mNode->mOrientation;
3632 case Dali::Actor::Property::WORLD_ORIENTATION:
3633 property = &mNode->mWorldOrientation;
3636 case Dali::Actor::Property::SCALE:
3637 property = &mNode->mScale;
3640 case Dali::Actor::Property::SCALE_X:
3641 property = &mNode->mScale;
3644 case Dali::Actor::Property::SCALE_Y:
3645 property = &mNode->mScale;
3648 case Dali::Actor::Property::SCALE_Z:
3649 property = &mNode->mScale;
3652 case Dali::Actor::Property::WORLD_SCALE:
3653 property = &mNode->mWorldScale;
3656 case Dali::Actor::Property::VISIBLE:
3657 property = &mNode->mVisible;
3660 case Dali::Actor::Property::COLOR:
3661 property = &mNode->mColor;
3664 case Dali::Actor::Property::COLOR_RED:
3665 property = &mNode->mColor;
3668 case Dali::Actor::Property::COLOR_GREEN:
3669 property = &mNode->mColor;
3672 case Dali::Actor::Property::COLOR_BLUE:
3673 property = &mNode->mColor;
3676 case Dali::Actor::Property::COLOR_ALPHA:
3677 property = &mNode->mColor;
3680 case Dali::Actor::Property::WORLD_COLOR:
3681 property = &mNode->mWorldColor;
3684 case Dali::Actor::Property::WORLD_MATRIX:
3685 property = &mNode->mWorldMatrix;
3696 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3698 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3702 case Dali::Actor::Property::PARENT_ORIGIN_X:
3703 case Dali::Actor::Property::ANCHOR_POINT_X:
3704 case Dali::Actor::Property::SIZE_WIDTH:
3705 case Dali::Actor::Property::POSITION_X:
3706 case Dali::Actor::Property::WORLD_POSITION_X:
3707 case Dali::Actor::Property::SCALE_X:
3708 case Dali::Actor::Property::COLOR_RED:
3714 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3715 case Dali::Actor::Property::ANCHOR_POINT_Y:
3716 case Dali::Actor::Property::SIZE_HEIGHT:
3717 case Dali::Actor::Property::POSITION_Y:
3718 case Dali::Actor::Property::WORLD_POSITION_Y:
3719 case Dali::Actor::Property::SCALE_Y:
3720 case Dali::Actor::Property::COLOR_GREEN:
3726 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3727 case Dali::Actor::Property::ANCHOR_POINT_Z:
3728 case Dali::Actor::Property::SIZE_DEPTH:
3729 case Dali::Actor::Property::POSITION_Z:
3730 case Dali::Actor::Property::WORLD_POSITION_Z:
3731 case Dali::Actor::Property::SCALE_Z:
3732 case Dali::Actor::Property::COLOR_BLUE:
3738 case Dali::Actor::Property::COLOR_ALPHA:
3751 return componentIndex;
3754 void Actor::SetParent( Actor* parent, int index )
3758 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3762 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3765 // Instruct each actor to create a corresponding node in the scene graph
3766 ConnectToStage( index );
3769 else // parent being set to NULL
3771 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3775 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3778 DALI_ASSERT_ALWAYS( mNode != NULL );
3782 // Disconnect the Node & its children from the scene-graph.
3783 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3786 // Instruct each actor to discard pointers to the scene-graph
3787 DisconnectFromStage();
3792 SceneGraph::Node* Actor::CreateNode() const
3797 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3800 Actor* actor = dynamic_cast< Actor* >( object );
3804 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3806 actor->SetVisible( true );
3809 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3811 actor->SetVisible( false );
3819 void Actor::EnsureRelayoutData() const
3821 // Assign relayout data.
3822 if( !mRelayoutData )
3824 mRelayoutData = new RelayoutData();
3828 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3830 // Check if actor is dependent on parent
3831 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3833 if( ( dimension & ( 1 << i ) ) )
3835 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3836 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3846 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3848 // Check if actor is dependent on children
3849 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3851 if( ( dimension & ( 1 << i ) ) )
3853 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3854 switch( resizePolicy )
3856 case ResizePolicy::FIT_TO_CHILDREN:
3857 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3873 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3875 return Actor::RelayoutDependentOnChildren( dimension );
3878 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3880 // Check each possible dimension and see if it is dependent on the input one
3881 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3883 if( dimension & ( 1 << i ) )
3885 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3892 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3894 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3896 if( dimension & ( 1 << i ) )
3898 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3903 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3905 // If more than one dimension is requested, just return the first one found
3906 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3908 if( ( dimension & ( 1 << i ) ) )
3910 return mRelayoutData->negotiatedDimensions[ i ];
3914 return 0.0f; // Default
3917 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3919 EnsureRelayoutData();
3921 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3923 if( dimension & ( 1 << i ) )
3925 mRelayoutData->dimensionPadding[ i ] = padding;
3930 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3932 EnsureRelayoutData();
3934 // If more than one dimension is requested, just return the first one found
3935 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3937 if( ( dimension & ( 1 << i ) ) )
3939 return mRelayoutData->dimensionPadding[ i ];
3943 return Vector2( 0.0f, 0.0f ); // Default
3946 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3948 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3950 if( dimension & ( 1 << i ) )
3952 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3957 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3959 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3961 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3970 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3972 // Could be overridden in derived classes.
3973 return CalculateChildSizeBase( child, dimension );
3976 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3978 // Fill to parent, taking size mode factor into account
3979 switch( child.GetResizePolicy( dimension ) )
3981 case ResizePolicy::FILL_TO_PARENT:
3983 return GetLatestSize( dimension );
3986 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3988 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3991 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3993 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3998 return GetLatestSize( dimension );
4003 float Actor::GetHeightForWidth( float width )
4005 // Could be overridden in derived classes.
4006 float height = 0.0f;
4008 const Vector3 naturalSize = GetNaturalSize();
4009 if( naturalSize.width > 0.0f )
4011 height = naturalSize.height * width / naturalSize.width;
4017 float Actor::GetWidthForHeight( float height )
4019 // Could be overridden in derived classes.
4022 const Vector3 naturalSize = GetNaturalSize();
4023 if( naturalSize.height > 0.0f )
4025 width = naturalSize.width * height / naturalSize.height;
4031 float Actor::GetLatestSize( Dimension::Type dimension ) const
4033 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4036 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4038 Vector2 padding = GetPadding( dimension );
4040 return GetLatestSize( dimension ) + padding.x + padding.y;
4043 float Actor::NegotiateFromParent( Dimension::Type dimension )
4045 Actor* parent = GetParent();
4048 Vector2 padding( GetPadding( dimension ) );
4049 Vector2 parentPadding( parent->GetPadding( dimension ) );
4050 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4056 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4058 float maxDimensionPoint = 0.0f;
4060 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4062 Dali::Actor child = GetChildAt( i );
4063 Actor& childImpl = GetImplementation( child );
4065 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4067 // Calculate the min and max points that the children range across
4068 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4069 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4070 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4074 return maxDimensionPoint;
4077 float Actor::GetSize( Dimension::Type dimension ) const
4079 return GetDimensionValue( GetTargetSize(), dimension );
4082 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4084 return GetDimensionValue( GetNaturalSize(), dimension );
4087 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4089 switch( GetResizePolicy( dimension ) )
4091 case ResizePolicy::USE_NATURAL_SIZE:
4093 return GetNaturalSize( dimension );
4096 case ResizePolicy::FIXED:
4098 return GetDimensionValue( GetPreferredSize(), dimension );
4101 case ResizePolicy::USE_ASSIGNED_SIZE:
4103 return GetDimensionValue( maximumSize, dimension );
4106 case ResizePolicy::FILL_TO_PARENT:
4107 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4108 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4110 return NegotiateFromParent( dimension );
4113 case ResizePolicy::FIT_TO_CHILDREN:
4115 return NegotiateFromChildren( dimension );
4118 case ResizePolicy::DIMENSION_DEPENDENCY:
4120 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4123 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4125 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4128 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4130 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4142 return 0.0f; // Default
4145 float Actor::ClampDimension( float size, Dimension::Type dimension )
4147 const float minSize = GetMinimumSize( dimension );
4148 const float maxSize = GetMaximumSize( dimension );
4150 return std::max( minSize, std::min( size, maxSize ) );
4153 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4155 // Check if it needs to be negotiated
4156 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4158 // Check that we havn't gotten into an infinite loop
4159 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4160 bool recursionFound = false;
4161 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4163 if( *it == searchActor )
4165 recursionFound = true;
4170 if( !recursionFound )
4172 // Record the path that we have taken
4173 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4175 // Dimension dependency check
4176 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4178 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4180 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4182 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4186 // Parent dependency check
4187 Actor* parent = GetParent();
4188 if( parent && RelayoutDependentOnParent( dimension ) )
4190 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4193 // Children dependency check
4194 if( RelayoutDependentOnChildren( dimension ) )
4196 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4198 Dali::Actor child = GetChildAt( i );
4199 Actor& childImpl = GetImplementation( child );
4201 // Only relayout child first if it is not dependent on this actor
4202 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4204 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4209 // For deriving classes
4210 OnCalculateRelayoutSize( dimension );
4212 // All dependencies checked, calculate the size and set negotiated flag
4213 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4215 SetNegotiatedDimension( newSize, dimension );
4216 SetLayoutNegotiated( true, dimension );
4218 // For deriving classes
4219 OnLayoutNegotiated( newSize, dimension );
4221 // This actor has been successfully processed, pop it off the recursion stack
4222 recursionStack.pop_back();
4226 // TODO: Break infinite loop
4227 SetLayoutNegotiated( true, dimension );
4232 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4234 // Negotiate all dimensions that require it
4235 ActorDimensionStack recursionStack;
4237 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4239 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4242 NegotiateDimension( dimension, allocatedSize, recursionStack );
4246 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4248 switch( mRelayoutData->sizeSetPolicy )
4250 case SizeScalePolicy::USE_SIZE_SET:
4255 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4257 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4258 const Vector3 naturalSize = GetNaturalSize();
4259 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4261 const float sizeRatio = size.width / size.height;
4262 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4264 if( naturalSizeRatio < sizeRatio )
4266 return Vector2( naturalSizeRatio * size.height, size.height );
4268 else if( naturalSizeRatio > sizeRatio )
4270 return Vector2( size.width, size.width / naturalSizeRatio );
4281 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4283 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4284 const Vector3 naturalSize = GetNaturalSize();
4285 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4287 const float sizeRatio = size.width / size.height;
4288 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4290 if( naturalSizeRatio < sizeRatio )
4292 return Vector2( size.width, size.width / naturalSizeRatio );
4294 else if( naturalSizeRatio > sizeRatio )
4296 return Vector2( naturalSizeRatio * size.height, size.height );
4314 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4316 // Do the set actor size
4317 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4319 // Adjust for size set policy
4320 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4322 // Lock the flag to stop recursive relayouts on set size
4323 mRelayoutData->insideRelayout = true;
4324 SetSize( negotiatedSize );
4325 mRelayoutData->insideRelayout = false;
4327 // Clear flags for all dimensions
4328 SetLayoutDirty( false );
4330 // Give deriving classes a chance to respond
4331 OnRelayout( negotiatedSize, container );
4333 if( !mOnRelayoutSignal.Empty() )
4335 Dali::Actor handle( this );
4336 mOnRelayoutSignal.Emit( handle );
4340 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4342 // Do the negotiation
4343 NegotiateDimensions( allocatedSize );
4345 // Set the actor size
4346 SetNegotiatedSize( container );
4348 // Negotiate down to children
4349 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4351 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4353 Dali::Actor child = GetChildAt( i );
4355 // Only relayout if required
4356 if( GetImplementation( child ).RelayoutRequired() )
4358 container.Add( child, newBounds );
4363 void Actor::RelayoutRequest( Dimension::Type dimension )
4365 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4366 if( relayoutController )
4368 Dali::Actor self( this );
4369 relayoutController->RequestRelayout( self, dimension );
4373 void Actor::PropagateRelayoutFlags()
4375 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4376 if( relayoutController )
4378 Dali::Actor self( this );
4379 relayoutController->PropagateFlags( self );
4383 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4387 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4391 void Actor::SetPreferredSize( const Vector2& size )
4393 EnsureRelayoutData();
4395 if( size.width > 0.0f )
4397 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4400 if( size.height > 0.0f )
4402 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4405 mRelayoutData->preferredSize = size;
4410 Vector2 Actor::GetPreferredSize() const
4412 EnsureRelayoutData();
4414 return mRelayoutData->preferredSize;
4417 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4419 EnsureRelayoutData();
4421 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4423 if( dimension & ( 1 << i ) )
4425 mRelayoutData->minimumSize[ i ] = size;
4432 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4434 EnsureRelayoutData();
4436 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4438 if( dimension & ( 1 << i ) )
4440 return mRelayoutData->minimumSize[ i ];
4444 return 0.0f; // Default
4447 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4449 EnsureRelayoutData();
4451 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4453 if( dimension & ( 1 << i ) )
4455 mRelayoutData->maximumSize[ i ] = size;
4462 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4464 EnsureRelayoutData();
4466 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4468 if( dimension & ( 1 << i ) )
4470 return mRelayoutData->maximumSize[ i ];
4474 return 0.0f; // Default
4477 } // namespace Internal