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( "relayout-enabled", BOOLEAN, true, false, false, Dali::Actor::Property::RELAYOUT_ENABLED )
230 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
231 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
232 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
233 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
234 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
235 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
236 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
237 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
238 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
242 const char* const SIGNAL_TOUCHED = "touched";
243 const char* const SIGNAL_HOVERED = "hovered";
244 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
245 const char* const SIGNAL_ON_STAGE = "on-stage";
246 const char* const SIGNAL_OFF_STAGE = "off-stage";
250 const char* const ACTION_SHOW = "show";
251 const char* const ACTION_HIDE = "hide";
253 BaseHandle CreateActor()
255 return Dali::Actor::New();
258 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
260 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
263 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
265 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
266 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
269 * @brief Extract a given dimension from a Vector2
271 * @param[in] values The values to extract from
272 * @param[in] dimension The dimension to extract
273 * @return Return the value for the dimension
275 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
279 case Dimension::WIDTH:
284 case Dimension::HEIGHT:
286 return values.height;
299 * @brief Extract a given dimension from a Vector3
301 * @param[in] values The values to extract from
302 * @param[in] dimension The dimension to extract
303 * @return Return the value for the dimension
305 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
307 return GetDimensionValue( values.GetVectorXY(), dimension );
310 } // unnamed namespace
312 ActorPtr Actor::New()
314 ActorPtr actor( new Actor( BASIC ) );
316 // Second-phase construction
322 const std::string& Actor::GetName() const
327 void Actor::SetName( const std::string& name )
333 // ATTENTION: string for debug purposes is not thread safe.
334 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
338 unsigned int Actor::GetId() const
343 void Actor::Attach( ActorAttachment& attachment )
345 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
349 attachment.Connect();
352 mAttachment = ActorAttachmentPtr( &attachment );
355 ActorAttachmentPtr Actor::GetAttachment()
360 bool Actor::OnStage() const
365 Dali::Layer Actor::GetLayer()
369 // Short-circuit for Layer derived actors
372 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
375 // Find the immediate Layer parent
376 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
378 if( parent->IsLayer() )
380 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
387 void Actor::Add( Actor& child )
389 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
390 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
394 mChildren = new ActorContainer;
397 Actor* const oldParent( child.mParent );
399 // child might already be ours
400 if( this != oldParent )
402 // if we already have parent, unparent us first
405 oldParent->Remove( child ); // This causes OnChildRemove callback
407 // Old parent may need to readjust to missing child
408 if( oldParent->RelayoutDependentOnChildren() )
410 oldParent->RelayoutRequest();
414 // Guard against Add() during previous OnChildRemove callback
417 // Do this first, since user callbacks from within SetParent() may need to remove child
418 mChildren->push_back( Dali::Actor( &child ) );
420 // SetParent asserts that child can be added
421 child.SetParent( this );
423 // Notification for derived classes
426 // Only put in a relayout request if there is a suitable dependency
427 if( RelayoutDependentOnChildren() )
435 void Actor::Insert( unsigned int index, Actor& child )
437 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
438 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
442 mChildren = new ActorContainer;
445 Actor* const oldParent( child.mParent );
447 // since an explicit position has been given, always insert, even if already a child
450 oldParent->Remove( child ); // This causes OnChildRemove callback
452 // Old parent may need to readjust to missing child
453 if( oldParent->RelayoutDependentOnChildren() )
455 oldParent->RelayoutRequest();
459 // Guard against Add() during previous OnChildRemove callback
462 // Do this first, since user callbacks from within SetParent() may need to remove child
463 if( index < GetChildCount() )
465 ActorIter it = mChildren->begin();
466 std::advance( it, index );
467 mChildren->insert( it, Dali::Actor( &child ) );
471 mChildren->push_back( Dali::Actor( &child ) );
473 // SetParent asserts that child can be added
474 child.SetParent( this, index );
476 // Notification for derived classes
479 // Only put in a relayout request if there is a suitable dependency
480 if( RelayoutDependentOnChildren() )
485 if( child.RelayoutDependentOnParent() )
487 child.RelayoutRequest();
492 void Actor::Remove( Actor& child )
494 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
504 // Find the child in mChildren, and unparent it
505 ActorIter end = mChildren->end();
506 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
508 Actor& actor = GetImplementation( *iter );
510 if( &actor == &child )
512 // Keep handle for OnChildRemove notification
513 removed = Dali::Actor( &actor );
515 // Do this first, since user callbacks from within SetParent() may need to add the child
516 mChildren->erase( iter );
518 DALI_ASSERT_DEBUG( actor.GetParent() == this );
519 actor.SetParent( NULL );
527 // Notification for derived classes
528 OnChildRemove( GetImplementation( removed ) );
530 // Only put in a relayout request if there is a suitable dependency
531 if( RelayoutDependentOnChildren() )
538 void Actor::Unparent()
542 // Remove this actor from the parent. The remove will put a relayout request in for
543 // the parent if required
544 mParent->Remove( *this );
545 // mParent is now NULL!
549 unsigned int Actor::GetChildCount() const
551 return ( NULL != mChildren ) ? mChildren->size() : 0;
554 Dali::Actor Actor::GetChildAt( unsigned int index ) const
556 DALI_ASSERT_ALWAYS( index < GetChildCount() );
558 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
561 ActorContainer Actor::GetChildren()
563 if( NULL != mChildren )
568 // return copy of mNullChildren
569 return mNullChildren;
572 const ActorContainer& Actor::GetChildren() const
574 if( NULL != mChildren )
579 // return const reference to mNullChildren
580 return mNullChildren;
583 ActorPtr Actor::FindChildByName( const std::string& actorName )
586 if( actorName == mName )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = GetImplementation( *iter ).FindChildByName( actorName );
606 ActorPtr Actor::FindChildById( const unsigned int id )
615 ActorIter end = mChildren->end();
616 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
618 child = GetImplementation( *iter ).FindChildById( id );
629 void Actor::SetParentOrigin( const Vector3& origin )
633 // mNode is being used in a separate thread; queue a message to set the value & base value
634 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
637 // Cache for event-thread access
640 // not allocated, check if different from default
641 if( ParentOrigin::DEFAULT != origin )
643 mParentOrigin = new Vector3( origin );
648 // check if different from current costs more than just set
649 *mParentOrigin = origin;
653 void Actor::SetParentOriginX( float x )
655 const Vector3& current = GetCurrentParentOrigin();
657 SetParentOrigin( Vector3( x, current.y, current.z ) );
660 void Actor::SetParentOriginY( float y )
662 const Vector3& current = GetCurrentParentOrigin();
664 SetParentOrigin( Vector3( current.x, y, current.z ) );
667 void Actor::SetParentOriginZ( float z )
669 const Vector3& current = GetCurrentParentOrigin();
671 SetParentOrigin( Vector3( current.x, current.y, z ) );
674 const Vector3& Actor::GetCurrentParentOrigin() const
676 // Cached for event-thread access
677 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
680 void Actor::SetAnchorPoint( const Vector3& anchor )
684 // mNode is being used in a separate thread; queue a message to set the value & base value
685 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
688 // Cache for event-thread access
691 // not allocated, check if different from default
692 if( AnchorPoint::DEFAULT != anchor )
694 mAnchorPoint = new Vector3( anchor );
699 // check if different from current costs more than just set
700 *mAnchorPoint = anchor;
704 void Actor::SetAnchorPointX( float x )
706 const Vector3& current = GetCurrentAnchorPoint();
708 SetAnchorPoint( Vector3( x, current.y, current.z ) );
711 void Actor::SetAnchorPointY( float y )
713 const Vector3& current = GetCurrentAnchorPoint();
715 SetAnchorPoint( Vector3( current.x, y, current.z ) );
718 void Actor::SetAnchorPointZ( float z )
720 const Vector3& current = GetCurrentAnchorPoint();
722 SetAnchorPoint( Vector3( current.x, current.y, z ) );
725 const Vector3& Actor::GetCurrentAnchorPoint() const
727 // Cached for event-thread access
728 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
731 void Actor::SetPosition( float x, float y )
733 SetPosition( Vector3( x, y, 0.0f ) );
736 void Actor::SetPosition( float x, float y, float z )
738 SetPosition( Vector3( x, y, z ) );
741 void Actor::SetPosition( const Vector3& position )
743 mTargetPosition = position;
747 // mNode is being used in a separate thread; queue a message to set the value & base value
748 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
752 void Actor::SetX( float x )
754 mTargetPosition.x = x;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
763 void Actor::SetY( float y )
765 mTargetPosition.y = y;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
774 void Actor::SetZ( float z )
776 mTargetPosition.z = z;
780 // mNode is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
785 void Actor::TranslateBy( const Vector3& distance )
787 mTargetPosition += distance;
791 // mNode is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
796 const Vector3& Actor::GetCurrentPosition() const
800 // mNode is being used in a separate thread; copy the value from the previous update
801 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
804 return Vector3::ZERO;
807 const Vector3& Actor::GetTargetPosition() const
809 return mTargetPosition;
812 const Vector3& Actor::GetCurrentWorldPosition() const
816 // mNode is being used in a separate thread; copy the value from the previous update
817 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
820 return Vector3::ZERO;
823 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
825 // this flag is not animatable so keep the value
826 mPositionInheritanceMode = mode;
829 // mNode is being used in a separate thread; queue a message to set the value
830 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
834 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
836 // Cached for event-thread access
837 return mPositionInheritanceMode;
840 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
842 Vector4 normalizedAxis( axis.x, axis.y, axis.z, 0.0f );
843 normalizedAxis.Normalize();
845 Quaternion orientation( Quaternion::FromAxisAngle( normalizedAxis, angle ) );
847 SetOrientation( orientation );
850 void Actor::SetOrientation( const Quaternion& orientation )
854 // mNode is being used in a separate thread; queue a message to set the value & base value
855 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
859 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
863 // mNode is being used in a separate thread; queue a message to set the value & base value
864 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
868 void Actor::RotateBy( const Quaternion& relativeRotation )
872 // mNode is being used in a separate thread; queue a message to set the value & base value
873 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
877 const Quaternion& Actor::GetCurrentOrientation() const
881 // mNode is being used in a separate thread; copy the value from the previous update
882 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
885 return Quaternion::IDENTITY;
888 const Quaternion& Actor::GetCurrentWorldOrientation() const
892 // mNode is being used in a separate thread; copy the value from the previous update
893 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
896 return Quaternion::IDENTITY;
899 void Actor::SetScale( float scale )
901 SetScale( Vector3( scale, scale, scale ) );
904 void Actor::SetScale( float x, float y, float z )
906 SetScale( Vector3( x, y, z ) );
909 void Actor::SetScale( const Vector3& scale )
913 // mNode is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
918 void Actor::SetScaleX( float x )
922 // mNode is being used in a separate thread; queue a message to set the value & base value
923 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
927 void Actor::SetScaleY( float y )
931 // mNode is being used in a separate thread; queue a message to set the value & base value
932 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
936 void Actor::SetScaleZ( float z )
940 // mNode is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
945 void Actor::SetInitialVolume( const Vector3& volume )
949 // mNode is being used in a separate thread; queue a message to set the value
950 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
954 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
958 // mNode is being used in a separate thread; queue a message to set the value
959 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
963 bool Actor::GetTransmitGeometryScaling() const
967 // mNode is being used in a separate thread; copy the value from the previous update
968 return mNode->GetTransmitGeometryScaling();
974 void Actor::ScaleBy( const Vector3& relativeScale )
978 // mNode is being used in a separate thread; queue a message to set the value & base value
979 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
983 const Vector3& Actor::GetCurrentScale() const
987 // mNode is being used in a separate thread; copy the value from the previous update
988 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
994 const Vector3& Actor::GetCurrentWorldScale() const
998 // mNode is being used in a separate thread; copy the value from the previous update
999 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1002 return Vector3::ONE;
1005 void Actor::SetInheritScale( bool inherit )
1007 // non animateable so keep local copy
1008 mInheritScale = inherit;
1011 // mNode is being used in a separate thread; queue a message to set the value
1012 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1016 bool Actor::IsScaleInherited() const
1018 return mInheritScale;
1021 Matrix Actor::GetCurrentWorldMatrix() const
1025 // World matrix is no longer updated unless there is something observing the node.
1026 // Need to calculate it from node's world position, orientation and scale:
1027 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1028 Matrix worldMatrix(false);
1029 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1030 mNode->GetWorldOrientation( updateBufferIndex ),
1031 mNode->GetWorldPosition( updateBufferIndex ) );
1035 return Matrix::IDENTITY;
1038 void Actor::SetVisible( bool visible )
1042 // mNode is being used in a separate thread; queue a message to set the value & base value
1043 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1047 bool Actor::IsVisible() const
1051 // mNode is being used in a separate thread; copy the value from the previous update
1052 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1058 void Actor::SetOpacity( float opacity )
1062 // mNode is being used in a separate thread; queue a message to set the value & base value
1063 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1067 float Actor::GetCurrentOpacity() const
1071 // mNode is being used in a separate thread; copy the value from the previous update
1072 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1078 const Vector4& Actor::GetCurrentWorldColor() const
1082 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1085 return Color::WHITE;
1088 void Actor::SetColor( const Vector4& color )
1092 // mNode is being used in a separate thread; queue a message to set the value & base value
1093 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1097 void Actor::SetColorRed( float red )
1101 // mNode is being used in a separate thread; queue a message to set the value & base value
1102 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1106 void Actor::SetColorGreen( float green )
1110 // mNode is being used in a separate thread; queue a message to set the value & base value
1111 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1115 void Actor::SetColorBlue( float blue )
1119 // mNode is being used in a separate thread; queue a message to set the value & base value
1120 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1124 const Vector4& Actor::GetCurrentColor() const
1128 // mNode is being used in a separate thread; copy the value from the previous update
1129 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1132 return Color::WHITE;
1135 void Actor::SetInheritOrientation( bool inherit )
1137 // non animateable so keep local copy
1138 mInheritOrientation = inherit;
1141 // mNode is being used in a separate thread; queue a message to set the value
1142 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1146 bool Actor::IsOrientationInherited() const
1148 return mInheritOrientation;
1151 void Actor::SetSizeModeFactor( const Vector3& factor )
1153 EnsureRelayoutData();
1155 mRelayoutData->sizeModeFactor = factor;
1158 const Vector3& Actor::GetSizeModeFactor() const
1160 EnsureRelayoutData();
1162 return mRelayoutData->sizeModeFactor;
1165 void Actor::SetColorMode( ColorMode colorMode )
1167 // non animateable so keep local copy
1168 mColorMode = colorMode;
1171 // mNode is being used in a separate thread; queue a message to set the value
1172 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1176 ColorMode Actor::GetColorMode() const
1178 // we have cached copy
1182 void Actor::SetSize( float width, float height )
1184 SetSize( Vector2( width, height ) );
1187 void Actor::SetSize( float width, float height, float depth )
1189 SetSize( Vector3( width, height, depth ) );
1192 void Actor::SetSize( const Vector2& size )
1194 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1197 void Actor::SetSizeInternal( const Vector2& size )
1199 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1202 float Actor::CalculateSizeZ( const Vector2& size ) const
1204 return std::min( size.width, size.height );
1207 void Actor::SetSize( const Vector3& size )
1209 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1211 SetPreferredSize( size.GetVectorXY() );
1215 SetSizeInternal( size );
1219 void Actor::SetSizeInternal( const Vector3& size )
1225 // mNode is being used in a separate thread; queue a message to set the value & base value
1226 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1228 // Notification for derived classes
1229 OnSizeSet( mTargetSize );
1231 // Raise a relayout request if the flag is not locked
1232 if( mRelayoutData && !mRelayoutData->insideRelayout )
1239 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1241 mTargetSize = targetSize;
1243 // Notify deriving classes
1244 OnSizeAnimation( animation, targetSize );
1247 void Actor::SetWidth( float width )
1251 // mNode is being used in a separate thread; queue a message to set the value & base value
1252 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1256 void Actor::SetHeight( float height )
1260 // mNode is being used in a separate thread; queue a message to set the value & base value
1261 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1265 void Actor::SetDepth( float depth )
1269 // mNode is being used in a separate thread; queue a message to set the value & base value
1270 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1274 const Vector3& Actor::GetTargetSize() const
1279 const Vector3& Actor::GetCurrentSize() const
1283 // mNode is being used in a separate thread; copy the value from the previous update
1284 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1287 return Vector3::ZERO;
1290 Vector3 Actor::GetNaturalSize() const
1292 // It is up to deriving classes to return the appropriate natural size
1293 return Vector3( 0.0f, 0.0f, 0.0f );
1296 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1298 EnsureRelayoutData();
1300 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1302 if( dimension & ( 1 << i ) )
1304 mRelayoutData->resizePolicies[ i ] = policy;
1308 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1310 if( dimension & Dimension::WIDTH )
1312 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1315 if( dimension & Dimension::HEIGHT )
1317 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1321 OnSetResizePolicy( policy, dimension );
1323 // Trigger relayout on this control
1327 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1329 EnsureRelayoutData();
1331 // If more than one dimension is requested, just return the first one found
1332 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1334 if( ( dimension & ( 1 << i ) ) )
1336 return mRelayoutData->resizePolicies[ i ];
1340 return ResizePolicy::FIXED; // Default
1343 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1345 EnsureRelayoutData();
1347 mRelayoutData->sizeSetPolicy = policy;
1350 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1352 EnsureRelayoutData();
1354 return mRelayoutData->sizeSetPolicy;
1357 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1359 EnsureRelayoutData();
1361 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1363 if( dimension & ( 1 << i ) )
1365 mRelayoutData->dimensionDependencies[ i ] = dependency;
1370 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1372 EnsureRelayoutData();
1374 // If more than one dimension is requested, just return the first one found
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( ( dimension & ( 1 << i ) ) )
1379 return mRelayoutData->dimensionDependencies[ i ];
1383 return Dimension::ALL_DIMENSIONS; // Default
1386 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1388 // If relayout data has not been allocated yet and the client is requesting
1389 // to disable it, do nothing
1390 if( mRelayoutData || relayoutEnabled )
1392 EnsureRelayoutData();
1394 mRelayoutData->relayoutEnabled = relayoutEnabled;
1398 bool Actor::IsRelayoutEnabled() const
1400 // Assume that if relayout data has not been allocated yet then
1401 // relayout is disabled
1402 return mRelayoutData && mRelayoutData->relayoutEnabled;
1405 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1407 EnsureRelayoutData();
1409 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1411 if( dimension & ( 1 << i ) )
1413 mRelayoutData->dimensionDirty[ i ] = dirty;
1418 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1420 EnsureRelayoutData();
1422 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1424 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1433 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1435 EnsureRelayoutData();
1437 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1440 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1442 EnsureRelayoutData();
1444 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1447 #ifdef DYNAMICS_SUPPORT
1449 //--------------- Dynamics ---------------
1451 void Actor::DisableDynamics()
1453 if( NULL != mDynamicsData )
1455 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1457 // ensure dynamics object are disconnected from scene
1458 DisconnectDynamics();
1460 // delete joint owned by this actor
1461 while( !mDynamicsData->joints.empty() )
1463 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1466 // delete other joints referencing this actor
1467 while( !mDynamicsData->referencedJoints.empty() )
1469 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1470 ActorPtr jointOwner( joint->GetActor( true ) );
1473 jointOwner->RemoveDynamicsJoint( joint );
1477 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1480 // delete the DynamicsBody object
1481 mDynamicsData->body.Reset();
1483 // Discard Dynamics data structure
1484 delete mDynamicsData;
1485 mDynamicsData = NULL;
1489 DynamicsBodyPtr Actor::GetDynamicsBody() const
1491 DynamicsBodyPtr body;
1493 if( NULL != mDynamicsData )
1495 body = mDynamicsData->body;
1501 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1503 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1505 if( NULL == mDynamicsData )
1507 mDynamicsData = new DynamicsData( this );
1510 if( !mDynamicsData->body )
1512 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1516 DynamicsWorldPtr world( DynamicsWorld::Get() );
1519 if( mParent == world->GetRootActor().Get() )
1521 mDynamicsData->body->Connect( GetEventThreadServices() );
1527 return mDynamicsData->body;
1530 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1532 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1533 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1536 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1538 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1539 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1541 DynamicsJointPtr joint;
1543 DynamicsWorldPtr world( DynamicsWorld::Get() );
1547 if( NULL != mDynamicsData )
1549 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1551 if( mDynamicsData->joints.end() != it )
1553 // use existing joint
1559 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1560 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1564 bodyA = EnableDynamics( new DynamicsBodyConfig );
1569 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1572 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1573 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1575 if( OnStage() && attachedActor->OnStage() )
1577 joint->Connect( GetEventThreadServices() );
1580 attachedActor->ReferenceJoint( joint );
1582 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1583 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1590 const int Actor::GetNumberOfJoints() const
1592 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1595 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1597 DynamicsJointPtr joint;
1599 if( NULL != mDynamicsData )
1601 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1603 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1605 for( int i = 0; i < index; ++i )
1617 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1619 DynamicsJointPtr joint;
1621 if( NULL != mDynamicsData )
1623 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1625 if( mDynamicsData->joints.end() != it )
1627 // use existing joint
1635 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1637 if( NULL != mDynamicsData )
1639 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1640 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1642 for(; it != endIt; ++it )
1644 if( it->second == joint.Get() )
1646 ActorPtr attachedActor( it->first );
1648 if( OnStage() && attachedActor && attachedActor->OnStage() )
1650 joint->Disconnect( GetEventThreadServices() );
1655 attachedActor->ReleaseJoint( joint );
1656 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1657 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1660 mDynamicsData->joints.erase(it);
1667 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1669 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1671 if( NULL != mDynamicsData )
1673 mDynamicsData->referencedJoints.push_back(joint);
1677 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1679 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1681 if( NULL != mDynamicsData )
1683 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1685 if( it != mDynamicsData->referencedJoints.end() )
1687 mDynamicsData->referencedJoints.erase( it );
1692 void Actor::SetDynamicsRoot(bool flag)
1694 if( mIsDynamicsRoot != flag )
1696 mIsDynamicsRoot = flag;
1698 if( OnStage() && mChildren )
1700 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1701 ActorIter end = mChildren->end();
1702 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1704 Actor& child = GetImplementation(*iter);
1706 if( child.GetDynamicsBody() )
1708 if( mIsDynamicsRoot )
1710 child.ConnectDynamics();
1714 child.DisconnectDynamics();
1722 bool Actor::IsDynamicsRoot() const
1724 return mIsDynamicsRoot;
1727 void Actor::AttachedActorOnStage( Dali::Actor actor )
1729 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1733 ActorPtr attachedActor( &GetImplementation(actor) );
1735 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1736 if( NULL != mDynamicsData )
1738 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1739 if( mDynamicsData->joints.end() != it )
1741 DynamicsJointPtr joint( it->second );
1742 joint->Connect( GetEventThreadServices() );
1748 void Actor::AttachedActorOffStage( Dali::Actor actor )
1750 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1754 ActorPtr attachedActor( &GetImplementation(actor) );
1756 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1757 if( NULL != mDynamicsData )
1759 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1760 if( mDynamicsData->joints.end() != it )
1762 DynamicsJointPtr joint( it->second );
1763 joint->Disconnect( GetEventThreadServices() );
1769 void Actor::ConnectDynamics()
1771 if( NULL != mDynamicsData && mDynamicsData->body )
1773 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1775 mDynamicsData->body->Connect( GetEventThreadServices() );
1777 // Connect all joints where attachedActor is also on stage
1778 if( !mDynamicsData->joints.empty() )
1780 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1781 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1783 for(; it != endIt; ++it )
1785 Actor* attachedActor( it->first );
1786 if( NULL != attachedActor && attachedActor->OnStage() )
1788 DynamicsJointPtr joint( it->second );
1790 joint->Connect( GetEventThreadServices() );
1798 void Actor::DisconnectDynamics()
1800 if( NULL != mDynamicsData && mDynamicsData->body )
1804 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1806 // Disconnect all joints
1807 if( !mDynamicsData->joints.empty() )
1809 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1810 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1812 for(; it != endIt; ++it )
1814 DynamicsJointPtr joint( it->second );
1816 joint->Disconnect( GetEventThreadServices() );
1823 #endif // DYNAMICS_SUPPORT
1825 void Actor::SetOverlay( bool enable )
1827 // Setting STENCIL will override OVERLAY
1828 if( DrawMode::STENCIL != mDrawMode )
1830 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1834 bool Actor::IsOverlay() const
1836 return ( DrawMode::OVERLAY == mDrawMode );
1839 void Actor::SetDrawMode( DrawMode::Type drawMode )
1841 // this flag is not animatable so keep the value
1842 mDrawMode = drawMode;
1845 // mNode is being used in a separate thread; queue a message to set the value
1846 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1850 DrawMode::Type Actor::GetDrawMode() const
1855 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1857 // only valid when on-stage
1860 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1862 Vector2 converted( screenX, screenY );
1864 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1865 const int taskCount = taskList.GetTaskCount();
1866 for( int i = taskCount - 1; i >= 0; --i )
1868 Dali::RenderTask task = taskList.GetTask( i );
1869 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1871 // found a task where this conversion was ok so return
1879 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1881 bool retval = false;
1882 // only valid when on-stage
1885 CameraActor* camera = renderTask.GetCameraActor();
1889 renderTask.GetViewport( viewport );
1891 // need to translate coordinates to render tasks coordinate space
1892 Vector2 converted( screenX, screenY );
1893 if( renderTask.TranslateCoordinates( converted ) )
1895 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1902 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1904 // Early-out if mNode is NULL
1910 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1912 // Calculate the ModelView matrix
1913 Matrix modelView( false/*don't init*/);
1914 // need to use the components as world matrix is only updated for actors that need it
1915 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1916 Matrix::Multiply( modelView, modelView, viewMatrix );
1918 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1919 Matrix invertedMvp( false/*don't init*/);
1920 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1921 bool success = invertedMvp.Invert();
1923 // Convert to GL coordinates
1924 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1929 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1936 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1942 if( XyPlaneIntersect( nearPos, farPos, local ) )
1944 Vector3 size = GetCurrentSize();
1945 localX = local.x + size.x * 0.5f;
1946 localY = local.y + size.y * 0.5f;
1957 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1960 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1962 Mathematical Formulation
1964 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1966 ( p - c ) dot ( p - c ) = r^2
1968 Given a ray with a point of origin 'o', and a direction vector 'd':
1970 ray(t) = o + td, t >= 0
1972 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1974 (o + td - c ) dot ( o + td - c ) = r^2
1976 To solve for t we first expand the above into a more recognisable quadratic equation form
1978 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1987 B = 2( o - c ) dot d
1988 C = ( o - c ) dot ( o - c ) - r^2
1990 which can be solved using a standard quadratic formula.
1992 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1994 Practical Simplification
1996 In a renderer, we often differentiate between world space and object space. In the object space
1997 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1998 into object space, the mathematical solution presented above can be simplified significantly.
2000 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
2004 and we can find the t at which the (transformed) ray intersects the sphere by
2006 ( o + td ) dot ( o + td ) = r^2
2008 According to the reasoning above, we expand the above quadratic equation into the general form
2012 which now has coefficients:
2019 // Early out if mNode is NULL
2025 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2027 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2028 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2029 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2031 // Compute the radius is not needed, square radius it's enough.
2032 const Vector3& size( mNode->GetSize( bufferIndex ) );
2034 // Scale the sphere.
2035 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2037 const float width = size.width * scale.width;
2038 const float height = size.height * scale.height;
2040 float squareSphereRadius = 0.5f * ( width * width + height * height );
2042 float a = rayDir.Dot( rayDir ); // a
2043 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2044 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2046 return ( b2 * b2 - a * c ) >= 0.f;
2049 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2056 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2058 // Transforms the ray to the local reference system.
2060 // Calculate the inverse of Model matrix
2061 Matrix invModelMatrix( false/*don't init*/);
2062 // need to use the components as world matrix is only updated for actors that need it
2063 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2065 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2066 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2068 // Test with the actor's XY plane (Normal = 0 0 1 1).
2070 float a = -rayOriginLocal.z;
2071 float b = rayDirLocal.z;
2073 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2075 // Ray travels distance * rayDirLocal to intersect with plane.
2078 const Vector3& size = mNode->GetSize( bufferIndex );
2080 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2081 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2083 // Test with the actor's geometry.
2084 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2091 void Actor::SetLeaveRequired( bool required )
2093 mLeaveRequired = required;
2096 bool Actor::GetLeaveRequired() const
2098 return mLeaveRequired;
2101 void Actor::SetKeyboardFocusable( bool focusable )
2103 mKeyboardFocusable = focusable;
2106 bool Actor::IsKeyboardFocusable() const
2108 return mKeyboardFocusable;
2111 bool Actor::GetTouchRequired() const
2113 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2116 bool Actor::GetHoverRequired() const
2118 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2121 bool Actor::GetMouseWheelEventRequired() const
2123 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2126 bool Actor::IsHittable() const
2128 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2131 ActorGestureData& Actor::GetGestureData()
2133 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2134 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2135 if( NULL == mGestureData )
2137 mGestureData = new ActorGestureData;
2139 return *mGestureData;
2142 bool Actor::IsGestureRequred( Gesture::Type type ) const
2144 return mGestureData && mGestureData->IsGestureRequred( type );
2147 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2149 bool consumed = false;
2151 if( !mTouchedSignal.Empty() )
2153 Dali::Actor handle( this );
2154 consumed = mTouchedSignal.Emit( handle, event );
2159 // Notification for derived classes
2160 consumed = OnTouchEvent( event );
2166 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2168 bool consumed = false;
2170 if( !mHoveredSignal.Empty() )
2172 Dali::Actor handle( this );
2173 consumed = mHoveredSignal.Emit( handle, event );
2178 // Notification for derived classes
2179 consumed = OnHoverEvent( event );
2185 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2187 bool consumed = false;
2189 if( !mMouseWheelEventSignal.Empty() )
2191 Dali::Actor handle( this );
2192 consumed = mMouseWheelEventSignal.Emit( handle, event );
2197 // Notification for derived classes
2198 consumed = OnMouseWheelEvent( event );
2204 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2206 return mTouchedSignal;
2209 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2211 return mHoveredSignal;
2214 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2216 return mMouseWheelEventSignal;
2219 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2221 return mOnStageSignal;
2224 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2226 return mOffStageSignal;
2229 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2231 return mOnRelayoutSignal;
2234 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2236 bool connected( true );
2237 Actor* actor = dynamic_cast< Actor* >( object );
2239 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2241 actor->TouchedSignal().Connect( tracker, functor );
2243 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2245 actor->HoveredSignal().Connect( tracker, functor );
2247 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2249 actor->MouseWheelEventSignal().Connect( tracker, functor );
2251 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2253 actor->OnStageSignal().Connect( tracker, functor );
2255 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2257 actor->OffStageSignal().Connect( tracker, functor );
2261 // signalName does not match any signal
2268 Actor::Actor( DerivedType derivedType )
2272 mParentOrigin( NULL ),
2273 mAnchorPoint( NULL ),
2274 mRelayoutData( NULL ),
2275 #ifdef DYNAMICS_SUPPORT
2276 mDynamicsData( NULL ),
2278 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
2279 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 )
2283 void Actor::Initialize()
2286 SceneGraph::Node* node = CreateNode();
2288 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2289 mNode = node; // Keep raw-pointer to Node
2293 GetEventThreadServices().RegisterObject( this );
2298 // Remove mParent pointers from children even if we're destroying core,
2299 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2302 ActorConstIter endIter = mChildren->end();
2303 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2305 Actor& actor = GetImplementation( *iter );
2306 actor.SetParent( NULL );
2311 // Guard to allow handle destruction after Core has been destroyed
2312 if( EventThreadServices::IsCoreRunning() )
2316 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2317 mNode = NULL; // Node is about to be destroyed
2320 GetEventThreadServices().UnregisterObject( this );
2323 #ifdef DYNAMICS_SUPPORT
2325 delete mDynamicsData;
2328 // Cleanup optional gesture data
2329 delete mGestureData;
2331 // Cleanup optional parent origin and anchor
2332 delete mParentOrigin;
2333 delete mAnchorPoint;
2335 // Delete optional relayout data
2338 delete mRelayoutData;
2342 void Actor::ConnectToStage( int index )
2344 // This container is used instead of walking the Actor hierachy.
2345 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2346 ActorContainer connectionList;
2348 // This stage is atomic i.e. not interrupted by user callbacks
2349 RecursiveConnectToStage( connectionList, index );
2351 // Notify applications about the newly connected actors.
2352 const ActorIter endIter = connectionList.end();
2353 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2355 Actor& actor = GetImplementation( *iter );
2356 actor.NotifyStageConnection();
2362 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2364 DALI_ASSERT_ALWAYS( !OnStage() );
2368 ConnectToSceneGraph( index );
2370 // Notification for internal derived classes
2371 OnStageConnectionInternal();
2373 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2374 connectionList.push_back( Dali::Actor( this ) );
2376 // Recursively connect children
2379 ActorConstIter endIter = mChildren->end();
2380 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2382 Actor& actor = GetImplementation( *iter );
2383 actor.RecursiveConnectToStage( connectionList );
2389 * This method is called when the Actor is connected to the Stage.
2390 * The parent must have added its Node to the scene-graph.
2391 * The child must connect its Node to the parent's Node.
2392 * This is resursive; the child calls ConnectToStage() for its children.
2394 void Actor::ConnectToSceneGraph( int index )
2396 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2400 // Reparent Node in next Update
2401 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2404 // Notify attachment
2407 mAttachment->Connect();
2410 #ifdef DYNAMICS_SUPPORT
2412 if( NULL != mDynamicsData )
2418 // Request relayout on all actors that are added to the scenegraph
2421 // Notification for Object::Observers
2425 void Actor::NotifyStageConnection()
2427 // Actors can be removed (in a callback), before the on-stage stage is reported.
2428 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2429 if( OnStage() && !mOnStageSignalled )
2431 // Notification for external (CustomActor) derived classes
2432 OnStageConnectionExternal();
2434 if( !mOnStageSignal.Empty() )
2436 Dali::Actor handle( this );
2437 mOnStageSignal.Emit( handle );
2440 // Guard against Remove during callbacks
2443 mOnStageSignalled = true; // signal required next time Actor is removed
2448 void Actor::DisconnectFromStage()
2450 // This container is used instead of walking the Actor hierachy.
2451 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2452 ActorContainer disconnectionList;
2454 // This stage is atomic i.e. not interrupted by user callbacks
2455 RecursiveDisconnectFromStage( disconnectionList );
2457 // Notify applications about the newly disconnected actors.
2458 const ActorIter endIter = disconnectionList.end();
2459 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2461 Actor& actor = GetImplementation( *iter );
2462 actor.NotifyStageDisconnection();
2466 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2468 DALI_ASSERT_ALWAYS( OnStage() );
2470 // Recursively disconnect children
2473 ActorConstIter endIter = mChildren->end();
2474 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2476 Actor& actor = GetImplementation( *iter );
2477 actor.RecursiveDisconnectFromStage( disconnectionList );
2481 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2482 disconnectionList.push_back( Dali::Actor( this ) );
2484 // Notification for internal derived classes
2485 OnStageDisconnectionInternal();
2487 DisconnectFromSceneGraph();
2493 * This method is called by an actor or its parent, before a node removal message is sent.
2494 * This is recursive; the child calls DisconnectFromStage() for its children.
2496 void Actor::DisconnectFromSceneGraph()
2498 // Notification for Object::Observers
2499 OnSceneObjectRemove();
2501 // Notify attachment
2504 mAttachment->Disconnect();
2507 #ifdef DYNAMICS_SUPPORT
2509 if( NULL != mDynamicsData )
2511 DisconnectDynamics();
2516 void Actor::NotifyStageDisconnection()
2518 // Actors can be added (in a callback), before the off-stage state is reported.
2519 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2520 // only do this step if there is a stage, i.e. Core is not being shut down
2521 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2523 // Notification for external (CustomeActor) derived classes
2524 OnStageDisconnectionExternal();
2526 if( !mOffStageSignal.Empty() )
2528 Dali::Actor handle( this );
2529 mOffStageSignal.Emit( handle );
2532 // Guard against Add during callbacks
2535 mOnStageSignalled = false; // signal required next time Actor is added
2540 bool Actor::IsNodeConnected() const
2542 bool connected( false );
2547 if( mNode->IsRoot() || mNode->GetParent() )
2556 unsigned int Actor::GetDefaultPropertyCount() const
2558 return DEFAULT_PROPERTY_COUNT;
2561 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2563 indices.reserve( DEFAULT_PROPERTY_COUNT );
2565 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2567 indices.push_back( i );
2571 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2573 if( index < DEFAULT_PROPERTY_COUNT )
2575 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2581 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2583 Property::Index index = Property::INVALID_INDEX;
2585 // Look for name in default properties
2586 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2588 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2589 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2599 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2601 if( index < DEFAULT_PROPERTY_COUNT )
2603 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2609 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2611 if( index < DEFAULT_PROPERTY_COUNT )
2613 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2619 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2621 if( index < DEFAULT_PROPERTY_COUNT )
2623 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2629 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2631 if( index < DEFAULT_PROPERTY_COUNT )
2633 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2636 // index out of range...return Property::NONE
2637 return Property::NONE;
2640 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2644 case Dali::Actor::Property::PARENT_ORIGIN:
2646 SetParentOrigin( property.Get< Vector3 >() );
2650 case Dali::Actor::Property::PARENT_ORIGIN_X:
2652 SetParentOriginX( property.Get< float >() );
2656 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2658 SetParentOriginY( property.Get< float >() );
2662 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2664 SetParentOriginZ( property.Get< float >() );
2668 case Dali::Actor::Property::ANCHOR_POINT:
2670 SetAnchorPoint( property.Get< Vector3 >() );
2674 case Dali::Actor::Property::ANCHOR_POINT_X:
2676 SetAnchorPointX( property.Get< float >() );
2680 case Dali::Actor::Property::ANCHOR_POINT_Y:
2682 SetAnchorPointY( property.Get< float >() );
2686 case Dali::Actor::Property::ANCHOR_POINT_Z:
2688 SetAnchorPointZ( property.Get< float >() );
2692 case Dali::Actor::Property::SIZE:
2694 SetSize( property.Get< Vector3 >() );
2698 case Dali::Actor::Property::SIZE_WIDTH:
2700 SetWidth( property.Get< float >() );
2704 case Dali::Actor::Property::SIZE_HEIGHT:
2706 SetHeight( property.Get< float >() );
2710 case Dali::Actor::Property::SIZE_DEPTH:
2712 SetDepth( property.Get< float >() );
2716 case Dali::Actor::Property::POSITION:
2718 SetPosition( property.Get< Vector3 >() );
2722 case Dali::Actor::Property::POSITION_X:
2724 SetX( property.Get< float >() );
2728 case Dali::Actor::Property::POSITION_Y:
2730 SetY( property.Get< float >() );
2734 case Dali::Actor::Property::POSITION_Z:
2736 SetZ( property.Get< float >() );
2740 case Dali::Actor::Property::ORIENTATION:
2742 SetOrientation( property.Get< Quaternion >() );
2746 case Dali::Actor::Property::SCALE:
2748 SetScale( property.Get< Vector3 >() );
2752 case Dali::Actor::Property::SCALE_X:
2754 SetScaleX( property.Get< float >() );
2758 case Dali::Actor::Property::SCALE_Y:
2760 SetScaleY( property.Get< float >() );
2764 case Dali::Actor::Property::SCALE_Z:
2766 SetScaleZ( property.Get< float >() );
2770 case Dali::Actor::Property::VISIBLE:
2772 SetVisible( property.Get< bool >() );
2776 case Dali::Actor::Property::COLOR:
2778 SetColor( property.Get< Vector4 >() );
2782 case Dali::Actor::Property::COLOR_RED:
2784 SetColorRed( property.Get< float >() );
2788 case Dali::Actor::Property::COLOR_GREEN:
2790 SetColorGreen( property.Get< float >() );
2794 case Dali::Actor::Property::COLOR_BLUE:
2796 SetColorBlue( property.Get< float >() );
2800 case Dali::Actor::Property::COLOR_ALPHA:
2802 SetOpacity( property.Get< float >() );
2806 case Dali::Actor::Property::NAME:
2808 SetName( property.Get< std::string >() );
2812 case Dali::Actor::Property::SENSITIVE:
2814 SetSensitive( property.Get< bool >() );
2818 case Dali::Actor::Property::LEAVE_REQUIRED:
2820 SetLeaveRequired( property.Get< bool >() );
2824 case Dali::Actor::Property::INHERIT_ORIENTATION:
2826 SetInheritOrientation( property.Get< bool >() );
2830 case Dali::Actor::Property::INHERIT_SCALE:
2832 SetInheritScale( property.Get< bool >() );
2836 case Dali::Actor::Property::COLOR_MODE:
2838 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2842 case Dali::Actor::Property::POSITION_INHERITANCE:
2844 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2848 case Dali::Actor::Property::DRAW_MODE:
2850 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2854 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2856 SetSizeModeFactor( property.Get< Vector3 >() );
2860 case Dali::Actor::Property::RELAYOUT_ENABLED:
2862 SetRelayoutEnabled( property.Get< bool >() );
2866 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2868 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2872 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2874 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2878 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2880 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2884 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2886 if( property.Get< bool >() )
2888 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2893 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2895 if( property.Get< bool >() )
2897 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2902 case Dali::Actor::Property::PADDING:
2904 Vector4 padding = property.Get< Vector4 >();
2905 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2906 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2910 case Dali::Actor::Property::MINIMUM_SIZE:
2912 Vector2 size = property.Get< Vector2 >();
2913 SetMinimumSize( size.x, Dimension::WIDTH );
2914 SetMinimumSize( size.y, Dimension::HEIGHT );
2918 case Dali::Actor::Property::MAXIMUM_SIZE:
2920 Vector2 size = property.Get< Vector2 >();
2921 SetMaximumSize( size.x, Dimension::WIDTH );
2922 SetMaximumSize( size.y, Dimension::HEIGHT );
2928 // this can happen in the case of a non-animatable default property so just do nothing
2934 // TODO: This method needs to be removed
2935 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2937 OnPropertySet( index, value );
2939 switch( entry.type )
2941 case Property::BOOLEAN:
2943 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2944 DALI_ASSERT_DEBUG( NULL != property );
2946 // property is being used in a separate thread; queue a message to set the property
2947 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2952 case Property::FLOAT:
2954 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2955 DALI_ASSERT_DEBUG( NULL != property );
2957 // property is being used in a separate thread; queue a message to set the property
2958 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2963 case Property::INTEGER:
2965 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2966 DALI_ASSERT_DEBUG( NULL != property );
2968 // property is being used in a separate thread; queue a message to set the property
2969 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2974 case Property::VECTOR2:
2976 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2977 DALI_ASSERT_DEBUG( NULL != property );
2979 // property is being used in a separate thread; queue a message to set the property
2980 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2985 case Property::VECTOR3:
2987 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2988 DALI_ASSERT_DEBUG( NULL != property );
2990 // property is being used in a separate thread; queue a message to set the property
2991 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2996 case Property::VECTOR4:
2998 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2999 DALI_ASSERT_DEBUG( NULL != property );
3001 // property is being used in a separate thread; queue a message to set the property
3002 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3007 case Property::ROTATION:
3009 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3010 DALI_ASSERT_DEBUG( NULL != property );
3012 // property is being used in a separate thread; queue a message to set the property
3013 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3018 case Property::MATRIX:
3020 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3021 DALI_ASSERT_DEBUG( NULL != property );
3023 // property is being used in a separate thread; queue a message to set the property
3024 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3029 case Property::MATRIX3:
3031 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3032 DALI_ASSERT_DEBUG( NULL != property );
3034 // property is being used in a separate thread; queue a message to set the property
3035 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3042 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3048 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3050 Property::Value value;
3054 case Dali::Actor::Property::PARENT_ORIGIN:
3056 value = GetCurrentParentOrigin();
3060 case Dali::Actor::Property::PARENT_ORIGIN_X:
3062 value = GetCurrentParentOrigin().x;
3066 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3068 value = GetCurrentParentOrigin().y;
3072 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3074 value = GetCurrentParentOrigin().z;
3078 case Dali::Actor::Property::ANCHOR_POINT:
3080 value = GetCurrentAnchorPoint();
3084 case Dali::Actor::Property::ANCHOR_POINT_X:
3086 value = GetCurrentAnchorPoint().x;
3090 case Dali::Actor::Property::ANCHOR_POINT_Y:
3092 value = GetCurrentAnchorPoint().y;
3096 case Dali::Actor::Property::ANCHOR_POINT_Z:
3098 value = GetCurrentAnchorPoint().z;
3102 case Dali::Actor::Property::SIZE:
3104 value = GetCurrentSize();
3108 case Dali::Actor::Property::SIZE_WIDTH:
3110 value = GetCurrentSize().width;
3114 case Dali::Actor::Property::SIZE_HEIGHT:
3116 value = GetCurrentSize().height;
3120 case Dali::Actor::Property::SIZE_DEPTH:
3122 value = GetCurrentSize().depth;
3126 case Dali::Actor::Property::POSITION:
3128 value = GetCurrentPosition();
3132 case Dali::Actor::Property::POSITION_X:
3134 value = GetCurrentPosition().x;
3138 case Dali::Actor::Property::POSITION_Y:
3140 value = GetCurrentPosition().y;
3144 case Dali::Actor::Property::POSITION_Z:
3146 value = GetCurrentPosition().z;
3150 case Dali::Actor::Property::WORLD_POSITION:
3152 value = GetCurrentWorldPosition();
3156 case Dali::Actor::Property::WORLD_POSITION_X:
3158 value = GetCurrentWorldPosition().x;
3162 case Dali::Actor::Property::WORLD_POSITION_Y:
3164 value = GetCurrentWorldPosition().y;
3168 case Dali::Actor::Property::WORLD_POSITION_Z:
3170 value = GetCurrentWorldPosition().z;
3174 case Dali::Actor::Property::ORIENTATION:
3176 value = GetCurrentOrientation();
3180 case Dali::Actor::Property::WORLD_ORIENTATION:
3182 value = GetCurrentWorldOrientation();
3186 case Dali::Actor::Property::SCALE:
3188 value = GetCurrentScale();
3192 case Dali::Actor::Property::SCALE_X:
3194 value = GetCurrentScale().x;
3198 case Dali::Actor::Property::SCALE_Y:
3200 value = GetCurrentScale().y;
3204 case Dali::Actor::Property::SCALE_Z:
3206 value = GetCurrentScale().z;
3210 case Dali::Actor::Property::WORLD_SCALE:
3212 value = GetCurrentWorldScale();
3216 case Dali::Actor::Property::VISIBLE:
3218 value = IsVisible();
3222 case Dali::Actor::Property::COLOR:
3224 value = GetCurrentColor();
3228 case Dali::Actor::Property::COLOR_RED:
3230 value = GetCurrentColor().r;
3234 case Dali::Actor::Property::COLOR_GREEN:
3236 value = GetCurrentColor().g;
3240 case Dali::Actor::Property::COLOR_BLUE:
3242 value = GetCurrentColor().b;
3246 case Dali::Actor::Property::COLOR_ALPHA:
3248 value = GetCurrentColor().a;
3252 case Dali::Actor::Property::WORLD_COLOR:
3254 value = GetCurrentWorldColor();
3258 case Dali::Actor::Property::WORLD_MATRIX:
3260 value = GetCurrentWorldMatrix();
3264 case Dali::Actor::Property::NAME:
3270 case Dali::Actor::Property::SENSITIVE:
3272 value = IsSensitive();
3276 case Dali::Actor::Property::LEAVE_REQUIRED:
3278 value = GetLeaveRequired();
3282 case Dali::Actor::Property::INHERIT_ORIENTATION:
3284 value = IsOrientationInherited();
3288 case Dali::Actor::Property::INHERIT_SCALE:
3290 value = IsScaleInherited();
3294 case Dali::Actor::Property::COLOR_MODE:
3296 value = Scripting::GetColorMode( GetColorMode() );
3300 case Dali::Actor::Property::POSITION_INHERITANCE:
3302 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3306 case Dali::Actor::Property::DRAW_MODE:
3308 value = Scripting::GetDrawMode( GetDrawMode() );
3312 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3314 value = GetSizeModeFactor();
3318 case Dali::Actor::Property::RELAYOUT_ENABLED:
3320 value = IsRelayoutEnabled();
3324 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3326 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3330 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3332 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3336 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3338 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3342 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3344 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3348 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3350 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3354 case Dali::Actor::Property::PADDING:
3356 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3357 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3358 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3362 case Dali::Actor::Property::MINIMUM_SIZE:
3364 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3368 case Dali::Actor::Property::MAXIMUM_SIZE:
3370 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3376 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3384 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3389 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3391 // This method should only return an object connected to the scene-graph
3392 return OnStage() ? mNode : NULL;
3395 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3397 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3399 const PropertyBase* property( NULL );
3401 // This method should only return a property of an object connected to the scene-graph
3407 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3409 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3412 const TypeInfo* typeInfo( GetTypeInfo() );
3415 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3417 animatable = FindAnimatableProperty( index );
3421 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3423 property = animatable->GetSceneGraphProperty();
3425 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3427 CustomPropertyMetadata* custom = FindCustomProperty( index );
3428 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3430 property = custom->GetSceneGraphProperty();
3432 else if( NULL != mNode )
3436 case Dali::Actor::Property::SIZE:
3437 property = &mNode->mSize;
3440 case Dali::Actor::Property::SIZE_WIDTH:
3441 property = &mNode->mSize;
3444 case Dali::Actor::Property::SIZE_HEIGHT:
3445 property = &mNode->mSize;
3448 case Dali::Actor::Property::SIZE_DEPTH:
3449 property = &mNode->mSize;
3452 case Dali::Actor::Property::POSITION:
3453 property = &mNode->mPosition;
3456 case Dali::Actor::Property::POSITION_X:
3457 property = &mNode->mPosition;
3460 case Dali::Actor::Property::POSITION_Y:
3461 property = &mNode->mPosition;
3464 case Dali::Actor::Property::POSITION_Z:
3465 property = &mNode->mPosition;
3468 case Dali::Actor::Property::ORIENTATION:
3469 property = &mNode->mOrientation;
3472 case Dali::Actor::Property::SCALE:
3473 property = &mNode->mScale;
3476 case Dali::Actor::Property::SCALE_X:
3477 property = &mNode->mScale;
3480 case Dali::Actor::Property::SCALE_Y:
3481 property = &mNode->mScale;
3484 case Dali::Actor::Property::SCALE_Z:
3485 property = &mNode->mScale;
3488 case Dali::Actor::Property::VISIBLE:
3489 property = &mNode->mVisible;
3492 case Dali::Actor::Property::COLOR:
3493 property = &mNode->mColor;
3496 case Dali::Actor::Property::COLOR_RED:
3497 property = &mNode->mColor;
3500 case Dali::Actor::Property::COLOR_GREEN:
3501 property = &mNode->mColor;
3504 case Dali::Actor::Property::COLOR_BLUE:
3505 property = &mNode->mColor;
3508 case Dali::Actor::Property::COLOR_ALPHA:
3509 property = &mNode->mColor;
3520 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3522 const PropertyInputImpl* property( NULL );
3524 // This method should only return a property of an object connected to the scene-graph
3530 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3532 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3535 const TypeInfo* typeInfo( GetTypeInfo() );
3538 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3540 animatable = FindAnimatableProperty( index );
3544 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3546 property = animatable->GetSceneGraphProperty();
3548 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3550 CustomPropertyMetadata* custom = FindCustomProperty( index );
3551 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3552 property = custom->GetSceneGraphProperty();
3554 else if( NULL != mNode )
3558 case Dali::Actor::Property::PARENT_ORIGIN:
3559 property = &mNode->mParentOrigin;
3562 case Dali::Actor::Property::PARENT_ORIGIN_X:
3563 property = &mNode->mParentOrigin;
3566 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3567 property = &mNode->mParentOrigin;
3570 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3571 property = &mNode->mParentOrigin;
3574 case Dali::Actor::Property::ANCHOR_POINT:
3575 property = &mNode->mAnchorPoint;
3578 case Dali::Actor::Property::ANCHOR_POINT_X:
3579 property = &mNode->mAnchorPoint;
3582 case Dali::Actor::Property::ANCHOR_POINT_Y:
3583 property = &mNode->mAnchorPoint;
3586 case Dali::Actor::Property::ANCHOR_POINT_Z:
3587 property = &mNode->mAnchorPoint;
3590 case Dali::Actor::Property::SIZE:
3591 property = &mNode->mSize;
3594 case Dali::Actor::Property::SIZE_WIDTH:
3595 property = &mNode->mSize;
3598 case Dali::Actor::Property::SIZE_HEIGHT:
3599 property = &mNode->mSize;
3602 case Dali::Actor::Property::SIZE_DEPTH:
3603 property = &mNode->mSize;
3606 case Dali::Actor::Property::POSITION:
3607 property = &mNode->mPosition;
3610 case Dali::Actor::Property::POSITION_X:
3611 property = &mNode->mPosition;
3614 case Dali::Actor::Property::POSITION_Y:
3615 property = &mNode->mPosition;
3618 case Dali::Actor::Property::POSITION_Z:
3619 property = &mNode->mPosition;
3622 case Dali::Actor::Property::WORLD_POSITION:
3623 property = &mNode->mWorldPosition;
3626 case Dali::Actor::Property::WORLD_POSITION_X:
3627 property = &mNode->mWorldPosition;
3630 case Dali::Actor::Property::WORLD_POSITION_Y:
3631 property = &mNode->mWorldPosition;
3634 case Dali::Actor::Property::WORLD_POSITION_Z:
3635 property = &mNode->mWorldPosition;
3638 case Dali::Actor::Property::ORIENTATION:
3639 property = &mNode->mOrientation;
3642 case Dali::Actor::Property::WORLD_ORIENTATION:
3643 property = &mNode->mWorldOrientation;
3646 case Dali::Actor::Property::SCALE:
3647 property = &mNode->mScale;
3650 case Dali::Actor::Property::SCALE_X:
3651 property = &mNode->mScale;
3654 case Dali::Actor::Property::SCALE_Y:
3655 property = &mNode->mScale;
3658 case Dali::Actor::Property::SCALE_Z:
3659 property = &mNode->mScale;
3662 case Dali::Actor::Property::WORLD_SCALE:
3663 property = &mNode->mWorldScale;
3666 case Dali::Actor::Property::VISIBLE:
3667 property = &mNode->mVisible;
3670 case Dali::Actor::Property::COLOR:
3671 property = &mNode->mColor;
3674 case Dali::Actor::Property::COLOR_RED:
3675 property = &mNode->mColor;
3678 case Dali::Actor::Property::COLOR_GREEN:
3679 property = &mNode->mColor;
3682 case Dali::Actor::Property::COLOR_BLUE:
3683 property = &mNode->mColor;
3686 case Dali::Actor::Property::COLOR_ALPHA:
3687 property = &mNode->mColor;
3690 case Dali::Actor::Property::WORLD_COLOR:
3691 property = &mNode->mWorldColor;
3694 case Dali::Actor::Property::WORLD_MATRIX:
3695 property = &mNode->mWorldMatrix;
3706 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3708 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3712 case Dali::Actor::Property::PARENT_ORIGIN_X:
3713 case Dali::Actor::Property::ANCHOR_POINT_X:
3714 case Dali::Actor::Property::SIZE_WIDTH:
3715 case Dali::Actor::Property::POSITION_X:
3716 case Dali::Actor::Property::WORLD_POSITION_X:
3717 case Dali::Actor::Property::SCALE_X:
3718 case Dali::Actor::Property::COLOR_RED:
3724 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3725 case Dali::Actor::Property::ANCHOR_POINT_Y:
3726 case Dali::Actor::Property::SIZE_HEIGHT:
3727 case Dali::Actor::Property::POSITION_Y:
3728 case Dali::Actor::Property::WORLD_POSITION_Y:
3729 case Dali::Actor::Property::SCALE_Y:
3730 case Dali::Actor::Property::COLOR_GREEN:
3736 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3737 case Dali::Actor::Property::ANCHOR_POINT_Z:
3738 case Dali::Actor::Property::SIZE_DEPTH:
3739 case Dali::Actor::Property::POSITION_Z:
3740 case Dali::Actor::Property::WORLD_POSITION_Z:
3741 case Dali::Actor::Property::SCALE_Z:
3742 case Dali::Actor::Property::COLOR_BLUE:
3748 case Dali::Actor::Property::COLOR_ALPHA:
3761 return componentIndex;
3764 void Actor::SetParent( Actor* parent, int index )
3768 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3772 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3775 // Instruct each actor to create a corresponding node in the scene graph
3776 ConnectToStage( index );
3779 else // parent being set to NULL
3781 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3785 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3788 DALI_ASSERT_ALWAYS( mNode != NULL );
3792 // Disconnect the Node & its children from the scene-graph.
3793 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3796 // Instruct each actor to discard pointers to the scene-graph
3797 DisconnectFromStage();
3802 SceneGraph::Node* Actor::CreateNode() const
3807 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3810 Actor* actor = dynamic_cast< Actor* >( object );
3814 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3816 actor->SetVisible( true );
3819 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3821 actor->SetVisible( false );
3829 void Actor::EnsureRelayoutData() const
3831 // Assign relayout data.
3832 if( !mRelayoutData )
3834 mRelayoutData = new RelayoutData();
3838 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3840 // Check if actor is dependent on parent
3841 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3843 if( ( dimension & ( 1 << i ) ) )
3845 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3846 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3856 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3858 // Check if actor is dependent on children
3859 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3861 if( ( dimension & ( 1 << i ) ) )
3863 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3864 switch( resizePolicy )
3866 case ResizePolicy::FIT_TO_CHILDREN:
3867 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3883 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3885 return Actor::RelayoutDependentOnChildren( dimension );
3888 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3890 // Check each possible dimension and see if it is dependent on the input one
3891 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3893 if( dimension & ( 1 << i ) )
3895 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3902 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3904 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3906 if( dimension & ( 1 << i ) )
3908 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3913 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3915 // If more than one dimension is requested, just return the first one found
3916 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3918 if( ( dimension & ( 1 << i ) ) )
3920 return mRelayoutData->negotiatedDimensions[ i ];
3924 return 0.0f; // Default
3927 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3929 EnsureRelayoutData();
3931 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3933 if( dimension & ( 1 << i ) )
3935 mRelayoutData->dimensionPadding[ i ] = padding;
3940 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3942 EnsureRelayoutData();
3944 // If more than one dimension is requested, just return the first one found
3945 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3947 if( ( dimension & ( 1 << i ) ) )
3949 return mRelayoutData->dimensionPadding[ i ];
3953 return Vector2( 0.0f, 0.0f ); // Default
3956 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3958 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3960 if( dimension & ( 1 << i ) )
3962 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3967 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3969 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3971 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3980 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3982 // Could be overridden in derived classes.
3983 return CalculateChildSizeBase( child, dimension );
3986 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3988 // Fill to parent, taking size mode factor into account
3989 switch( child.GetResizePolicy( dimension ) )
3991 case ResizePolicy::FILL_TO_PARENT:
3993 return GetLatestSize( dimension );
3996 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3998 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4001 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4003 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4008 return GetLatestSize( dimension );
4013 float Actor::GetHeightForWidth( float width )
4015 // Could be overridden in derived classes.
4016 float height = 0.0f;
4018 const Vector3 naturalSize = GetNaturalSize();
4019 if( naturalSize.width > 0.0f )
4021 height = naturalSize.height * width / naturalSize.width;
4027 float Actor::GetWidthForHeight( float height )
4029 // Could be overridden in derived classes.
4032 const Vector3 naturalSize = GetNaturalSize();
4033 if( naturalSize.height > 0.0f )
4035 width = naturalSize.width * height / naturalSize.height;
4041 float Actor::GetLatestSize( Dimension::Type dimension ) const
4043 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4046 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4048 Vector2 padding = GetPadding( dimension );
4050 return GetLatestSize( dimension ) + padding.x + padding.y;
4053 float Actor::NegotiateFromParent( Dimension::Type dimension )
4055 Actor* parent = GetParent();
4058 Vector2 padding( GetPadding( dimension ) );
4059 Vector2 parentPadding( parent->GetPadding( dimension ) );
4060 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4066 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4068 float maxDimensionPoint = 0.0f;
4070 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4072 Dali::Actor child = GetChildAt( i );
4073 Actor& childImpl = GetImplementation( child );
4075 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4077 // Calculate the min and max points that the children range across
4078 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4079 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4080 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4084 return maxDimensionPoint;
4087 float Actor::GetSize( Dimension::Type dimension ) const
4089 return GetDimensionValue( GetTargetSize(), dimension );
4092 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4094 return GetDimensionValue( GetNaturalSize(), dimension );
4097 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4099 switch( GetResizePolicy( dimension ) )
4101 case ResizePolicy::USE_NATURAL_SIZE:
4103 return GetNaturalSize( dimension );
4106 case ResizePolicy::FIXED:
4108 return GetDimensionValue( GetPreferredSize(), dimension );
4111 case ResizePolicy::USE_ASSIGNED_SIZE:
4113 return GetDimensionValue( maximumSize, dimension );
4116 case ResizePolicy::FILL_TO_PARENT:
4117 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4118 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4120 return NegotiateFromParent( dimension );
4123 case ResizePolicy::FIT_TO_CHILDREN:
4125 return NegotiateFromChildren( dimension );
4128 case ResizePolicy::DIMENSION_DEPENDENCY:
4130 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4133 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4135 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4138 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4140 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4152 return 0.0f; // Default
4155 float Actor::ConstrainDimension( float size, Dimension::Type dimension )
4157 const float minSize = GetMinimumSize( dimension );
4158 const float maxSize = GetMaximumSize( dimension );
4160 return std::max( minSize, std::min( size, maxSize ) );
4163 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4165 // Check if it needs to be negotiated
4166 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4168 // Check that we havn't gotten into an infinite loop
4169 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4170 bool recursionFound = false;
4171 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4173 if( *it == searchActor )
4175 recursionFound = true;
4180 if( !recursionFound )
4182 // Record the path that we have taken
4183 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4185 // Dimension dependency check
4186 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4188 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4190 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4192 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4196 // Parent dependency check
4197 Actor* parent = GetParent();
4198 if( parent && RelayoutDependentOnParent( dimension ) )
4200 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4203 // Children dependency check
4204 if( RelayoutDependentOnChildren( dimension ) )
4206 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4208 Dali::Actor child = GetChildAt( i );
4209 Actor& childImpl = GetImplementation( child );
4211 // Only relayout child first if it is not dependent on this actor
4212 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4214 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4219 // For deriving classes
4220 OnCalculateRelayoutSize( dimension );
4222 // All dependencies checked, calculate the size and set negotiated flag
4223 const float newSize = ConstrainDimension( CalculateSize( dimension, allocatedSize ), dimension );
4225 SetNegotiatedDimension( newSize, dimension );
4226 SetLayoutNegotiated( true, dimension );
4228 // For deriving classes
4229 OnLayoutNegotiated( newSize, dimension );
4231 // This actor has been successfully processed, pop it off the recursion stack
4232 recursionStack.pop_back();
4236 // TODO: Break infinite loop
4237 SetLayoutNegotiated( true, dimension );
4242 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4244 // Negotiate all dimensions that require it
4245 ActorDimensionStack recursionStack;
4247 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4249 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4252 NegotiateDimension( dimension, allocatedSize, recursionStack );
4256 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4258 switch( mRelayoutData->sizeSetPolicy )
4260 case SizeScalePolicy::USE_SIZE_SET:
4265 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4267 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4268 const Vector3 naturalSize = GetNaturalSize();
4269 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4271 const float sizeRatio = size.width / size.height;
4272 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4274 if( naturalSizeRatio < sizeRatio )
4276 return Vector2( naturalSizeRatio * size.height, size.height );
4278 else if( naturalSizeRatio > sizeRatio )
4280 return Vector2( size.width, size.width / naturalSizeRatio );
4291 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4293 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4294 const Vector3 naturalSize = GetNaturalSize();
4295 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4297 const float sizeRatio = size.width / size.height;
4298 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4300 if( naturalSizeRatio < sizeRatio )
4302 return Vector2( size.width, size.width / naturalSizeRatio );
4304 else if( naturalSizeRatio > sizeRatio )
4306 return Vector2( naturalSizeRatio * size.height, size.height );
4324 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4326 // Do the set actor size
4327 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4329 // Adjust for size set policy
4330 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4332 // Lock the flag to stop recursive relayouts on set size
4333 mRelayoutData->insideRelayout = true;
4334 SetSize( negotiatedSize );
4335 mRelayoutData->insideRelayout = false;
4337 // Clear flags for all dimensions
4338 SetLayoutDirty( false );
4340 // Give deriving classes a chance to respond
4341 OnRelayout( negotiatedSize, container );
4343 if( !mOnRelayoutSignal.Empty() )
4345 Dali::Actor handle( this );
4346 mOnRelayoutSignal.Emit( handle );
4350 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4352 // Do the negotiation
4353 NegotiateDimensions( allocatedSize );
4355 // Set the actor size
4356 SetNegotiatedSize( container );
4358 // Negotiate down to children
4359 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4361 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4363 Dali::Actor child = GetChildAt( i );
4365 // Only relayout if required
4366 if( GetImplementation( child ).RelayoutRequired() )
4368 container.Add( child, newBounds );
4373 void Actor::RelayoutRequest( Dimension::Type dimension )
4375 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4376 if( relayoutController )
4378 Dali::Actor self( this );
4379 relayoutController->RequestRelayout( self, dimension );
4383 void Actor::RelayoutRequestTree()
4385 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4386 if( relayoutController )
4388 Dali::Actor self( this );
4389 relayoutController->RequestRelayoutTree( self );
4393 void Actor::PropagateRelayoutFlags()
4395 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4396 if( relayoutController )
4398 Dali::Actor self( this );
4399 relayoutController->PropagateFlags( self );
4403 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4407 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4411 void Actor::SetPreferredSize( const Vector2& size )
4413 EnsureRelayoutData();
4415 if( size.width > 0.0f )
4417 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4420 if( size.height > 0.0f )
4422 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4425 mRelayoutData->preferredSize = size;
4430 Vector2 Actor::GetPreferredSize() const
4432 EnsureRelayoutData();
4434 return mRelayoutData->preferredSize;
4437 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4439 EnsureRelayoutData();
4441 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4443 if( dimension & ( 1 << i ) )
4445 mRelayoutData->minimumSize[ i ] = size;
4452 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4454 EnsureRelayoutData();
4456 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4458 if( dimension & ( 1 << i ) )
4460 return mRelayoutData->minimumSize[ i ];
4464 return 0.0f; // Default
4467 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4469 EnsureRelayoutData();
4471 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4473 if( dimension & ( 1 << i ) )
4475 mRelayoutData->maximumSize[ i ] = size;
4482 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4484 EnsureRelayoutData();
4486 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4488 if( dimension & ( 1 << i ) )
4490 return mRelayoutData->maximumSize[ i ];
4494 return 0.0f; // Default
4497 } // namespace Internal