2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
25 #include <cstring> // for strcmp
29 #include <dali/public-api/common/dali-common.h>
30 #include <dali/public-api/common/constants.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-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/actor-attachments/renderer-attachment-impl.h>
47 #include <dali/internal/event/animation/constraint-impl.h>
48 #include <dali/internal/event/common/projection.h>
49 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
50 #include <dali/internal/update/common/animatable-property.h>
51 #include <dali/internal/update/nodes/node-messages.h>
52 #include <dali/internal/update/nodes/node-declarations.h>
53 #include <dali/internal/update/animation/scene-graph-constraint.h>
54 #include <dali/internal/event/events/actor-gesture-data.h>
55 #include <dali/internal/common/message.h>
56 #include <dali/integration-api/debug.h>
58 #ifdef DYNAMICS_SUPPORT
59 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
61 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
62 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
65 using Dali::Internal::SceneGraph::Node;
66 using Dali::Internal::SceneGraph::AnimatableProperty;
67 using Dali::Internal::SceneGraph::PropertyBase;
71 namespace ResizePolicy
76 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( FIXED )
77 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
78 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
80 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
81 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
82 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
83 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
84 DALI_ENUM_TO_STRING_TABLE_END( Type )
86 } // unnamed namespace
89 namespace SizeScalePolicy
93 // Enumeration to / from string conversion tables
94 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
95 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
97 DALI_ENUM_TO_STRING_TABLE_END( Type )
98 } // unnamed namespace
104 unsigned int Actor::mActorCounter = 0;
107 * Struct to collect relayout variables
109 struct Actor::RelayoutData
112 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
114 // Set size negotiation defaults
115 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
117 resizePolicies[ i ] = ResizePolicy::FIXED;
118 negotiatedDimensions[ i ] = 0.0f;
119 dimensionNegotiated[ i ] = false;
120 dimensionDirty[ i ] = false;
121 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
122 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
123 minimumSize[ i ] = 0.0f;
124 maximumSize[ i ] = FLT_MAX;
128 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
130 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
132 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
134 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
136 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
137 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
139 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
140 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
142 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
144 Vector2 preferredSize; ///< The preferred size of the actor
146 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
148 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
149 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
152 #ifdef DYNAMICS_SUPPORT
154 // Encapsulate actor related dynamics data
157 DynamicsData( Actor* slotOwner )
158 : slotDelegate( slotOwner )
162 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
163 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
165 DynamicsBodyPtr body;
166 JointContainer joints;
167 ReferencedJointContainer referencedJoints;
169 SlotDelegate< Actor > slotDelegate;
172 #endif // DYNAMICS_SUPPORT
174 namespace // unnamed namespace
180 * We want to discourage the use of property strings (minimize string comparisons),
181 * particularly for the default properties.
182 * Name Type writable animatable constraint-input enum for index-checking
184 DALI_PROPERTY_TABLE_BEGIN
185 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
186 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
187 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
188 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
189 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
190 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
191 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
192 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
193 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
194 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
195 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
196 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
197 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
198 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
199 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
200 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
201 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
202 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
203 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
204 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
205 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
206 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
207 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
208 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
209 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
210 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
211 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
212 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
213 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
214 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
215 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
216 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
217 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
218 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
219 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
220 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
221 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
222 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
223 DALI_PROPERTY( "inherit-orientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
224 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
225 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
226 DALI_PROPERTY( "position-inheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
227 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
228 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
229 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
230 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
231 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
232 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
233 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
234 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
235 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
236 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
237 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
241 const char* const SIGNAL_TOUCHED = "touched";
242 const char* const SIGNAL_HOVERED = "hovered";
243 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
244 const char* const SIGNAL_ON_STAGE = "on-stage";
245 const char* const SIGNAL_OFF_STAGE = "off-stage";
249 const char* const ACTION_SHOW = "show";
250 const char* const ACTION_HIDE = "hide";
252 BaseHandle CreateActor()
254 return Dali::Actor::New();
257 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
259 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
264 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
265 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
268 * @brief Extract a given dimension from a Vector2
270 * @param[in] values The values to extract from
271 * @param[in] dimension The dimension to extract
272 * @return Return the value for the dimension
274 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
278 case Dimension::WIDTH:
283 case Dimension::HEIGHT:
285 return values.height;
298 * @brief Extract a given dimension from a Vector3
300 * @param[in] values The values to extract from
301 * @param[in] dimension The dimension to extract
302 * @return Return the value for the dimension
304 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
306 return GetDimensionValue( values.GetVectorXY(), dimension );
309 } // unnamed namespace
311 ActorPtr Actor::New()
313 ActorPtr actor( new Actor( BASIC ) );
315 // Second-phase construction
321 const std::string& Actor::GetName() const
326 void Actor::SetName( const std::string& name )
332 // ATTENTION: string for debug purposes is not thread safe.
333 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
337 unsigned int Actor::GetId() const
342 void Actor::Attach( ActorAttachment& attachment )
344 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
348 attachment.Connect();
351 mAttachment = ActorAttachmentPtr( &attachment );
354 ActorAttachmentPtr Actor::GetAttachment()
359 bool Actor::OnStage() const
364 Dali::Layer Actor::GetLayer()
368 // Short-circuit for Layer derived actors
371 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
374 // Find the immediate Layer parent
375 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
377 if( parent->IsLayer() )
379 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
386 void Actor::Add( Actor& child )
388 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
389 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
393 mChildren = new ActorContainer;
396 Actor* const oldParent( child.mParent );
398 // child might already be ours
399 if( this != oldParent )
401 // if we already have parent, unparent us first
404 oldParent->Remove( child ); // This causes OnChildRemove callback
406 // Old parent may need to readjust to missing child
407 if( oldParent->RelayoutDependentOnChildren() )
409 oldParent->RelayoutRequest();
413 // Guard against Add() during previous OnChildRemove callback
416 // Do this first, since user callbacks from within SetParent() may need to remove child
417 mChildren->push_back( Dali::Actor( &child ) );
419 // SetParent asserts that child can be added
420 child.SetParent( this );
422 // Notification for derived classes
425 // Only put in a relayout request if there is a suitable dependency
426 if( RelayoutDependentOnChildren() )
434 void Actor::Insert( unsigned int index, Actor& child )
436 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
437 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
441 mChildren = new ActorContainer;
444 Actor* const oldParent( child.mParent );
446 // since an explicit position has been given, always insert, even if already a child
449 oldParent->Remove( child ); // This causes OnChildRemove callback
451 // Old parent may need to readjust to missing child
452 if( oldParent->RelayoutDependentOnChildren() )
454 oldParent->RelayoutRequest();
458 // Guard against Add() during previous OnChildRemove callback
461 // Do this first, since user callbacks from within SetParent() may need to remove child
462 if( index < GetChildCount() )
464 ActorIter it = mChildren->begin();
465 std::advance( it, index );
466 mChildren->insert( it, Dali::Actor( &child ) );
470 mChildren->push_back( Dali::Actor( &child ) );
472 // SetParent asserts that child can be added
473 child.SetParent( this, index );
475 // Notification for derived classes
478 // Only put in a relayout request if there is a suitable dependency
479 if( RelayoutDependentOnChildren() )
484 if( child.RelayoutDependentOnParent() )
486 child.RelayoutRequest();
491 void Actor::Remove( Actor& child )
493 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
503 // Find the child in mChildren, and unparent it
504 ActorIter end = mChildren->end();
505 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
507 Actor& actor = GetImplementation( *iter );
509 if( &actor == &child )
511 // Keep handle for OnChildRemove notification
512 removed = Dali::Actor( &actor );
514 // Do this first, since user callbacks from within SetParent() may need to add the child
515 mChildren->erase( iter );
517 DALI_ASSERT_DEBUG( actor.GetParent() == this );
518 actor.SetParent( NULL );
526 // Notification for derived classes
527 OnChildRemove( GetImplementation( removed ) );
529 // Only put in a relayout request if there is a suitable dependency
530 if( RelayoutDependentOnChildren() )
537 void Actor::Unparent()
541 // Remove this actor from the parent. The remove will put a relayout request in for
542 // the parent if required
543 mParent->Remove( *this );
544 // mParent is now NULL!
548 unsigned int Actor::GetChildCount() const
550 return ( NULL != mChildren ) ? mChildren->size() : 0;
553 Dali::Actor Actor::GetChildAt( unsigned int index ) const
555 DALI_ASSERT_ALWAYS( index < GetChildCount() );
557 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
560 ActorPtr Actor::FindChildByName( const std::string& actorName )
563 if( actorName == mName )
569 ActorIter end = mChildren->end();
570 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
572 child = GetImplementation( *iter ).FindChildByName( actorName );
583 ActorPtr Actor::FindChildById( const unsigned int id )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = GetImplementation( *iter ).FindChildById( id );
606 void Actor::SetParentOrigin( const Vector3& origin )
610 // mNode is being used in a separate thread; queue a message to set the value & base value
611 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
614 // Cache for event-thread access
617 // not allocated, check if different from default
618 if( ParentOrigin::DEFAULT != origin )
620 mParentOrigin = new Vector3( origin );
625 // check if different from current costs more than just set
626 *mParentOrigin = origin;
630 void Actor::SetParentOriginX( float x )
632 const Vector3& current = GetCurrentParentOrigin();
634 SetParentOrigin( Vector3( x, current.y, current.z ) );
637 void Actor::SetParentOriginY( float y )
639 const Vector3& current = GetCurrentParentOrigin();
641 SetParentOrigin( Vector3( current.x, y, current.z ) );
644 void Actor::SetParentOriginZ( float z )
646 const Vector3& current = GetCurrentParentOrigin();
648 SetParentOrigin( Vector3( current.x, current.y, z ) );
651 const Vector3& Actor::GetCurrentParentOrigin() const
653 // Cached for event-thread access
654 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
657 void Actor::SetAnchorPoint( const Vector3& anchor )
661 // mNode is being used in a separate thread; queue a message to set the value & base value
662 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
665 // Cache for event-thread access
668 // not allocated, check if different from default
669 if( AnchorPoint::DEFAULT != anchor )
671 mAnchorPoint = new Vector3( anchor );
676 // check if different from current costs more than just set
677 *mAnchorPoint = anchor;
681 void Actor::SetAnchorPointX( float x )
683 const Vector3& current = GetCurrentAnchorPoint();
685 SetAnchorPoint( Vector3( x, current.y, current.z ) );
688 void Actor::SetAnchorPointY( float y )
690 const Vector3& current = GetCurrentAnchorPoint();
692 SetAnchorPoint( Vector3( current.x, y, current.z ) );
695 void Actor::SetAnchorPointZ( float z )
697 const Vector3& current = GetCurrentAnchorPoint();
699 SetAnchorPoint( Vector3( current.x, current.y, z ) );
702 const Vector3& Actor::GetCurrentAnchorPoint() const
704 // Cached for event-thread access
705 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
708 void Actor::SetPosition( float x, float y )
710 SetPosition( Vector3( x, y, 0.0f ) );
713 void Actor::SetPosition( float x, float y, float z )
715 SetPosition( Vector3( x, y, z ) );
718 void Actor::SetPosition( const Vector3& position )
720 mTargetPosition = position;
724 // mNode is being used in a separate thread; queue a message to set the value & base value
725 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
729 void Actor::SetX( float x )
731 mTargetPosition.x = x;
735 // mNode is being used in a separate thread; queue a message to set the value & base value
736 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
740 void Actor::SetY( float y )
742 mTargetPosition.y = y;
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
751 void Actor::SetZ( float z )
753 mTargetPosition.z = z;
757 // mNode is being used in a separate thread; queue a message to set the value & base value
758 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
762 void Actor::TranslateBy( const Vector3& distance )
764 mTargetPosition += distance;
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
773 const Vector3& Actor::GetCurrentPosition() const
777 // mNode is being used in a separate thread; copy the value from the previous update
778 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
781 return Vector3::ZERO;
784 const Vector3& Actor::GetTargetPosition() const
786 return mTargetPosition;
789 const Vector3& Actor::GetCurrentWorldPosition() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 return Vector3::ZERO;
800 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
802 // this flag is not animatable so keep the value
803 mPositionInheritanceMode = mode;
806 // mNode is being used in a separate thread; queue a message to set the value
807 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
811 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
813 // Cached for event-thread access
814 return mPositionInheritanceMode;
817 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
819 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
820 normalizedAxis.Normalize();
822 Quaternion orientation( angle, normalizedAxis );
824 SetOrientation( orientation );
827 void Actor::SetOrientation( const Quaternion& orientation )
831 // mNode is being used in a separate thread; queue a message to set the value & base value
832 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
836 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
840 // mNode is being used in a separate thread; queue a message to set the value & base value
841 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
845 void Actor::RotateBy( const Quaternion& relativeRotation )
849 // mNode is being used in a separate thread; queue a message to set the value & base value
850 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
854 const Quaternion& Actor::GetCurrentOrientation() const
858 // mNode is being used in a separate thread; copy the value from the previous update
859 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
862 return Quaternion::IDENTITY;
865 const Quaternion& Actor::GetCurrentWorldOrientation() const
869 // mNode is being used in a separate thread; copy the value from the previous update
870 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
873 return Quaternion::IDENTITY;
876 void Actor::SetScale( float scale )
878 SetScale( Vector3( scale, scale, scale ) );
881 void Actor::SetScale( float x, float y, float z )
883 SetScale( Vector3( x, y, z ) );
886 void Actor::SetScale( const Vector3& scale )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
895 void Actor::SetScaleX( float x )
899 // mNode is being used in a separate thread; queue a message to set the value & base value
900 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
904 void Actor::SetScaleY( float y )
908 // mNode is being used in a separate thread; queue a message to set the value & base value
909 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
913 void Actor::SetScaleZ( float z )
917 // mNode is being used in a separate thread; queue a message to set the value & base value
918 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
922 void Actor::ScaleBy(const Vector3& relativeScale)
926 // mNode is being used in a separate thread; queue a message to set the value & base value
927 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
931 const Vector3& Actor::GetCurrentScale() const
935 // mNode is being used in a separate thread; copy the value from the previous update
936 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
942 const Vector3& Actor::GetCurrentWorldScale() const
946 // mNode is being used in a separate thread; copy the value from the previous update
947 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
953 void Actor::SetInheritScale( bool inherit )
955 // non animateable so keep local copy
956 mInheritScale = inherit;
959 // mNode is being used in a separate thread; queue a message to set the value
960 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
964 bool Actor::IsScaleInherited() const
966 return mInheritScale;
969 Matrix Actor::GetCurrentWorldMatrix() const
973 // World matrix is no longer updated unless there is something observing the node.
974 // Need to calculate it from node's world position, orientation and scale:
975 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
976 Matrix worldMatrix(false);
977 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
978 mNode->GetWorldOrientation( updateBufferIndex ),
979 mNode->GetWorldPosition( updateBufferIndex ) );
983 return Matrix::IDENTITY;
986 void Actor::SetVisible( bool visible )
990 // mNode is being used in a separate thread; queue a message to set the value & base value
991 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
995 bool Actor::IsVisible() const
999 // mNode is being used in a separate thread; copy the value from the previous update
1000 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1006 void Actor::SetOpacity( float opacity )
1010 // mNode is being used in a separate thread; queue a message to set the value & base value
1011 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1015 float Actor::GetCurrentOpacity() const
1019 // mNode is being used in a separate thread; copy the value from the previous update
1020 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1026 const Vector4& Actor::GetCurrentWorldColor() const
1030 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1033 return Color::WHITE;
1036 void Actor::SetColor( const Vector4& color )
1040 // mNode is being used in a separate thread; queue a message to set the value & base value
1041 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1045 void Actor::SetColorRed( float red )
1049 // mNode is being used in a separate thread; queue a message to set the value & base value
1050 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1054 void Actor::SetColorGreen( float green )
1058 // mNode is being used in a separate thread; queue a message to set the value & base value
1059 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1063 void Actor::SetColorBlue( float blue )
1067 // mNode is being used in a separate thread; queue a message to set the value & base value
1068 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1072 const Vector4& Actor::GetCurrentColor() const
1076 // mNode is being used in a separate thread; copy the value from the previous update
1077 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1080 return Color::WHITE;
1083 void Actor::SetInheritOrientation( bool inherit )
1085 // non animateable so keep local copy
1086 mInheritOrientation = inherit;
1089 // mNode is being used in a separate thread; queue a message to set the value
1090 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1094 bool Actor::IsOrientationInherited() const
1096 return mInheritOrientation;
1099 void Actor::SetSizeModeFactor( const Vector3& factor )
1101 EnsureRelayoutData();
1103 mRelayoutData->sizeModeFactor = factor;
1106 const Vector3& Actor::GetSizeModeFactor() const
1108 EnsureRelayoutData();
1110 return mRelayoutData->sizeModeFactor;
1113 void Actor::SetColorMode( ColorMode colorMode )
1115 // non animateable so keep local copy
1116 mColorMode = colorMode;
1119 // mNode is being used in a separate thread; queue a message to set the value
1120 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1124 ColorMode Actor::GetColorMode() const
1126 // we have cached copy
1130 void Actor::SetSize( float width, float height )
1132 SetSize( Vector2( width, height ) );
1135 void Actor::SetSize( float width, float height, float depth )
1137 SetSize( Vector3( width, height, depth ) );
1140 void Actor::SetSize( const Vector2& size )
1142 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1145 void Actor::SetSizeInternal( const Vector2& size )
1147 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1150 float Actor::CalculateSizeZ( const Vector2& size ) const
1152 return std::min( size.width, size.height );
1155 void Actor::SetSize( const Vector3& size )
1157 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1159 SetPreferredSize( size.GetVectorXY() );
1163 SetSizeInternal( size );
1167 void Actor::SetSizeInternal( const Vector3& size )
1173 // mNode is being used in a separate thread; queue a message to set the value & base value
1174 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1176 // Notification for derived classes
1177 OnSizeSet( mTargetSize );
1179 // Raise a relayout request if the flag is not locked
1180 if( mRelayoutData && !mRelayoutData->insideRelayout )
1187 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1189 mTargetSize = targetSize;
1191 // Notify deriving classes
1192 OnSizeAnimation( animation, targetSize );
1195 void Actor::SetWidth( float width )
1199 // mNode is being used in a separate thread; queue a message to set the value & base value
1200 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1204 void Actor::SetHeight( float height )
1208 // mNode is being used in a separate thread; queue a message to set the value & base value
1209 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1213 void Actor::SetDepth( float depth )
1217 // mNode is being used in a separate thread; queue a message to set the value & base value
1218 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1222 const Vector3& Actor::GetTargetSize() const
1227 const Vector3& Actor::GetCurrentSize() const
1231 // mNode is being used in a separate thread; copy the value from the previous update
1232 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1235 return Vector3::ZERO;
1238 Vector3 Actor::GetNaturalSize() const
1240 // It is up to deriving classes to return the appropriate natural size
1241 return Vector3( 0.0f, 0.0f, 0.0f );
1244 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1246 EnsureRelayoutData();
1248 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1250 if( dimension & ( 1 << i ) )
1252 mRelayoutData->resizePolicies[ i ] = policy;
1256 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1258 if( dimension & Dimension::WIDTH )
1260 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1263 if( dimension & Dimension::HEIGHT )
1265 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1269 // If calling SetResizePolicy, assume we want relayout enabled
1270 SetRelayoutEnabled( true );
1272 OnSetResizePolicy( policy, dimension );
1274 // Trigger relayout on this control
1278 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1280 EnsureRelayoutData();
1282 // If more than one dimension is requested, just return the first one found
1283 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1285 if( ( dimension & ( 1 << i ) ) )
1287 return mRelayoutData->resizePolicies[ i ];
1291 return ResizePolicy::FIXED; // Default
1294 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1296 EnsureRelayoutData();
1298 mRelayoutData->sizeSetPolicy = policy;
1301 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1303 EnsureRelayoutData();
1305 return mRelayoutData->sizeSetPolicy;
1308 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1310 EnsureRelayoutData();
1312 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1314 if( dimension & ( 1 << i ) )
1316 mRelayoutData->dimensionDependencies[ i ] = dependency;
1321 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1323 EnsureRelayoutData();
1325 // If more than one dimension is requested, just return the first one found
1326 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1328 if( ( dimension & ( 1 << i ) ) )
1330 return mRelayoutData->dimensionDependencies[ i ];
1334 return Dimension::ALL_DIMENSIONS; // Default
1337 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1339 // If relayout data has not been allocated yet and the client is requesting
1340 // to disable it, do nothing
1341 if( mRelayoutData || relayoutEnabled )
1343 EnsureRelayoutData();
1345 mRelayoutData->relayoutEnabled = relayoutEnabled;
1349 bool Actor::IsRelayoutEnabled() const
1351 // Assume that if relayout data has not been allocated yet then
1352 // relayout is disabled
1353 return mRelayoutData && mRelayoutData->relayoutEnabled;
1356 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1358 EnsureRelayoutData();
1360 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1362 if( dimension & ( 1 << i ) )
1364 mRelayoutData->dimensionDirty[ i ] = dirty;
1369 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1371 EnsureRelayoutData();
1373 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1375 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1384 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1386 EnsureRelayoutData();
1388 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1391 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1393 EnsureRelayoutData();
1395 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1398 unsigned int Actor::AddRenderer( Renderer& renderer )
1400 //TODO: MESH_REWORK : Add support for multiple renderers
1401 if ( ! mAttachment )
1403 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1409 unsigned int Actor::GetRendererCount() const
1411 //TODO: MESH_REWORK : Add support for multiple renderers
1412 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1413 return attachment ? 1u : 0u;
1416 Renderer& Actor::GetRendererAt( unsigned int index )
1418 //TODO: MESH_REWORK : Add support for multiple renderers
1419 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1421 //TODO: MESH_REWORK : Temporary code
1422 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1423 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1425 return attachment->GetRenderer();
1428 void Actor::RemoveRenderer( Renderer& renderer )
1430 //TODO: MESH_REWORK : Add support for multiple renderers
1434 void Actor::RemoveRenderer( unsigned int index )
1436 //TODO: MESH_REWORK : Add support for multiple renderers
1441 #ifdef DYNAMICS_SUPPORT
1443 //--------------- Dynamics ---------------
1445 void Actor::DisableDynamics()
1447 if( NULL != mDynamicsData )
1449 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1451 // ensure dynamics object are disconnected from scene
1452 DisconnectDynamics();
1454 // delete joint owned by this actor
1455 while( !mDynamicsData->joints.empty() )
1457 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1460 // delete other joints referencing this actor
1461 while( !mDynamicsData->referencedJoints.empty() )
1463 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1464 ActorPtr jointOwner( joint->GetActor( true ) );
1467 jointOwner->RemoveDynamicsJoint( joint );
1471 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1474 // delete the DynamicsBody object
1475 mDynamicsData->body.Reset();
1477 // Discard Dynamics data structure
1478 delete mDynamicsData;
1479 mDynamicsData = NULL;
1483 DynamicsBodyPtr Actor::GetDynamicsBody() const
1485 DynamicsBodyPtr body;
1487 if( NULL != mDynamicsData )
1489 body = mDynamicsData->body;
1495 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1497 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1499 if( NULL == mDynamicsData )
1501 mDynamicsData = new DynamicsData( this );
1504 if( !mDynamicsData->body )
1506 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1510 DynamicsWorldPtr world( DynamicsWorld::Get() );
1513 if( mParent == world->GetRootActor().Get() )
1515 mDynamicsData->body->Connect( GetEventThreadServices() );
1521 return mDynamicsData->body;
1524 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1526 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1527 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1530 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1532 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1533 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1535 DynamicsJointPtr joint;
1537 DynamicsWorldPtr world( DynamicsWorld::Get() );
1541 if( NULL != mDynamicsData )
1543 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1545 if( mDynamicsData->joints.end() != it )
1547 // use existing joint
1553 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1554 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1558 bodyA = EnableDynamics( new DynamicsBodyConfig );
1563 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1566 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1567 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1569 if( OnStage() && attachedActor->OnStage() )
1571 joint->Connect( GetEventThreadServices() );
1574 attachedActor->ReferenceJoint( joint );
1576 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1577 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1584 const int Actor::GetNumberOfJoints() const
1586 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1589 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1591 DynamicsJointPtr joint;
1593 if( NULL != mDynamicsData )
1595 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1597 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1599 for( int i = 0; i < index; ++i )
1611 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1613 DynamicsJointPtr joint;
1615 if( NULL != mDynamicsData )
1617 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1619 if( mDynamicsData->joints.end() != it )
1621 // use existing joint
1629 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1631 if( NULL != mDynamicsData )
1633 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1634 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1636 for(; it != endIt; ++it )
1638 if( it->second == joint.Get() )
1640 ActorPtr attachedActor( it->first );
1642 if( OnStage() && attachedActor && attachedActor->OnStage() )
1644 joint->Disconnect( GetEventThreadServices() );
1649 attachedActor->ReleaseJoint( joint );
1650 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1651 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1654 mDynamicsData->joints.erase(it);
1661 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1663 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1665 if( NULL != mDynamicsData )
1667 mDynamicsData->referencedJoints.push_back(joint);
1671 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1673 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1675 if( NULL != mDynamicsData )
1677 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1679 if( it != mDynamicsData->referencedJoints.end() )
1681 mDynamicsData->referencedJoints.erase( it );
1686 void Actor::SetDynamicsRoot(bool flag)
1688 if( mIsDynamicsRoot != flag )
1690 mIsDynamicsRoot = flag;
1692 if( OnStage() && mChildren )
1694 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1695 ActorIter end = mChildren->end();
1696 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1698 Actor& child = GetImplementation(*iter);
1700 if( child.GetDynamicsBody() )
1702 if( mIsDynamicsRoot )
1704 child.ConnectDynamics();
1708 child.DisconnectDynamics();
1716 bool Actor::IsDynamicsRoot() const
1718 return mIsDynamicsRoot;
1721 void Actor::AttachedActorOnStage( Dali::Actor actor )
1723 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1727 ActorPtr attachedActor( &GetImplementation(actor) );
1729 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1730 if( NULL != mDynamicsData )
1732 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1733 if( mDynamicsData->joints.end() != it )
1735 DynamicsJointPtr joint( it->second );
1736 joint->Connect( GetEventThreadServices() );
1742 void Actor::AttachedActorOffStage( Dali::Actor actor )
1744 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1748 ActorPtr attachedActor( &GetImplementation(actor) );
1750 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1751 if( NULL != mDynamicsData )
1753 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1754 if( mDynamicsData->joints.end() != it )
1756 DynamicsJointPtr joint( it->second );
1757 joint->Disconnect( GetEventThreadServices() );
1763 void Actor::ConnectDynamics()
1765 if( NULL != mDynamicsData && mDynamicsData->body )
1767 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1769 mDynamicsData->body->Connect( GetEventThreadServices() );
1771 // Connect all joints where attachedActor is also on stage
1772 if( !mDynamicsData->joints.empty() )
1774 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1775 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1777 for(; it != endIt; ++it )
1779 Actor* attachedActor( it->first );
1780 if( NULL != attachedActor && attachedActor->OnStage() )
1782 DynamicsJointPtr joint( it->second );
1784 joint->Connect( GetEventThreadServices() );
1792 void Actor::DisconnectDynamics()
1794 if( NULL != mDynamicsData && mDynamicsData->body )
1798 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1800 // Disconnect all joints
1801 if( !mDynamicsData->joints.empty() )
1803 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1804 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1806 for(; it != endIt; ++it )
1808 DynamicsJointPtr joint( it->second );
1810 joint->Disconnect( GetEventThreadServices() );
1817 #endif // DYNAMICS_SUPPORT
1819 void Actor::SetOverlay( bool enable )
1821 // Setting STENCIL will override OVERLAY
1822 if( DrawMode::STENCIL != mDrawMode )
1824 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1828 bool Actor::IsOverlay() const
1830 return ( DrawMode::OVERLAY == mDrawMode );
1833 void Actor::SetDrawMode( DrawMode::Type drawMode )
1835 // this flag is not animatable so keep the value
1836 mDrawMode = drawMode;
1839 // mNode is being used in a separate thread; queue a message to set the value
1840 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1844 DrawMode::Type Actor::GetDrawMode() const
1849 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1851 // only valid when on-stage
1854 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1856 Vector2 converted( screenX, screenY );
1858 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1859 const int taskCount = taskList.GetTaskCount();
1860 for( int i = taskCount - 1; i >= 0; --i )
1862 Dali::RenderTask task = taskList.GetTask( i );
1863 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1865 // found a task where this conversion was ok so return
1873 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1875 bool retval = false;
1876 // only valid when on-stage
1879 CameraActor* camera = renderTask.GetCameraActor();
1883 renderTask.GetViewport( viewport );
1885 // need to translate coordinates to render tasks coordinate space
1886 Vector2 converted( screenX, screenY );
1887 if( renderTask.TranslateCoordinates( converted ) )
1889 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1896 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1898 // Early-out if mNode is NULL
1904 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1906 // Calculate the ModelView matrix
1907 Matrix modelView( false/*don't init*/);
1908 // need to use the components as world matrix is only updated for actors that need it
1909 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1910 Matrix::Multiply( modelView, modelView, viewMatrix );
1912 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1913 Matrix invertedMvp( false/*don't init*/);
1914 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1915 bool success = invertedMvp.Invert();
1917 // Convert to GL coordinates
1918 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1923 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1930 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1936 if( XyPlaneIntersect( nearPos, farPos, local ) )
1938 Vector3 size = GetCurrentSize();
1939 localX = local.x + size.x * 0.5f;
1940 localY = local.y + size.y * 0.5f;
1951 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1954 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1956 Mathematical Formulation
1958 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1960 ( p - c ) dot ( p - c ) = r^2
1962 Given a ray with a point of origin 'o', and a direction vector 'd':
1964 ray(t) = o + td, t >= 0
1966 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1968 (o + td - c ) dot ( o + td - c ) = r^2
1970 To solve for t we first expand the above into a more recognisable quadratic equation form
1972 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1981 B = 2( o - c ) dot d
1982 C = ( o - c ) dot ( o - c ) - r^2
1984 which can be solved using a standard quadratic formula.
1986 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1988 Practical Simplification
1990 In a renderer, we often differentiate between world space and object space. In the object space
1991 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1992 into object space, the mathematical solution presented above can be simplified significantly.
1994 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1998 and we can find the t at which the (transformed) ray intersects the sphere by
2000 ( o + td ) dot ( o + td ) = r^2
2002 According to the reasoning above, we expand the above quadratic equation into the general form
2006 which now has coefficients:
2013 // Early out if mNode is NULL
2019 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2021 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2022 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2023 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2025 // Compute the radius is not needed, square radius it's enough.
2026 const Vector3& size( mNode->GetSize( bufferIndex ) );
2028 // Scale the sphere.
2029 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2031 const float width = size.width * scale.width;
2032 const float height = size.height * scale.height;
2034 float squareSphereRadius = 0.5f * ( width * width + height * height );
2036 float a = rayDir.Dot( rayDir ); // a
2037 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2038 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2040 return ( b2 * b2 - a * c ) >= 0.f;
2043 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2050 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2052 // Transforms the ray to the local reference system.
2054 // Calculate the inverse of Model matrix
2055 Matrix invModelMatrix( false/*don't init*/);
2056 // need to use the components as world matrix is only updated for actors that need it
2057 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2059 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2060 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2062 // Test with the actor's XY plane (Normal = 0 0 1 1).
2064 float a = -rayOriginLocal.z;
2065 float b = rayDirLocal.z;
2067 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2069 // Ray travels distance * rayDirLocal to intersect with plane.
2072 const Vector3& size = mNode->GetSize( bufferIndex );
2074 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2075 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2077 // Test with the actor's geometry.
2078 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2085 void Actor::SetLeaveRequired( bool required )
2087 mLeaveRequired = required;
2090 bool Actor::GetLeaveRequired() const
2092 return mLeaveRequired;
2095 void Actor::SetKeyboardFocusable( bool focusable )
2097 mKeyboardFocusable = focusable;
2100 bool Actor::IsKeyboardFocusable() const
2102 return mKeyboardFocusable;
2105 bool Actor::GetTouchRequired() const
2107 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2110 bool Actor::GetHoverRequired() const
2112 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2115 bool Actor::GetMouseWheelEventRequired() const
2117 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2120 bool Actor::IsHittable() const
2122 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2125 ActorGestureData& Actor::GetGestureData()
2127 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2128 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2129 if( NULL == mGestureData )
2131 mGestureData = new ActorGestureData;
2133 return *mGestureData;
2136 bool Actor::IsGestureRequred( Gesture::Type type ) const
2138 return mGestureData && mGestureData->IsGestureRequred( type );
2141 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2143 bool consumed = false;
2145 if( !mTouchedSignal.Empty() )
2147 Dali::Actor handle( this );
2148 consumed = mTouchedSignal.Emit( handle, event );
2153 // Notification for derived classes
2154 consumed = OnTouchEvent( event );
2160 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2162 bool consumed = false;
2164 if( !mHoveredSignal.Empty() )
2166 Dali::Actor handle( this );
2167 consumed = mHoveredSignal.Emit( handle, event );
2172 // Notification for derived classes
2173 consumed = OnHoverEvent( event );
2179 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2181 bool consumed = false;
2183 if( !mMouseWheelEventSignal.Empty() )
2185 Dali::Actor handle( this );
2186 consumed = mMouseWheelEventSignal.Emit( handle, event );
2191 // Notification for derived classes
2192 consumed = OnMouseWheelEvent( event );
2198 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2200 return mTouchedSignal;
2203 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2205 return mHoveredSignal;
2208 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2210 return mMouseWheelEventSignal;
2213 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2215 return mOnStageSignal;
2218 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2220 return mOffStageSignal;
2223 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2225 return mOnRelayoutSignal;
2228 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2230 bool connected( true );
2231 Actor* actor = dynamic_cast< Actor* >( object );
2233 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2235 actor->TouchedSignal().Connect( tracker, functor );
2237 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2239 actor->HoveredSignal().Connect( tracker, functor );
2241 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2243 actor->MouseWheelEventSignal().Connect( tracker, functor );
2245 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2247 actor->OnStageSignal().Connect( tracker, functor );
2249 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2251 actor->OffStageSignal().Connect( tracker, functor );
2255 // signalName does not match any signal
2262 Actor::Actor( DerivedType derivedType )
2266 mParentOrigin( NULL ),
2267 mAnchorPoint( NULL ),
2268 mRelayoutData( NULL ),
2269 #ifdef DYNAMICS_SUPPORT
2270 mDynamicsData( NULL ),
2272 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
2273 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 )
2277 void Actor::Initialize()
2280 SceneGraph::Node* node = CreateNode();
2282 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2283 mNode = node; // Keep raw-pointer to Node
2287 GetEventThreadServices().RegisterObject( this );
2292 // Remove mParent pointers from children even if we're destroying core,
2293 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2296 ActorConstIter endIter = mChildren->end();
2297 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2299 Actor& actor = GetImplementation( *iter );
2300 actor.SetParent( NULL );
2305 // Guard to allow handle destruction after Core has been destroyed
2306 if( EventThreadServices::IsCoreRunning() )
2310 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2311 mNode = NULL; // Node is about to be destroyed
2314 GetEventThreadServices().UnregisterObject( this );
2317 #ifdef DYNAMICS_SUPPORT
2319 delete mDynamicsData;
2322 // Cleanup optional gesture data
2323 delete mGestureData;
2325 // Cleanup optional parent origin and anchor
2326 delete mParentOrigin;
2327 delete mAnchorPoint;
2329 // Delete optional relayout data
2332 delete mRelayoutData;
2336 void Actor::ConnectToStage( int index )
2338 // This container is used instead of walking the Actor hierachy.
2339 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2340 ActorContainer connectionList;
2342 // This stage is atomic i.e. not interrupted by user callbacks
2343 RecursiveConnectToStage( connectionList, index );
2345 // Notify applications about the newly connected actors.
2346 const ActorIter endIter = connectionList.end();
2347 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2349 Actor& actor = GetImplementation( *iter );
2350 actor.NotifyStageConnection();
2356 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2358 DALI_ASSERT_ALWAYS( !OnStage() );
2362 ConnectToSceneGraph( index );
2364 // Notification for internal derived classes
2365 OnStageConnectionInternal();
2367 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2368 connectionList.push_back( Dali::Actor( this ) );
2370 // Recursively connect children
2373 ActorConstIter endIter = mChildren->end();
2374 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2376 Actor& actor = GetImplementation( *iter );
2377 actor.RecursiveConnectToStage( connectionList );
2383 * This method is called when the Actor is connected to the Stage.
2384 * The parent must have added its Node to the scene-graph.
2385 * The child must connect its Node to the parent's Node.
2386 * This is resursive; the child calls ConnectToStage() for its children.
2388 void Actor::ConnectToSceneGraph( int index )
2390 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2394 // Reparent Node in next Update
2395 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2398 // Notify attachment
2401 mAttachment->Connect();
2404 #ifdef DYNAMICS_SUPPORT
2406 if( NULL != mDynamicsData )
2412 // Request relayout on all actors that are added to the scenegraph
2415 // Notification for Object::Observers
2419 void Actor::NotifyStageConnection()
2421 // Actors can be removed (in a callback), before the on-stage stage is reported.
2422 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2423 if( OnStage() && !mOnStageSignalled )
2425 // Notification for external (CustomActor) derived classes
2426 OnStageConnectionExternal();
2428 if( !mOnStageSignal.Empty() )
2430 Dali::Actor handle( this );
2431 mOnStageSignal.Emit( handle );
2434 // Guard against Remove during callbacks
2437 mOnStageSignalled = true; // signal required next time Actor is removed
2442 void Actor::DisconnectFromStage()
2444 // This container is used instead of walking the Actor hierachy.
2445 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2446 ActorContainer disconnectionList;
2448 // This stage is atomic i.e. not interrupted by user callbacks
2449 RecursiveDisconnectFromStage( disconnectionList );
2451 // Notify applications about the newly disconnected actors.
2452 const ActorIter endIter = disconnectionList.end();
2453 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2455 Actor& actor = GetImplementation( *iter );
2456 actor.NotifyStageDisconnection();
2460 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2462 DALI_ASSERT_ALWAYS( OnStage() );
2464 // Recursively disconnect children
2467 ActorConstIter endIter = mChildren->end();
2468 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2470 Actor& actor = GetImplementation( *iter );
2471 actor.RecursiveDisconnectFromStage( disconnectionList );
2475 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2476 disconnectionList.push_back( Dali::Actor( this ) );
2478 // Notification for internal derived classes
2479 OnStageDisconnectionInternal();
2481 DisconnectFromSceneGraph();
2487 * This method is called by an actor or its parent, before a node removal message is sent.
2488 * This is recursive; the child calls DisconnectFromStage() for its children.
2490 void Actor::DisconnectFromSceneGraph()
2492 // Notification for Object::Observers
2493 OnSceneObjectRemove();
2495 // Notify attachment
2498 mAttachment->Disconnect();
2501 #ifdef DYNAMICS_SUPPORT
2503 if( NULL != mDynamicsData )
2505 DisconnectDynamics();
2510 void Actor::NotifyStageDisconnection()
2512 // Actors can be added (in a callback), before the off-stage state is reported.
2513 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2514 // only do this step if there is a stage, i.e. Core is not being shut down
2515 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2517 // Notification for external (CustomeActor) derived classes
2518 OnStageDisconnectionExternal();
2520 if( !mOffStageSignal.Empty() )
2522 Dali::Actor handle( this );
2523 mOffStageSignal.Emit( handle );
2526 // Guard against Add during callbacks
2529 mOnStageSignalled = false; // signal required next time Actor is added
2534 bool Actor::IsNodeConnected() const
2536 bool connected( false );
2541 if( mNode->IsRoot() || mNode->GetParent() )
2550 unsigned int Actor::GetDefaultPropertyCount() const
2552 return DEFAULT_PROPERTY_COUNT;
2555 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2557 indices.reserve( DEFAULT_PROPERTY_COUNT );
2559 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2561 indices.push_back( i );
2565 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2567 if( index < DEFAULT_PROPERTY_COUNT )
2569 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2575 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2577 Property::Index index = Property::INVALID_INDEX;
2579 // Look for name in default properties
2580 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2582 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2583 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2593 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2595 if( index < DEFAULT_PROPERTY_COUNT )
2597 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2603 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2605 if( index < DEFAULT_PROPERTY_COUNT )
2607 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2613 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2615 if( index < DEFAULT_PROPERTY_COUNT )
2617 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2623 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2625 if( index < DEFAULT_PROPERTY_COUNT )
2627 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2630 // index out of range...return Property::NONE
2631 return Property::NONE;
2634 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2638 case Dali::Actor::Property::PARENT_ORIGIN:
2640 SetParentOrigin( property.Get< Vector3 >() );
2644 case Dali::Actor::Property::PARENT_ORIGIN_X:
2646 SetParentOriginX( property.Get< float >() );
2650 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2652 SetParentOriginY( property.Get< float >() );
2656 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2658 SetParentOriginZ( property.Get< float >() );
2662 case Dali::Actor::Property::ANCHOR_POINT:
2664 SetAnchorPoint( property.Get< Vector3 >() );
2668 case Dali::Actor::Property::ANCHOR_POINT_X:
2670 SetAnchorPointX( property.Get< float >() );
2674 case Dali::Actor::Property::ANCHOR_POINT_Y:
2676 SetAnchorPointY( property.Get< float >() );
2680 case Dali::Actor::Property::ANCHOR_POINT_Z:
2682 SetAnchorPointZ( property.Get< float >() );
2686 case Dali::Actor::Property::SIZE:
2688 SetSize( property.Get< Vector3 >() );
2692 case Dali::Actor::Property::SIZE_WIDTH:
2694 SetWidth( property.Get< float >() );
2698 case Dali::Actor::Property::SIZE_HEIGHT:
2700 SetHeight( property.Get< float >() );
2704 case Dali::Actor::Property::SIZE_DEPTH:
2706 SetDepth( property.Get< float >() );
2710 case Dali::Actor::Property::POSITION:
2712 SetPosition( property.Get< Vector3 >() );
2716 case Dali::Actor::Property::POSITION_X:
2718 SetX( property.Get< float >() );
2722 case Dali::Actor::Property::POSITION_Y:
2724 SetY( property.Get< float >() );
2728 case Dali::Actor::Property::POSITION_Z:
2730 SetZ( property.Get< float >() );
2734 case Dali::Actor::Property::ORIENTATION:
2736 SetOrientation( property.Get< Quaternion >() );
2740 case Dali::Actor::Property::SCALE:
2742 SetScale( property.Get< Vector3 >() );
2746 case Dali::Actor::Property::SCALE_X:
2748 SetScaleX( property.Get< float >() );
2752 case Dali::Actor::Property::SCALE_Y:
2754 SetScaleY( property.Get< float >() );
2758 case Dali::Actor::Property::SCALE_Z:
2760 SetScaleZ( property.Get< float >() );
2764 case Dali::Actor::Property::VISIBLE:
2766 SetVisible( property.Get< bool >() );
2770 case Dali::Actor::Property::COLOR:
2772 SetColor( property.Get< Vector4 >() );
2776 case Dali::Actor::Property::COLOR_RED:
2778 SetColorRed( property.Get< float >() );
2782 case Dali::Actor::Property::COLOR_GREEN:
2784 SetColorGreen( property.Get< float >() );
2788 case Dali::Actor::Property::COLOR_BLUE:
2790 SetColorBlue( property.Get< float >() );
2794 case Dali::Actor::Property::COLOR_ALPHA:
2796 SetOpacity( property.Get< float >() );
2800 case Dali::Actor::Property::NAME:
2802 SetName( property.Get< std::string >() );
2806 case Dali::Actor::Property::SENSITIVE:
2808 SetSensitive( property.Get< bool >() );
2812 case Dali::Actor::Property::LEAVE_REQUIRED:
2814 SetLeaveRequired( property.Get< bool >() );
2818 case Dali::Actor::Property::INHERIT_ORIENTATION:
2820 SetInheritOrientation( property.Get< bool >() );
2824 case Dali::Actor::Property::INHERIT_SCALE:
2826 SetInheritScale( property.Get< bool >() );
2830 case Dali::Actor::Property::COLOR_MODE:
2832 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2836 case Dali::Actor::Property::POSITION_INHERITANCE:
2838 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2842 case Dali::Actor::Property::DRAW_MODE:
2844 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2848 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2850 SetSizeModeFactor( property.Get< Vector3 >() );
2854 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2856 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2860 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2862 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2866 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2868 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2872 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2874 if( property.Get< bool >() )
2876 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2881 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2883 if( property.Get< bool >() )
2885 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2890 case Dali::Actor::Property::PADDING:
2892 Vector4 padding = property.Get< Vector4 >();
2893 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2894 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2898 case Dali::Actor::Property::MINIMUM_SIZE:
2900 Vector2 size = property.Get< Vector2 >();
2901 SetMinimumSize( size.x, Dimension::WIDTH );
2902 SetMinimumSize( size.y, Dimension::HEIGHT );
2906 case Dali::Actor::Property::MAXIMUM_SIZE:
2908 Vector2 size = property.Get< Vector2 >();
2909 SetMaximumSize( size.x, Dimension::WIDTH );
2910 SetMaximumSize( size.y, Dimension::HEIGHT );
2916 // this can happen in the case of a non-animatable default property so just do nothing
2922 // TODO: This method needs to be removed
2923 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2925 switch( entry.type )
2927 case Property::BOOLEAN:
2929 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2930 DALI_ASSERT_DEBUG( NULL != property );
2932 // property is being used in a separate thread; queue a message to set the property
2933 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2938 case Property::INTEGER:
2940 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2941 DALI_ASSERT_DEBUG( NULL != property );
2943 // property is being used in a separate thread; queue a message to set the property
2944 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2949 case Property::UNSIGNED_INTEGER:
2951 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2952 DALI_ASSERT_DEBUG( NULL != property );
2954 // property is being used in a separate thread; queue a message to set the property
2955 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2960 case Property::FLOAT:
2962 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2963 DALI_ASSERT_DEBUG( NULL != property );
2965 // property is being used in a separate thread; queue a message to set the property
2966 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2971 case Property::VECTOR2:
2973 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2974 DALI_ASSERT_DEBUG( NULL != property );
2976 // property is being used in a separate thread; queue a message to set the property
2977 if(entry.componentIndex == 0)
2979 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2981 else if(entry.componentIndex == 1)
2983 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2987 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2993 case Property::VECTOR3:
2995 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2996 DALI_ASSERT_DEBUG( NULL != property );
2998 // property is being used in a separate thread; queue a message to set the property
2999 if(entry.componentIndex == 0)
3001 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3003 else if(entry.componentIndex == 1)
3005 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3007 else if(entry.componentIndex == 2)
3009 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3013 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3019 case Property::VECTOR4:
3021 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3022 DALI_ASSERT_DEBUG( NULL != property );
3024 // property is being used in a separate thread; queue a message to set the property
3025 if(entry.componentIndex == 0)
3027 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3029 else if(entry.componentIndex == 1)
3031 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3033 else if(entry.componentIndex == 2)
3035 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3037 else if(entry.componentIndex == 3)
3039 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3043 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3049 case Property::ROTATION:
3051 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3052 DALI_ASSERT_DEBUG( NULL != property );
3054 // property is being used in a separate thread; queue a message to set the property
3055 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3060 case Property::MATRIX:
3062 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3063 DALI_ASSERT_DEBUG( NULL != property );
3065 // property is being used in a separate thread; queue a message to set the property
3066 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3071 case Property::MATRIX3:
3073 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3074 DALI_ASSERT_DEBUG( NULL != property );
3076 // property is being used in a separate thread; queue a message to set the property
3077 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3084 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3090 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3092 Property::Value value;
3096 case Dali::Actor::Property::PARENT_ORIGIN:
3098 value = GetCurrentParentOrigin();
3102 case Dali::Actor::Property::PARENT_ORIGIN_X:
3104 value = GetCurrentParentOrigin().x;
3108 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3110 value = GetCurrentParentOrigin().y;
3114 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3116 value = GetCurrentParentOrigin().z;
3120 case Dali::Actor::Property::ANCHOR_POINT:
3122 value = GetCurrentAnchorPoint();
3126 case Dali::Actor::Property::ANCHOR_POINT_X:
3128 value = GetCurrentAnchorPoint().x;
3132 case Dali::Actor::Property::ANCHOR_POINT_Y:
3134 value = GetCurrentAnchorPoint().y;
3138 case Dali::Actor::Property::ANCHOR_POINT_Z:
3140 value = GetCurrentAnchorPoint().z;
3144 case Dali::Actor::Property::SIZE:
3146 value = GetCurrentSize();
3150 case Dali::Actor::Property::SIZE_WIDTH:
3152 value = GetCurrentSize().width;
3156 case Dali::Actor::Property::SIZE_HEIGHT:
3158 value = GetCurrentSize().height;
3162 case Dali::Actor::Property::SIZE_DEPTH:
3164 value = GetCurrentSize().depth;
3168 case Dali::Actor::Property::POSITION:
3170 value = GetCurrentPosition();
3174 case Dali::Actor::Property::POSITION_X:
3176 value = GetCurrentPosition().x;
3180 case Dali::Actor::Property::POSITION_Y:
3182 value = GetCurrentPosition().y;
3186 case Dali::Actor::Property::POSITION_Z:
3188 value = GetCurrentPosition().z;
3192 case Dali::Actor::Property::WORLD_POSITION:
3194 value = GetCurrentWorldPosition();
3198 case Dali::Actor::Property::WORLD_POSITION_X:
3200 value = GetCurrentWorldPosition().x;
3204 case Dali::Actor::Property::WORLD_POSITION_Y:
3206 value = GetCurrentWorldPosition().y;
3210 case Dali::Actor::Property::WORLD_POSITION_Z:
3212 value = GetCurrentWorldPosition().z;
3216 case Dali::Actor::Property::ORIENTATION:
3218 value = GetCurrentOrientation();
3222 case Dali::Actor::Property::WORLD_ORIENTATION:
3224 value = GetCurrentWorldOrientation();
3228 case Dali::Actor::Property::SCALE:
3230 value = GetCurrentScale();
3234 case Dali::Actor::Property::SCALE_X:
3236 value = GetCurrentScale().x;
3240 case Dali::Actor::Property::SCALE_Y:
3242 value = GetCurrentScale().y;
3246 case Dali::Actor::Property::SCALE_Z:
3248 value = GetCurrentScale().z;
3252 case Dali::Actor::Property::WORLD_SCALE:
3254 value = GetCurrentWorldScale();
3258 case Dali::Actor::Property::VISIBLE:
3260 value = IsVisible();
3264 case Dali::Actor::Property::COLOR:
3266 value = GetCurrentColor();
3270 case Dali::Actor::Property::COLOR_RED:
3272 value = GetCurrentColor().r;
3276 case Dali::Actor::Property::COLOR_GREEN:
3278 value = GetCurrentColor().g;
3282 case Dali::Actor::Property::COLOR_BLUE:
3284 value = GetCurrentColor().b;
3288 case Dali::Actor::Property::COLOR_ALPHA:
3290 value = GetCurrentColor().a;
3294 case Dali::Actor::Property::WORLD_COLOR:
3296 value = GetCurrentWorldColor();
3300 case Dali::Actor::Property::WORLD_MATRIX:
3302 value = GetCurrentWorldMatrix();
3306 case Dali::Actor::Property::NAME:
3312 case Dali::Actor::Property::SENSITIVE:
3314 value = IsSensitive();
3318 case Dali::Actor::Property::LEAVE_REQUIRED:
3320 value = GetLeaveRequired();
3324 case Dali::Actor::Property::INHERIT_ORIENTATION:
3326 value = IsOrientationInherited();
3330 case Dali::Actor::Property::INHERIT_SCALE:
3332 value = IsScaleInherited();
3336 case Dali::Actor::Property::COLOR_MODE:
3338 value = Scripting::GetColorMode( GetColorMode() );
3342 case Dali::Actor::Property::POSITION_INHERITANCE:
3344 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3348 case Dali::Actor::Property::DRAW_MODE:
3350 value = Scripting::GetDrawMode( GetDrawMode() );
3354 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3356 value = GetSizeModeFactor();
3360 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3362 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3366 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3368 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3372 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3374 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3378 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3380 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3384 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3386 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3390 case Dali::Actor::Property::PADDING:
3392 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3393 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3394 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3398 case Dali::Actor::Property::MINIMUM_SIZE:
3400 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3404 case Dali::Actor::Property::MAXIMUM_SIZE:
3406 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3412 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3420 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3425 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3427 // This method should only return an object connected to the scene-graph
3428 return OnStage() ? mNode : NULL;
3431 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3433 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3435 const PropertyBase* property( NULL );
3437 // This method should only return a property of an object connected to the scene-graph
3443 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3445 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3446 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3448 property = animatable->GetSceneGraphProperty();
3450 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3452 CustomPropertyMetadata* custom = FindCustomProperty( index );
3453 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3455 property = custom->GetSceneGraphProperty();
3457 else if( NULL != mNode )
3461 case Dali::Actor::Property::SIZE:
3462 property = &mNode->mSize;
3465 case Dali::Actor::Property::SIZE_WIDTH:
3466 property = &mNode->mSize;
3469 case Dali::Actor::Property::SIZE_HEIGHT:
3470 property = &mNode->mSize;
3473 case Dali::Actor::Property::SIZE_DEPTH:
3474 property = &mNode->mSize;
3477 case Dali::Actor::Property::POSITION:
3478 property = &mNode->mPosition;
3481 case Dali::Actor::Property::POSITION_X:
3482 property = &mNode->mPosition;
3485 case Dali::Actor::Property::POSITION_Y:
3486 property = &mNode->mPosition;
3489 case Dali::Actor::Property::POSITION_Z:
3490 property = &mNode->mPosition;
3493 case Dali::Actor::Property::ORIENTATION:
3494 property = &mNode->mOrientation;
3497 case Dali::Actor::Property::SCALE:
3498 property = &mNode->mScale;
3501 case Dali::Actor::Property::SCALE_X:
3502 property = &mNode->mScale;
3505 case Dali::Actor::Property::SCALE_Y:
3506 property = &mNode->mScale;
3509 case Dali::Actor::Property::SCALE_Z:
3510 property = &mNode->mScale;
3513 case Dali::Actor::Property::VISIBLE:
3514 property = &mNode->mVisible;
3517 case Dali::Actor::Property::COLOR:
3518 property = &mNode->mColor;
3521 case Dali::Actor::Property::COLOR_RED:
3522 property = &mNode->mColor;
3525 case Dali::Actor::Property::COLOR_GREEN:
3526 property = &mNode->mColor;
3529 case Dali::Actor::Property::COLOR_BLUE:
3530 property = &mNode->mColor;
3533 case Dali::Actor::Property::COLOR_ALPHA:
3534 property = &mNode->mColor;
3545 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3547 const PropertyInputImpl* property( NULL );
3549 // This method should only return a property of an object connected to the scene-graph
3555 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3557 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3558 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3560 property = animatable->GetSceneGraphProperty();
3562 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3564 CustomPropertyMetadata* custom = FindCustomProperty( index );
3565 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3566 property = custom->GetSceneGraphProperty();
3568 else if( NULL != mNode )
3572 case Dali::Actor::Property::PARENT_ORIGIN:
3573 property = &mNode->mParentOrigin;
3576 case Dali::Actor::Property::PARENT_ORIGIN_X:
3577 property = &mNode->mParentOrigin;
3580 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3581 property = &mNode->mParentOrigin;
3584 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3585 property = &mNode->mParentOrigin;
3588 case Dali::Actor::Property::ANCHOR_POINT:
3589 property = &mNode->mAnchorPoint;
3592 case Dali::Actor::Property::ANCHOR_POINT_X:
3593 property = &mNode->mAnchorPoint;
3596 case Dali::Actor::Property::ANCHOR_POINT_Y:
3597 property = &mNode->mAnchorPoint;
3600 case Dali::Actor::Property::ANCHOR_POINT_Z:
3601 property = &mNode->mAnchorPoint;
3604 case Dali::Actor::Property::SIZE:
3605 property = &mNode->mSize;
3608 case Dali::Actor::Property::SIZE_WIDTH:
3609 property = &mNode->mSize;
3612 case Dali::Actor::Property::SIZE_HEIGHT:
3613 property = &mNode->mSize;
3616 case Dali::Actor::Property::SIZE_DEPTH:
3617 property = &mNode->mSize;
3620 case Dali::Actor::Property::POSITION:
3621 property = &mNode->mPosition;
3624 case Dali::Actor::Property::POSITION_X:
3625 property = &mNode->mPosition;
3628 case Dali::Actor::Property::POSITION_Y:
3629 property = &mNode->mPosition;
3632 case Dali::Actor::Property::POSITION_Z:
3633 property = &mNode->mPosition;
3636 case Dali::Actor::Property::WORLD_POSITION:
3637 property = &mNode->mWorldPosition;
3640 case Dali::Actor::Property::WORLD_POSITION_X:
3641 property = &mNode->mWorldPosition;
3644 case Dali::Actor::Property::WORLD_POSITION_Y:
3645 property = &mNode->mWorldPosition;
3648 case Dali::Actor::Property::WORLD_POSITION_Z:
3649 property = &mNode->mWorldPosition;
3652 case Dali::Actor::Property::ORIENTATION:
3653 property = &mNode->mOrientation;
3656 case Dali::Actor::Property::WORLD_ORIENTATION:
3657 property = &mNode->mWorldOrientation;
3660 case Dali::Actor::Property::SCALE:
3661 property = &mNode->mScale;
3664 case Dali::Actor::Property::SCALE_X:
3665 property = &mNode->mScale;
3668 case Dali::Actor::Property::SCALE_Y:
3669 property = &mNode->mScale;
3672 case Dali::Actor::Property::SCALE_Z:
3673 property = &mNode->mScale;
3676 case Dali::Actor::Property::WORLD_SCALE:
3677 property = &mNode->mWorldScale;
3680 case Dali::Actor::Property::VISIBLE:
3681 property = &mNode->mVisible;
3684 case Dali::Actor::Property::COLOR:
3685 property = &mNode->mColor;
3688 case Dali::Actor::Property::COLOR_RED:
3689 property = &mNode->mColor;
3692 case Dali::Actor::Property::COLOR_GREEN:
3693 property = &mNode->mColor;
3696 case Dali::Actor::Property::COLOR_BLUE:
3697 property = &mNode->mColor;
3700 case Dali::Actor::Property::COLOR_ALPHA:
3701 property = &mNode->mColor;
3704 case Dali::Actor::Property::WORLD_COLOR:
3705 property = &mNode->mWorldColor;
3708 case Dali::Actor::Property::WORLD_MATRIX:
3709 property = &mNode->mWorldMatrix;
3720 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3722 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3724 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3726 // check whether the animatable property is registered already, if not then register one.
3727 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3728 if( animatableProperty )
3730 componentIndex = animatableProperty->componentIndex;
3737 case Dali::Actor::Property::PARENT_ORIGIN_X:
3738 case Dali::Actor::Property::ANCHOR_POINT_X:
3739 case Dali::Actor::Property::SIZE_WIDTH:
3740 case Dali::Actor::Property::POSITION_X:
3741 case Dali::Actor::Property::WORLD_POSITION_X:
3742 case Dali::Actor::Property::SCALE_X:
3743 case Dali::Actor::Property::COLOR_RED:
3749 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3750 case Dali::Actor::Property::ANCHOR_POINT_Y:
3751 case Dali::Actor::Property::SIZE_HEIGHT:
3752 case Dali::Actor::Property::POSITION_Y:
3753 case Dali::Actor::Property::WORLD_POSITION_Y:
3754 case Dali::Actor::Property::SCALE_Y:
3755 case Dali::Actor::Property::COLOR_GREEN:
3761 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3762 case Dali::Actor::Property::ANCHOR_POINT_Z:
3763 case Dali::Actor::Property::SIZE_DEPTH:
3764 case Dali::Actor::Property::POSITION_Z:
3765 case Dali::Actor::Property::WORLD_POSITION_Z:
3766 case Dali::Actor::Property::SCALE_Z:
3767 case Dali::Actor::Property::COLOR_BLUE:
3773 case Dali::Actor::Property::COLOR_ALPHA:
3787 return componentIndex;
3790 void Actor::SetParent( Actor* parent, int index )
3794 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3798 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3801 // Instruct each actor to create a corresponding node in the scene graph
3802 ConnectToStage( index );
3805 else // parent being set to NULL
3807 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3811 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3814 DALI_ASSERT_ALWAYS( mNode != NULL );
3818 // Disconnect the Node & its children from the scene-graph.
3819 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3822 // Instruct each actor to discard pointers to the scene-graph
3823 DisconnectFromStage();
3828 SceneGraph::Node* Actor::CreateNode() const
3833 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3836 Actor* actor = dynamic_cast< Actor* >( object );
3840 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3842 actor->SetVisible( true );
3845 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3847 actor->SetVisible( false );
3855 void Actor::EnsureRelayoutData() const
3857 // Assign relayout data.
3858 if( !mRelayoutData )
3860 mRelayoutData = new RelayoutData();
3864 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3866 // Check if actor is dependent on parent
3867 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3869 if( ( dimension & ( 1 << i ) ) )
3871 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3872 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3882 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3884 // Check if actor is dependent on children
3885 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3887 if( ( dimension & ( 1 << i ) ) )
3889 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3890 switch( resizePolicy )
3892 case ResizePolicy::FIT_TO_CHILDREN:
3893 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3909 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3911 return Actor::RelayoutDependentOnChildren( dimension );
3914 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3916 // Check each possible dimension and see if it is dependent on the input one
3917 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3919 if( dimension & ( 1 << i ) )
3921 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3928 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3930 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3932 if( dimension & ( 1 << i ) )
3934 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3939 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3941 // If more than one dimension is requested, just return the first one found
3942 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3944 if( ( dimension & ( 1 << i ) ) )
3946 return mRelayoutData->negotiatedDimensions[ i ];
3950 return 0.0f; // Default
3953 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3955 EnsureRelayoutData();
3957 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3959 if( dimension & ( 1 << i ) )
3961 mRelayoutData->dimensionPadding[ i ] = padding;
3966 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3968 EnsureRelayoutData();
3970 // If more than one dimension is requested, just return the first one found
3971 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3973 if( ( dimension & ( 1 << i ) ) )
3975 return mRelayoutData->dimensionPadding[ i ];
3979 return Vector2( 0.0f, 0.0f ); // Default
3982 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3984 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3986 if( dimension & ( 1 << i ) )
3988 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3993 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3995 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3997 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4006 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4008 // Could be overridden in derived classes.
4009 return CalculateChildSizeBase( child, dimension );
4012 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4014 // Fill to parent, taking size mode factor into account
4015 switch( child.GetResizePolicy( dimension ) )
4017 case ResizePolicy::FILL_TO_PARENT:
4019 return GetLatestSize( dimension );
4022 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4024 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4027 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4029 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4034 return GetLatestSize( dimension );
4039 float Actor::GetHeightForWidth( float width )
4041 // Could be overridden in derived classes.
4042 float height = 0.0f;
4044 const Vector3 naturalSize = GetNaturalSize();
4045 if( naturalSize.width > 0.0f )
4047 height = naturalSize.height * width / naturalSize.width;
4053 float Actor::GetWidthForHeight( float height )
4055 // Could be overridden in derived classes.
4058 const Vector3 naturalSize = GetNaturalSize();
4059 if( naturalSize.height > 0.0f )
4061 width = naturalSize.width * height / naturalSize.height;
4067 float Actor::GetLatestSize( Dimension::Type dimension ) const
4069 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4072 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4074 Vector2 padding = GetPadding( dimension );
4076 return GetLatestSize( dimension ) + padding.x + padding.y;
4079 float Actor::NegotiateFromParent( Dimension::Type dimension )
4081 Actor* parent = GetParent();
4084 Vector2 padding( GetPadding( dimension ) );
4085 Vector2 parentPadding( parent->GetPadding( dimension ) );
4086 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4092 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4094 float maxDimensionPoint = 0.0f;
4096 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4098 Dali::Actor child = GetChildAt( i );
4099 Actor& childImpl = GetImplementation( child );
4101 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4103 // Calculate the min and max points that the children range across
4104 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4105 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4106 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4110 return maxDimensionPoint;
4113 float Actor::GetSize( Dimension::Type dimension ) const
4115 return GetDimensionValue( GetTargetSize(), dimension );
4118 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4120 return GetDimensionValue( GetNaturalSize(), dimension );
4123 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4125 switch( GetResizePolicy( dimension ) )
4127 case ResizePolicy::USE_NATURAL_SIZE:
4129 return GetNaturalSize( dimension );
4132 case ResizePolicy::FIXED:
4134 return GetDimensionValue( GetPreferredSize(), dimension );
4137 case ResizePolicy::USE_ASSIGNED_SIZE:
4139 return GetDimensionValue( maximumSize, dimension );
4142 case ResizePolicy::FILL_TO_PARENT:
4143 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4144 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4146 return NegotiateFromParent( dimension );
4149 case ResizePolicy::FIT_TO_CHILDREN:
4151 return NegotiateFromChildren( dimension );
4154 case ResizePolicy::DIMENSION_DEPENDENCY:
4156 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4159 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4161 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4164 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4166 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4178 return 0.0f; // Default
4181 float Actor::ClampDimension( float size, Dimension::Type dimension )
4183 const float minSize = GetMinimumSize( dimension );
4184 const float maxSize = GetMaximumSize( dimension );
4186 return std::max( minSize, std::min( size, maxSize ) );
4189 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4191 // Check if it needs to be negotiated
4192 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4194 // Check that we havn't gotten into an infinite loop
4195 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4196 bool recursionFound = false;
4197 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4199 if( *it == searchActor )
4201 recursionFound = true;
4206 if( !recursionFound )
4208 // Record the path that we have taken
4209 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4211 // Dimension dependency check
4212 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4214 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4216 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4218 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4222 // Parent dependency check
4223 Actor* parent = GetParent();
4224 if( parent && RelayoutDependentOnParent( dimension ) )
4226 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4229 // Children dependency check
4230 if( RelayoutDependentOnChildren( dimension ) )
4232 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4234 Dali::Actor child = GetChildAt( i );
4235 Actor& childImpl = GetImplementation( child );
4237 // Only relayout child first if it is not dependent on this actor
4238 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4240 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4245 // For deriving classes
4246 OnCalculateRelayoutSize( dimension );
4248 // All dependencies checked, calculate the size and set negotiated flag
4249 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4251 SetNegotiatedDimension( newSize, dimension );
4252 SetLayoutNegotiated( true, dimension );
4254 // For deriving classes
4255 OnLayoutNegotiated( newSize, dimension );
4257 // This actor has been successfully processed, pop it off the recursion stack
4258 recursionStack.pop_back();
4262 // TODO: Break infinite loop
4263 SetLayoutNegotiated( true, dimension );
4268 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4270 // Negotiate all dimensions that require it
4271 ActorDimensionStack recursionStack;
4273 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4275 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4278 NegotiateDimension( dimension, allocatedSize, recursionStack );
4282 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4284 switch( mRelayoutData->sizeSetPolicy )
4286 case SizeScalePolicy::USE_SIZE_SET:
4291 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4293 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
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( naturalSizeRatio * size.height, size.height );
4304 else if( naturalSizeRatio > sizeRatio )
4306 return Vector2( size.width, size.width / naturalSizeRatio );
4317 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4319 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4320 const Vector3 naturalSize = GetNaturalSize();
4321 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4323 const float sizeRatio = size.width / size.height;
4324 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4326 if( naturalSizeRatio < sizeRatio )
4328 return Vector2( size.width, size.width / naturalSizeRatio );
4330 else if( naturalSizeRatio > sizeRatio )
4332 return Vector2( naturalSizeRatio * size.height, size.height );
4350 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4352 // Do the set actor size
4353 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4355 // Adjust for size set policy
4356 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4358 // Lock the flag to stop recursive relayouts on set size
4359 mRelayoutData->insideRelayout = true;
4360 SetSize( negotiatedSize );
4361 mRelayoutData->insideRelayout = false;
4363 // Clear flags for all dimensions
4364 SetLayoutDirty( false );
4366 // Give deriving classes a chance to respond
4367 OnRelayout( negotiatedSize, container );
4369 if( !mOnRelayoutSignal.Empty() )
4371 Dali::Actor handle( this );
4372 mOnRelayoutSignal.Emit( handle );
4376 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4378 // Do the negotiation
4379 NegotiateDimensions( allocatedSize );
4381 // Set the actor size
4382 SetNegotiatedSize( container );
4384 // Negotiate down to children
4385 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4387 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4389 Dali::Actor child = GetChildAt( i );
4391 // Only relayout if required
4392 if( GetImplementation( child ).RelayoutRequired() )
4394 container.Add( child, newBounds );
4399 void Actor::RelayoutRequest( Dimension::Type dimension )
4401 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4402 if( relayoutController )
4404 Dali::Actor self( this );
4405 relayoutController->RequestRelayout( self, dimension );
4409 void Actor::PropagateRelayoutFlags()
4411 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4412 if( relayoutController )
4414 Dali::Actor self( this );
4415 relayoutController->PropagateFlags( self );
4419 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4423 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4427 void Actor::SetPreferredSize( const Vector2& size )
4429 EnsureRelayoutData();
4431 if( size.width > 0.0f )
4433 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4436 if( size.height > 0.0f )
4438 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4441 mRelayoutData->preferredSize = size;
4446 Vector2 Actor::GetPreferredSize() const
4448 EnsureRelayoutData();
4450 return mRelayoutData->preferredSize;
4453 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4455 EnsureRelayoutData();
4457 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4459 if( dimension & ( 1 << i ) )
4461 mRelayoutData->minimumSize[ i ] = size;
4468 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4470 EnsureRelayoutData();
4472 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4474 if( dimension & ( 1 << i ) )
4476 return mRelayoutData->minimumSize[ i ];
4480 return 0.0f; // Default
4483 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4485 EnsureRelayoutData();
4487 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4489 if( dimension & ( 1 << i ) )
4491 mRelayoutData->maximumSize[ i ] = size;
4498 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4500 EnsureRelayoutData();
4502 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4504 if( dimension & ( 1 << i ) )
4506 return mRelayoutData->maximumSize[ i ];
4510 return 0.0f; // Default
4513 } // namespace Internal